From a8243c3e0e164f9222380f5d00524ec8e56f8c91 Mon Sep 17 00:00:00 2001 From: dexyfex Date: Thu, 21 Sep 2017 20:33:05 +1000 Subject: [PATCH] R26_dev8 - First public commit --- .gitattributes | 63 + .gitignore | 243 + AboutForm.Designer.cs | 96 + AboutForm.cs | 25 + AboutForm.resx | 419 + App.config | 192 + BinarySearchForm.Designer.cs | 170 + BinarySearchForm.cs | 177 + BinarySearchForm.resx | 412 + BrowseForm.Designer.cs | 846 ++ BrowseForm.cs | 1295 ++ BrowseForm.resx | 418 + CodeWalker Explorer.bat | 1 + .../CodeWalker.WinForms.csproj | 109 + CodeWalker.WinForms/MenuStripFix.Designer.cs | 36 + CodeWalker.WinForms/MenuStripFix.cs | 49 + .../Properties/AssemblyInfo.cs | 36 + .../PropertyGridFix.Designer.cs | 36 + CodeWalker.WinForms/PropertyGridFix.cs | 26 + .../ReadOnlyPropertyGrid.Designer.cs | 36 + CodeWalker.WinForms/ReadOnlyPropertyGrid.cs | 70 + CodeWalker.WinForms/TextBoxFix.Designer.cs | 36 + CodeWalker.WinForms/TextBoxFix.cs | 38 + .../TextBoxScrollSyncFix.Designer.cs | 36 + CodeWalker.WinForms/TextBoxScrollSyncFix.cs | 48 + CodeWalker.WinForms/ToolStripFix.Designer.cs | 36 + CodeWalker.WinForms/ToolStripFix.cs | 48 + .../ToolStripSplitButtonFix.Designer.cs | 36 + .../ToolStripSplitButtonFix.cs | 56 + .../ToolStripSpringTextBox.Designer.cs | 36 + CodeWalker.WinForms/ToolStripSpringTextBox.cs | 79 + CodeWalker.WinForms/TreeViewFix.Designer.cs | 36 + CodeWalker.WinForms/TreeViewFix.cs | 40 + CodeWalker.csproj | 589 + CodeWalker.sln | 65 + ExploreForm.Designer.cs | 1074 ++ ExploreForm.cs | 2568 ++++ ExploreForm.resx | 855 ++ ExtractKeysForm.Designer.cs | 160 + ExtractKeysForm.cs | 145 + ExtractKeysForm.resx | 415 + ExtractRawForm.Designer.cs | 229 + ExtractRawForm.cs | 227 + ExtractRawForm.resx | 412 + ExtractScriptsForm.Designer.cs | 244 + ExtractScriptsForm.cs | 235 + ExtractScriptsForm.resx | 415 + ExtractShadersForm.Designer.cs | 221 + ExtractShadersForm.cs | 225 + ExtractShadersForm.resx | 412 + ExtractTexForm.Designer.cs | 236 + ExtractTexForm.cs | 276 + ExtractTexForm.resx | 412 + Forms/AwcForm.Designer.cs | 254 + Forms/AwcForm.cs | 196 + Forms/AwcForm.resx | 409 + Forms/FxcForm.Designer.cs | 379 + Forms/FxcForm.cs | 197 + Forms/FxcForm.resx | 448 + Forms/GxtForm.Designer.cs | 82 + Forms/GxtForm.cs | 79 + Forms/GxtForm.resx | 409 + Forms/HexForm.Designer.cs | 123 + Forms/HexForm.cs | 155 + Forms/HexForm.resx | 412 + Forms/MetaForm.Designer.cs | 371 + Forms/MetaForm.cs | 333 + Forms/MetaForm.resx | 471 + Forms/ModelForm.Designer.cs | 674 ++ Forms/ModelForm.cs | 2570 ++++ Forms/ModelForm.resx | 415 + Forms/RelForm.Designer.cs | 143 + Forms/RelForm.cs | 108 + Forms/RelForm.resx | 409 + Forms/TextForm.Designer.cs | 296 + Forms/TextForm.cs | 208 + Forms/TextForm.resx | 471 + Forms/XmlForm.Designer.cs | 297 + Forms/XmlForm.cs | 276 + Forms/XmlForm.resx | 471 + Forms/YtdForm.Designer.cs | 400 + Forms/YtdForm.cs | 196 + Forms/YtdForm.resx | 447 + Forms/YvrForm.Designer.cs | 82 + Forms/YvrForm.cs | 117 + Forms/YvrForm.resx | 409 + Forms/YwrForm.Designer.cs | 82 + Forms/YwrForm.cs | 94 + Forms/YwrForm.resx | 409 + GameFiles/FileTypes/AwcFile.cs | 702 ++ GameFiles/FileTypes/CacheDatFile.cs | 491 + GameFiles/FileTypes/CutFile.cs | 48 + GameFiles/FileTypes/DlcContentFile.cs | 431 + GameFiles/FileTypes/DlcSetupFile.cs | 82 + GameFiles/FileTypes/FxcFile.cs | 1074 ++ GameFiles/FileTypes/Gxt2File.cs | 164 + GameFiles/FileTypes/JPsoFile.cs | 48 + GameFiles/FileTypes/RelFile.cs | 800 ++ GameFiles/FileTypes/Stats.cs | 84 + GameFiles/FileTypes/YbnFile.cs | 44 + GameFiles/FileTypes/YcdFile.cs | 55 + GameFiles/FileTypes/YddFile.cs | 89 + GameFiles/FileTypes/YdrFile.cs | 59 + GameFiles/FileTypes/YftFile.cs | 50 + GameFiles/FileTypes/YmapFile.cs | 1359 +++ GameFiles/FileTypes/YmfFile.cs | 187 + GameFiles/FileTypes/YmtFile.cs | 372 + GameFiles/FileTypes/YndFile.cs | 1349 +++ GameFiles/FileTypes/YnvFile.cs | 405 + GameFiles/FileTypes/YptFile.cs | 106 + GameFiles/FileTypes/YtdFile.cs | 49 + GameFiles/FileTypes/YtypFile.cs | 265 + GameFiles/FileTypes/YvrFile.cs | 54 + GameFiles/FileTypes/YwrFile.cs | 54 + GameFiles/GameFile.cs | 74 + GameFiles/GameFileCache.cs | 2537 ++++ GameFiles/MetaTypes/Meta.cs | 641 + GameFiles/MetaTypes/MetaBuilder.cs | 377 + GameFiles/MetaTypes/MetaNames.cs | 6874 +++++++++++ GameFiles/MetaTypes/MetaTypes.cs | 5459 +++++++++ GameFiles/MetaTypes/MetaXml.cs | 1535 +++ GameFiles/MetaTypes/Pso.cs | 910 ++ GameFiles/MetaTypes/PsoTypes.cs | 856 ++ GameFiles/MetaTypes/Rbf.cs | 295 + GameFiles/Resources/Archetype.cs | 191 + GameFiles/Resources/Bounds.cs | 1413 +++ GameFiles/Resources/Clip.cs | 1804 +++ GameFiles/Resources/Data.cs | 483 + GameFiles/Resources/Drawable.cs | 2642 ++++ GameFiles/Resources/Frag.cs | 3742 ++++++ GameFiles/Resources/Nav.cs | 803 ++ GameFiles/Resources/Node.cs | 280 + GameFiles/Resources/Particle.cs | 4303 +++++++ GameFiles/Resources/ResourceBaseTypes.cs | 1414 +++ GameFiles/Resources/ResourceBuilder.cs | 340 + GameFiles/Resources/ResourceData.cs | 750 ++ GameFiles/Resources/ResourceFile.cs | 149 + GameFiles/Resources/RpfFile.cs | 1444 +++ GameFiles/Resources/RpfManager.cs | 423 + GameFiles/Resources/Texture.cs | 591 + GameFiles/Resources/VehicleRecord.cs | 116 + GameFiles/Resources/VertexTypes.cs | 1460 +++ GameFiles/Resources/WaypointRecord.cs | 107 + GameFiles/Utils/GTACrypto.cs | 251 + GameFiles/Utils/GTAKeys.cs | 1472 +++ GameFiles/Utils/Jenk.cs | 254 + JenkGenForm.Designer.cs | 147 + JenkGenForm.cs | 39 + JenkGenForm.resx | 409 + JenkIndForm.Designer.cs | 190 + JenkIndForm.cs | 246 + JenkIndForm.resx | 412 + KeyBindForm.Designer.cs | 115 + KeyBindForm.cs | 62 + KeyBindForm.resx | 409 + MainForm.Designer.cs | 224 + MainForm.cs | 138 + MainForm.resx | 415 + MapForm.Designer.cs | 847 ++ MapForm.cs | 1206 ++ MapForm.resx | 132 + Materials.txt | 215 + Notice.txt | 35 + Program.cs | 64 + Project/ProjectFile.cs | 604 + Project/UndoStep.cs | 604 + ProjectForm.Designer.cs | 8652 +++++++++++++ ProjectForm.cs | 10069 ++++++++++++++++ ProjectForm.resx | 418 + Properties/AssemblyInfo.cs | 36 + Properties/Resources.Designer.cs | 83 + Properties/Resources.resx | 127 + Properties/Settings.Designer.cs | 678 ++ Properties/Settings.settings | 181 + Readme.txt | 119 + Readme_Src.txt | 3 + Rendering/DirectX/DXForm.cs | 28 + Rendering/DirectX/DXManager.cs | 337 + Rendering/DirectX/DXUtility.cs | 463 + Rendering/Renderable.cs | 1642 +++ Rendering/RenderableCache.cs | 376 + Rendering/ShaderManager.cs | 1294 ++ Rendering/Shaders/BasicShader.cs | 885 ++ Rendering/Shaders/BoundsShader.cs | 239 + Rendering/Shaders/CableShader.cs | 345 + Rendering/Shaders/CloudsShader.cs | 356 + Rendering/Shaders/DistantLightsShader.cs | 146 + Rendering/Shaders/MarkerShader.cs | 166 + Rendering/Shaders/PathShader.cs | 246 + Rendering/Shaders/PostProcessor.cs | 688 ++ Rendering/Shaders/Shader.cs | 30 + Rendering/Shaders/ShadowShader.cs | 351 + Rendering/Shaders/SkydomeShader.cs | 410 + Rendering/Shaders/TerrainShader.cs | 645 + Rendering/Shaders/TreesLodShader.cs | 320 + Rendering/Shaders/WaterShader.cs | 564 + Rendering/Shaders/WidgetShader.cs | 617 + Rendering/Utils/GpuBuffers.cs | 372 + Rendering/Utils/RenderTargetSwitch.cs | 86 + Rendering/Utils/Shadowmap.cs | 1061 ++ Rendering/Utils/UnitCapsule.cs | 268 + Rendering/Utils/UnitCube.cs | 228 + Rendering/Utils/UnitCylinder.cs | 172 + Rendering/Utils/UnitDisc.cs | 93 + Rendering/Utils/UnitQuad.cs | 93 + Rendering/Utils/UnitSphere.cs | 181 + Resources/CW.ico | Bin 0 -> 17006 bytes Resources/CW16.ico | Bin 0 -> 894 bytes Resources/magic.dat | Bin 0 -> 154053 bytes SelectFolderForm.Designer.cs | 121 + SelectFolderForm.cs | 67 + SelectFolderForm.resx | 412 + Settings.cs | 28 + SettingsForm.Designer.cs | 875 ++ SettingsForm.cs | 323 + SettingsForm.resx | 412 + Shaders/BasicPS.cso | Bin 0 -> 10240 bytes Shaders/BasicPS.hlsl | 528 + Shaders/BasicVS.hlsli | 755 ++ Shaders/BasicVS_Box.cso | Bin 0 -> 4548 bytes Shaders/BasicVS_Box.hlsl | 68 + Shaders/BasicVS_Capsule.cso | Bin 0 -> 5208 bytes Shaders/BasicVS_Capsule.hlsl | 62 + Shaders/BasicVS_Cylinder.cso | Bin 0 -> 5256 bytes Shaders/BasicVS_Cylinder.hlsl | 62 + Shaders/BasicVS_PNCCT.cso | Bin 0 -> 9960 bytes Shaders/BasicVS_PNCCT.hlsl | 40 + Shaders/BasicVS_PNCCTT.cso | Bin 0 -> 9984 bytes Shaders/BasicVS_PNCCTT.hlsl | 41 + Shaders/BasicVS_PNCCTTT.cso | Bin 0 -> 10008 bytes Shaders/BasicVS_PNCCTTT.hlsl | 42 + Shaders/BasicVS_PNCCTTTX.cso | Bin 0 -> 10556 bytes Shaders/BasicVS_PNCCTTTX.hlsl | 43 + Shaders/BasicVS_PNCCTTX.cso | Bin 0 -> 10532 bytes Shaders/BasicVS_PNCCTTX.hlsl | 42 + Shaders/BasicVS_PNCCTX.cso | Bin 0 -> 10508 bytes Shaders/BasicVS_PNCCTX.hlsl | 41 + Shaders/BasicVS_PNCT.cso | Bin 0 -> 9928 bytes Shaders/BasicVS_PNCT.hlsl | 39 + Shaders/BasicVS_PNCTTTX.cso | Bin 0 -> 10524 bytes Shaders/BasicVS_PNCTTTX.hlsl | 42 + Shaders/BasicVS_PNCTTX.cso | Bin 0 -> 10500 bytes Shaders/BasicVS_PNCTTX.hlsl | 41 + Shaders/BasicVS_PNCTX.cso | Bin 0 -> 10476 bytes Shaders/BasicVS_PNCTX.hlsl | 40 + Shaders/BasicVS_Sphere.cso | Bin 0 -> 4456 bytes Shaders/BasicVS_Sphere.hlsl | 56 + Shaders/BoundingBoxVS.cso | Bin 0 -> 1536 bytes Shaders/BoundingBoxVS.hlsl | 27 + Shaders/BoundingSphereVS.cso | Bin 0 -> 1364 bytes Shaders/BoundingSphereVS.hlsl | 32 + Shaders/BoundsPS.cso | Bin 0 -> 516 bytes Shaders/BoundsPS.hlsl | 9 + Shaders/CablePS.cso | Bin 0 -> 7084 bytes Shaders/CablePS.hlsl | 102 + Shaders/CableVS.cso | Bin 0 -> 9788 bytes Shaders/CableVS.hlsl | 39 + Shaders/Clouds.hlsli | 49 + Shaders/CloudsPS.cso | Bin 0 -> 2780 bytes Shaders/CloudsPS.hlsl | 301 + Shaders/CloudsVS.cso | Bin 0 -> 4724 bytes Shaders/CloudsVS.hlsl | 398 + Shaders/CodeWalkerShaders.vcxproj | 551 + Shaders/CodeWalkerShaders.vcxproj.filters | 79 + Shaders/Common.hlsli | 169 + Shaders/DistantLightsPS.cso | Bin 0 -> 672 bytes Shaders/DistantLightsPS.hlsl | 16 + Shaders/DistantLightsVS.cso | Bin 0 -> 1904 bytes Shaders/DistantLightsVS.hlsl | 57 + Shaders/MarkerPS.cso | Bin 0 -> 596 bytes Shaders/MarkerPS.hlsl | 15 + Shaders/MarkerVS.cso | Bin 0 -> 1372 bytes Shaders/MarkerVS.hlsl | 41 + Shaders/PPBloomFilterBPHCS.cso | Bin 0 -> 3268 bytes Shaders/PPBloomFilterBPHCS.hlsl | 62 + Shaders/PPBloomFilterVCS.cso | Bin 0 -> 2568 bytes Shaders/PPBloomFilterVCS.hlsl | 72 + Shaders/PPCopyPixelsPS.cso | Bin 0 -> 896 bytes Shaders/PPCopyPixelsPS.hlsl | 27 + Shaders/PPFinalPassPS.cso | Bin 0 -> 1468 bytes Shaders/PPFinalPassPS.hlsl | 41 + Shaders/PPFinalPassVS.cso | Bin 0 -> 544 bytes Shaders/PPFinalPassVS.hlsl | 14 + Shaders/PPLumBlendCS.cso | Bin 0 -> 988 bytes Shaders/PPLumBlendCS.hlsl | 16 + Shaders/PPReduceTo0DCS.cso | Bin 0 -> 2236 bytes Shaders/PPReduceTo0DCS.hlsl | 54 + Shaders/PPReduceTo1DCS.cso | Bin 0 -> 2148 bytes Shaders/PPReduceTo1DCS.hlsl | 63 + Shaders/PathBoxPS.cso | Bin 0 -> 516 bytes Shaders/PathBoxPS.hlsl | 17 + Shaders/PathBoxVS.cso | Bin 0 -> 1300 bytes Shaders/PathBoxVS.hlsl | 45 + Shaders/PathDynVS.cso | Bin 0 -> 1404 bytes Shaders/PathDynVS.hlsl | 45 + Shaders/PathPS.cso | Bin 0 -> 484 bytes Shaders/PathPS.hlsl | 16 + Shaders/PathVS.cso | Bin 0 -> 968 bytes Shaders/PathVS.hlsl | 37 + Shaders/Quaternion.hlsli | 11 + Shaders/ShadowPS.cso | Bin 0 -> 1120 bytes Shaders/ShadowPS.hlsl | 32 + Shaders/ShadowVS.cso | Bin 0 -> 2600 bytes Shaders/ShadowVS.hlsl | 93 + Shaders/Shadowmap.hlsli | 250 + Shaders/SkyMoonPS.cso | Bin 0 -> 792 bytes Shaders/SkyMoonPS.hlsl | 24 + Shaders/SkyMoonVS.cso | Bin 0 -> 1156 bytes Shaders/SkyMoonVS.hlsl | 36 + Shaders/SkySunPS.cso | Bin 0 -> 520 bytes Shaders/SkySunPS.hlsl | 11 + Shaders/SkySunVS.cso | Bin 0 -> 1116 bytes Shaders/SkySunVS.hlsl | 36 + Shaders/Skydome.hlsli | 45 + Shaders/SkydomePS.cso | Bin 0 -> 3732 bytes Shaders/SkydomePS.hlsl | 342 + Shaders/SkydomeVS.cso | Bin 0 -> 5420 bytes Shaders/SkydomeVS.hlsl | 448 + Shaders/TerrainPS.cso | Bin 0 -> 13296 bytes Shaders/TerrainPS.hlsl | 278 + Shaders/TerrainVS.hlsli | 87 + Shaders/TerrainVS_PNCCT.cso | Bin 0 -> 4908 bytes Shaders/TerrainVS_PNCCT.hlsl | 39 + Shaders/TerrainVS_PNCCTT.cso | Bin 0 -> 4932 bytes Shaders/TerrainVS_PNCCTT.hlsl | 40 + Shaders/TerrainVS_PNCCTTTX.cso | Bin 0 -> 5504 bytes Shaders/TerrainVS_PNCCTTTX.hlsl | 42 + Shaders/TerrainVS_PNCCTTX.cso | Bin 0 -> 5480 bytes Shaders/TerrainVS_PNCCTTX.hlsl | 41 + Shaders/TerrainVS_PNCCTX.cso | Bin 0 -> 5456 bytes Shaders/TerrainVS_PNCCTX.hlsl | 40 + Shaders/TerrainVS_PNCTTTX.cso | Bin 0 -> 5480 bytes Shaders/TerrainVS_PNCTTTX.hlsl | 41 + Shaders/TerrainVS_PNCTTX.cso | Bin 0 -> 5456 bytes Shaders/TerrainVS_PNCTTX.hlsl | 40 + Shaders/TreesLodPS.cso | Bin 0 -> 2056 bytes Shaders/TreesLodPS.hlsl | 53 + Shaders/TreesLodVS.cso | Bin 0 -> 3020 bytes Shaders/TreesLodVS.hlsl | 95 + Shaders/WaterPS.cso | Bin 0 -> 10084 bytes Shaders/WaterPS.hlsl | 800 ++ Shaders/WaterVS.hlsli | 474 + Shaders/WaterVS_PCT.cso | Bin 0 -> 4596 bytes Shaders/WaterVS_PCT.hlsl | 33 + Shaders/WaterVS_PNCT.cso | Bin 0 -> 4600 bytes Shaders/WaterVS_PNCT.hlsl | 34 + Shaders/WaterVS_PNCTX.cso | Bin 0 -> 5016 bytes Shaders/WaterVS_PNCTX.hlsl | 34 + Shaders/WaterVS_PT.cso | Bin 0 -> 4092 bytes Shaders/WaterVS_PT.hlsl | 32 + Shaders/WidgetPS.cso | Bin 0 -> 556 bytes Shaders/WidgetPS.hlsl | 14 + Shaders/WidgetVS.cso | Bin 0 -> 2080 bytes Shaders/WidgetVS.hlsl | 63 + Todo.txt | 194 + Toolbar/cammode_2D.png | Bin 0 -> 1309 bytes Toolbar/cammode_3D.png | Bin 0 -> 1311 bytes Toolbar/cammode_Or.png | Bin 0 -> 1296 bytes Utils/Cache.cs | 121 + Utils/DDSIO.cs | 2411 ++++ Utils/Matrices.cs | 42 + Utils/Quaternions.cs | 74 + Utils/TextureLoader.cs | 186 + Utils/Utils.cs | 448 + Utils/Vectors.cs | 60 + Utils/Xml.cs | 113 + World/Camera.cs | 364 + World/Clouds.cs | 459 + World/Entity.cs | 179 + World/PopZone.cs | 166 + World/Scenarios.cs | 1856 +++ World/Space.cs | 2078 ++++ World/Timecycle.cs | 124 + World/TimecycleMods.cs | 148 + World/Trains.cs | 433 + World/Water.cs | 213 + World/Weather.cs | 569 + World/Widget.cs | 941 ++ WorldForm.Designer.cs | 3434 ++++++ WorldForm.cs | 9462 +++++++++++++++ WorldForm.resx | 691 ++ WorldInfoForm.Designer.cs | 641 + WorldInfoForm.cs | 489 + WorldInfoForm.resx | 409 + WorldSearchForm.Designer.cs | 668 + WorldSearchForm.cs | 520 + WorldSearchForm.resx | 412 + icons/icon_glokon_debug_32x32.png | Bin 0 -> 1952 bytes icons/icon_glokon_normal_32x32.png | Bin 0 -> 2074 bytes icons/icon_google_marker_64x64.png | Bin 0 -> 2014 bytes packages.config | 12 + 391 files changed, 157678 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 AboutForm.Designer.cs create mode 100644 AboutForm.cs create mode 100644 AboutForm.resx create mode 100644 App.config create mode 100644 BinarySearchForm.Designer.cs create mode 100644 BinarySearchForm.cs create mode 100644 BinarySearchForm.resx create mode 100644 BrowseForm.Designer.cs create mode 100644 BrowseForm.cs create mode 100644 BrowseForm.resx create mode 100644 CodeWalker Explorer.bat create mode 100644 CodeWalker.WinForms/CodeWalker.WinForms.csproj create mode 100644 CodeWalker.WinForms/MenuStripFix.Designer.cs create mode 100644 CodeWalker.WinForms/MenuStripFix.cs create mode 100644 CodeWalker.WinForms/Properties/AssemblyInfo.cs create mode 100644 CodeWalker.WinForms/PropertyGridFix.Designer.cs create mode 100644 CodeWalker.WinForms/PropertyGridFix.cs create mode 100644 CodeWalker.WinForms/ReadOnlyPropertyGrid.Designer.cs create mode 100644 CodeWalker.WinForms/ReadOnlyPropertyGrid.cs create mode 100644 CodeWalker.WinForms/TextBoxFix.Designer.cs create mode 100644 CodeWalker.WinForms/TextBoxFix.cs create mode 100644 CodeWalker.WinForms/TextBoxScrollSyncFix.Designer.cs create mode 100644 CodeWalker.WinForms/TextBoxScrollSyncFix.cs create mode 100644 CodeWalker.WinForms/ToolStripFix.Designer.cs create mode 100644 CodeWalker.WinForms/ToolStripFix.cs create mode 100644 CodeWalker.WinForms/ToolStripSplitButtonFix.Designer.cs create mode 100644 CodeWalker.WinForms/ToolStripSplitButtonFix.cs create mode 100644 CodeWalker.WinForms/ToolStripSpringTextBox.Designer.cs create mode 100644 CodeWalker.WinForms/ToolStripSpringTextBox.cs create mode 100644 CodeWalker.WinForms/TreeViewFix.Designer.cs create mode 100644 CodeWalker.WinForms/TreeViewFix.cs create mode 100644 CodeWalker.csproj create mode 100644 CodeWalker.sln create mode 100644 ExploreForm.Designer.cs create mode 100644 ExploreForm.cs create mode 100644 ExploreForm.resx create mode 100644 ExtractKeysForm.Designer.cs create mode 100644 ExtractKeysForm.cs create mode 100644 ExtractKeysForm.resx create mode 100644 ExtractRawForm.Designer.cs create mode 100644 ExtractRawForm.cs create mode 100644 ExtractRawForm.resx create mode 100644 ExtractScriptsForm.Designer.cs create mode 100644 ExtractScriptsForm.cs create mode 100644 ExtractScriptsForm.resx create mode 100644 ExtractShadersForm.Designer.cs create mode 100644 ExtractShadersForm.cs create mode 100644 ExtractShadersForm.resx create mode 100644 ExtractTexForm.Designer.cs create mode 100644 ExtractTexForm.cs create mode 100644 ExtractTexForm.resx create mode 100644 Forms/AwcForm.Designer.cs create mode 100644 Forms/AwcForm.cs create mode 100644 Forms/AwcForm.resx create mode 100644 Forms/FxcForm.Designer.cs create mode 100644 Forms/FxcForm.cs create mode 100644 Forms/FxcForm.resx create mode 100644 Forms/GxtForm.Designer.cs create mode 100644 Forms/GxtForm.cs create mode 100644 Forms/GxtForm.resx create mode 100644 Forms/HexForm.Designer.cs create mode 100644 Forms/HexForm.cs create mode 100644 Forms/HexForm.resx create mode 100644 Forms/MetaForm.Designer.cs create mode 100644 Forms/MetaForm.cs create mode 100644 Forms/MetaForm.resx create mode 100644 Forms/ModelForm.Designer.cs create mode 100644 Forms/ModelForm.cs create mode 100644 Forms/ModelForm.resx create mode 100644 Forms/RelForm.Designer.cs create mode 100644 Forms/RelForm.cs create mode 100644 Forms/RelForm.resx create mode 100644 Forms/TextForm.Designer.cs create mode 100644 Forms/TextForm.cs create mode 100644 Forms/TextForm.resx create mode 100644 Forms/XmlForm.Designer.cs create mode 100644 Forms/XmlForm.cs create mode 100644 Forms/XmlForm.resx create mode 100644 Forms/YtdForm.Designer.cs create mode 100644 Forms/YtdForm.cs create mode 100644 Forms/YtdForm.resx create mode 100644 Forms/YvrForm.Designer.cs create mode 100644 Forms/YvrForm.cs create mode 100644 Forms/YvrForm.resx create mode 100644 Forms/YwrForm.Designer.cs create mode 100644 Forms/YwrForm.cs create mode 100644 Forms/YwrForm.resx create mode 100644 GameFiles/FileTypes/AwcFile.cs create mode 100644 GameFiles/FileTypes/CacheDatFile.cs create mode 100644 GameFiles/FileTypes/CutFile.cs create mode 100644 GameFiles/FileTypes/DlcContentFile.cs create mode 100644 GameFiles/FileTypes/DlcSetupFile.cs create mode 100644 GameFiles/FileTypes/FxcFile.cs create mode 100644 GameFiles/FileTypes/Gxt2File.cs create mode 100644 GameFiles/FileTypes/JPsoFile.cs create mode 100644 GameFiles/FileTypes/RelFile.cs create mode 100644 GameFiles/FileTypes/Stats.cs create mode 100644 GameFiles/FileTypes/YbnFile.cs create mode 100644 GameFiles/FileTypes/YcdFile.cs create mode 100644 GameFiles/FileTypes/YddFile.cs create mode 100644 GameFiles/FileTypes/YdrFile.cs create mode 100644 GameFiles/FileTypes/YftFile.cs create mode 100644 GameFiles/FileTypes/YmapFile.cs create mode 100644 GameFiles/FileTypes/YmfFile.cs create mode 100644 GameFiles/FileTypes/YmtFile.cs create mode 100644 GameFiles/FileTypes/YndFile.cs create mode 100644 GameFiles/FileTypes/YnvFile.cs create mode 100644 GameFiles/FileTypes/YptFile.cs create mode 100644 GameFiles/FileTypes/YtdFile.cs create mode 100644 GameFiles/FileTypes/YtypFile.cs create mode 100644 GameFiles/FileTypes/YvrFile.cs create mode 100644 GameFiles/FileTypes/YwrFile.cs create mode 100644 GameFiles/GameFile.cs create mode 100644 GameFiles/GameFileCache.cs create mode 100644 GameFiles/MetaTypes/Meta.cs create mode 100644 GameFiles/MetaTypes/MetaBuilder.cs create mode 100644 GameFiles/MetaTypes/MetaNames.cs create mode 100644 GameFiles/MetaTypes/MetaTypes.cs create mode 100644 GameFiles/MetaTypes/MetaXml.cs create mode 100644 GameFiles/MetaTypes/Pso.cs create mode 100644 GameFiles/MetaTypes/PsoTypes.cs create mode 100644 GameFiles/MetaTypes/Rbf.cs create mode 100644 GameFiles/Resources/Archetype.cs create mode 100644 GameFiles/Resources/Bounds.cs create mode 100644 GameFiles/Resources/Clip.cs create mode 100644 GameFiles/Resources/Data.cs create mode 100644 GameFiles/Resources/Drawable.cs create mode 100644 GameFiles/Resources/Frag.cs create mode 100644 GameFiles/Resources/Nav.cs create mode 100644 GameFiles/Resources/Node.cs create mode 100644 GameFiles/Resources/Particle.cs create mode 100644 GameFiles/Resources/ResourceBaseTypes.cs create mode 100644 GameFiles/Resources/ResourceBuilder.cs create mode 100644 GameFiles/Resources/ResourceData.cs create mode 100644 GameFiles/Resources/ResourceFile.cs create mode 100644 GameFiles/Resources/RpfFile.cs create mode 100644 GameFiles/Resources/RpfManager.cs create mode 100644 GameFiles/Resources/Texture.cs create mode 100644 GameFiles/Resources/VehicleRecord.cs create mode 100644 GameFiles/Resources/VertexTypes.cs create mode 100644 GameFiles/Resources/WaypointRecord.cs create mode 100644 GameFiles/Utils/GTACrypto.cs create mode 100644 GameFiles/Utils/GTAKeys.cs create mode 100644 GameFiles/Utils/Jenk.cs create mode 100644 JenkGenForm.Designer.cs create mode 100644 JenkGenForm.cs create mode 100644 JenkGenForm.resx create mode 100644 JenkIndForm.Designer.cs create mode 100644 JenkIndForm.cs create mode 100644 JenkIndForm.resx create mode 100644 KeyBindForm.Designer.cs create mode 100644 KeyBindForm.cs create mode 100644 KeyBindForm.resx create mode 100644 MainForm.Designer.cs create mode 100644 MainForm.cs create mode 100644 MainForm.resx create mode 100644 MapForm.Designer.cs create mode 100644 MapForm.cs create mode 100644 MapForm.resx create mode 100644 Materials.txt create mode 100644 Notice.txt create mode 100644 Program.cs create mode 100644 Project/ProjectFile.cs create mode 100644 Project/UndoStep.cs create mode 100644 ProjectForm.Designer.cs create mode 100644 ProjectForm.cs create mode 100644 ProjectForm.resx create mode 100644 Properties/AssemblyInfo.cs create mode 100644 Properties/Resources.Designer.cs create mode 100644 Properties/Resources.resx create mode 100644 Properties/Settings.Designer.cs create mode 100644 Properties/Settings.settings create mode 100644 Readme.txt create mode 100644 Readme_Src.txt create mode 100644 Rendering/DirectX/DXForm.cs create mode 100644 Rendering/DirectX/DXManager.cs create mode 100644 Rendering/DirectX/DXUtility.cs create mode 100644 Rendering/Renderable.cs create mode 100644 Rendering/RenderableCache.cs create mode 100644 Rendering/ShaderManager.cs create mode 100644 Rendering/Shaders/BasicShader.cs create mode 100644 Rendering/Shaders/BoundsShader.cs create mode 100644 Rendering/Shaders/CableShader.cs create mode 100644 Rendering/Shaders/CloudsShader.cs create mode 100644 Rendering/Shaders/DistantLightsShader.cs create mode 100644 Rendering/Shaders/MarkerShader.cs create mode 100644 Rendering/Shaders/PathShader.cs create mode 100644 Rendering/Shaders/PostProcessor.cs create mode 100644 Rendering/Shaders/Shader.cs create mode 100644 Rendering/Shaders/ShadowShader.cs create mode 100644 Rendering/Shaders/SkydomeShader.cs create mode 100644 Rendering/Shaders/TerrainShader.cs create mode 100644 Rendering/Shaders/TreesLodShader.cs create mode 100644 Rendering/Shaders/WaterShader.cs create mode 100644 Rendering/Shaders/WidgetShader.cs create mode 100644 Rendering/Utils/GpuBuffers.cs create mode 100644 Rendering/Utils/RenderTargetSwitch.cs create mode 100644 Rendering/Utils/Shadowmap.cs create mode 100644 Rendering/Utils/UnitCapsule.cs create mode 100644 Rendering/Utils/UnitCube.cs create mode 100644 Rendering/Utils/UnitCylinder.cs create mode 100644 Rendering/Utils/UnitDisc.cs create mode 100644 Rendering/Utils/UnitQuad.cs create mode 100644 Rendering/Utils/UnitSphere.cs create mode 100644 Resources/CW.ico create mode 100644 Resources/CW16.ico create mode 100644 Resources/magic.dat create mode 100644 SelectFolderForm.Designer.cs create mode 100644 SelectFolderForm.cs create mode 100644 SelectFolderForm.resx create mode 100644 Settings.cs create mode 100644 SettingsForm.Designer.cs create mode 100644 SettingsForm.cs create mode 100644 SettingsForm.resx create mode 100644 Shaders/BasicPS.cso create mode 100644 Shaders/BasicPS.hlsl create mode 100644 Shaders/BasicVS.hlsli create mode 100644 Shaders/BasicVS_Box.cso create mode 100644 Shaders/BasicVS_Box.hlsl create mode 100644 Shaders/BasicVS_Capsule.cso create mode 100644 Shaders/BasicVS_Capsule.hlsl create mode 100644 Shaders/BasicVS_Cylinder.cso create mode 100644 Shaders/BasicVS_Cylinder.hlsl create mode 100644 Shaders/BasicVS_PNCCT.cso create mode 100644 Shaders/BasicVS_PNCCT.hlsl create mode 100644 Shaders/BasicVS_PNCCTT.cso create mode 100644 Shaders/BasicVS_PNCCTT.hlsl create mode 100644 Shaders/BasicVS_PNCCTTT.cso create mode 100644 Shaders/BasicVS_PNCCTTT.hlsl create mode 100644 Shaders/BasicVS_PNCCTTTX.cso create mode 100644 Shaders/BasicVS_PNCCTTTX.hlsl create mode 100644 Shaders/BasicVS_PNCCTTX.cso create mode 100644 Shaders/BasicVS_PNCCTTX.hlsl create mode 100644 Shaders/BasicVS_PNCCTX.cso create mode 100644 Shaders/BasicVS_PNCCTX.hlsl create mode 100644 Shaders/BasicVS_PNCT.cso create mode 100644 Shaders/BasicVS_PNCT.hlsl create mode 100644 Shaders/BasicVS_PNCTTTX.cso create mode 100644 Shaders/BasicVS_PNCTTTX.hlsl create mode 100644 Shaders/BasicVS_PNCTTX.cso create mode 100644 Shaders/BasicVS_PNCTTX.hlsl create mode 100644 Shaders/BasicVS_PNCTX.cso create mode 100644 Shaders/BasicVS_PNCTX.hlsl create mode 100644 Shaders/BasicVS_Sphere.cso create mode 100644 Shaders/BasicVS_Sphere.hlsl create mode 100644 Shaders/BoundingBoxVS.cso create mode 100644 Shaders/BoundingBoxVS.hlsl create mode 100644 Shaders/BoundingSphereVS.cso create mode 100644 Shaders/BoundingSphereVS.hlsl create mode 100644 Shaders/BoundsPS.cso create mode 100644 Shaders/BoundsPS.hlsl create mode 100644 Shaders/CablePS.cso create mode 100644 Shaders/CablePS.hlsl create mode 100644 Shaders/CableVS.cso create mode 100644 Shaders/CableVS.hlsl create mode 100644 Shaders/Clouds.hlsli create mode 100644 Shaders/CloudsPS.cso create mode 100644 Shaders/CloudsPS.hlsl create mode 100644 Shaders/CloudsVS.cso create mode 100644 Shaders/CloudsVS.hlsl create mode 100644 Shaders/CodeWalkerShaders.vcxproj create mode 100644 Shaders/CodeWalkerShaders.vcxproj.filters create mode 100644 Shaders/Common.hlsli create mode 100644 Shaders/DistantLightsPS.cso create mode 100644 Shaders/DistantLightsPS.hlsl create mode 100644 Shaders/DistantLightsVS.cso create mode 100644 Shaders/DistantLightsVS.hlsl create mode 100644 Shaders/MarkerPS.cso create mode 100644 Shaders/MarkerPS.hlsl create mode 100644 Shaders/MarkerVS.cso create mode 100644 Shaders/MarkerVS.hlsl create mode 100644 Shaders/PPBloomFilterBPHCS.cso create mode 100644 Shaders/PPBloomFilterBPHCS.hlsl create mode 100644 Shaders/PPBloomFilterVCS.cso create mode 100644 Shaders/PPBloomFilterVCS.hlsl create mode 100644 Shaders/PPCopyPixelsPS.cso create mode 100644 Shaders/PPCopyPixelsPS.hlsl create mode 100644 Shaders/PPFinalPassPS.cso create mode 100644 Shaders/PPFinalPassPS.hlsl create mode 100644 Shaders/PPFinalPassVS.cso create mode 100644 Shaders/PPFinalPassVS.hlsl create mode 100644 Shaders/PPLumBlendCS.cso create mode 100644 Shaders/PPLumBlendCS.hlsl create mode 100644 Shaders/PPReduceTo0DCS.cso create mode 100644 Shaders/PPReduceTo0DCS.hlsl create mode 100644 Shaders/PPReduceTo1DCS.cso create mode 100644 Shaders/PPReduceTo1DCS.hlsl create mode 100644 Shaders/PathBoxPS.cso create mode 100644 Shaders/PathBoxPS.hlsl create mode 100644 Shaders/PathBoxVS.cso create mode 100644 Shaders/PathBoxVS.hlsl create mode 100644 Shaders/PathDynVS.cso create mode 100644 Shaders/PathDynVS.hlsl create mode 100644 Shaders/PathPS.cso create mode 100644 Shaders/PathPS.hlsl create mode 100644 Shaders/PathVS.cso create mode 100644 Shaders/PathVS.hlsl create mode 100644 Shaders/Quaternion.hlsli create mode 100644 Shaders/ShadowPS.cso create mode 100644 Shaders/ShadowPS.hlsl create mode 100644 Shaders/ShadowVS.cso create mode 100644 Shaders/ShadowVS.hlsl create mode 100644 Shaders/Shadowmap.hlsli create mode 100644 Shaders/SkyMoonPS.cso create mode 100644 Shaders/SkyMoonPS.hlsl create mode 100644 Shaders/SkyMoonVS.cso create mode 100644 Shaders/SkyMoonVS.hlsl create mode 100644 Shaders/SkySunPS.cso create mode 100644 Shaders/SkySunPS.hlsl create mode 100644 Shaders/SkySunVS.cso create mode 100644 Shaders/SkySunVS.hlsl create mode 100644 Shaders/Skydome.hlsli create mode 100644 Shaders/SkydomePS.cso create mode 100644 Shaders/SkydomePS.hlsl create mode 100644 Shaders/SkydomeVS.cso create mode 100644 Shaders/SkydomeVS.hlsl create mode 100644 Shaders/TerrainPS.cso create mode 100644 Shaders/TerrainPS.hlsl create mode 100644 Shaders/TerrainVS.hlsli create mode 100644 Shaders/TerrainVS_PNCCT.cso create mode 100644 Shaders/TerrainVS_PNCCT.hlsl create mode 100644 Shaders/TerrainVS_PNCCTT.cso create mode 100644 Shaders/TerrainVS_PNCCTT.hlsl create mode 100644 Shaders/TerrainVS_PNCCTTTX.cso create mode 100644 Shaders/TerrainVS_PNCCTTTX.hlsl create mode 100644 Shaders/TerrainVS_PNCCTTX.cso create mode 100644 Shaders/TerrainVS_PNCCTTX.hlsl create mode 100644 Shaders/TerrainVS_PNCCTX.cso create mode 100644 Shaders/TerrainVS_PNCCTX.hlsl create mode 100644 Shaders/TerrainVS_PNCTTTX.cso create mode 100644 Shaders/TerrainVS_PNCTTTX.hlsl create mode 100644 Shaders/TerrainVS_PNCTTX.cso create mode 100644 Shaders/TerrainVS_PNCTTX.hlsl create mode 100644 Shaders/TreesLodPS.cso create mode 100644 Shaders/TreesLodPS.hlsl create mode 100644 Shaders/TreesLodVS.cso create mode 100644 Shaders/TreesLodVS.hlsl create mode 100644 Shaders/WaterPS.cso create mode 100644 Shaders/WaterPS.hlsl create mode 100644 Shaders/WaterVS.hlsli create mode 100644 Shaders/WaterVS_PCT.cso create mode 100644 Shaders/WaterVS_PCT.hlsl create mode 100644 Shaders/WaterVS_PNCT.cso create mode 100644 Shaders/WaterVS_PNCT.hlsl create mode 100644 Shaders/WaterVS_PNCTX.cso create mode 100644 Shaders/WaterVS_PNCTX.hlsl create mode 100644 Shaders/WaterVS_PT.cso create mode 100644 Shaders/WaterVS_PT.hlsl create mode 100644 Shaders/WidgetPS.cso create mode 100644 Shaders/WidgetPS.hlsl create mode 100644 Shaders/WidgetVS.cso create mode 100644 Shaders/WidgetVS.hlsl create mode 100644 Todo.txt create mode 100644 Toolbar/cammode_2D.png create mode 100644 Toolbar/cammode_3D.png create mode 100644 Toolbar/cammode_Or.png create mode 100644 Utils/Cache.cs create mode 100644 Utils/DDSIO.cs create mode 100644 Utils/Matrices.cs create mode 100644 Utils/Quaternions.cs create mode 100644 Utils/TextureLoader.cs create mode 100644 Utils/Utils.cs create mode 100644 Utils/Vectors.cs create mode 100644 Utils/Xml.cs create mode 100644 World/Camera.cs create mode 100644 World/Clouds.cs create mode 100644 World/Entity.cs create mode 100644 World/PopZone.cs create mode 100644 World/Scenarios.cs create mode 100644 World/Space.cs create mode 100644 World/Timecycle.cs create mode 100644 World/TimecycleMods.cs create mode 100644 World/Trains.cs create mode 100644 World/Water.cs create mode 100644 World/Weather.cs create mode 100644 World/Widget.cs create mode 100644 WorldForm.Designer.cs create mode 100644 WorldForm.cs create mode 100644 WorldForm.resx create mode 100644 WorldInfoForm.Designer.cs create mode 100644 WorldInfoForm.cs create mode 100644 WorldInfoForm.resx create mode 100644 WorldSearchForm.Designer.cs create mode 100644 WorldSearchForm.cs create mode 100644 WorldSearchForm.resx create mode 100644 icons/icon_glokon_debug_32x32.png create mode 100644 icons/icon_glokon_normal_32x32.png create mode 100644 icons/icon_google_marker_64x64.png create mode 100644 packages.config diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb079fa --- /dev/null +++ b/.gitignore @@ -0,0 +1,243 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +[Xx]64/ +[Xx]86/ +[Bb]uild/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml + +# TODO: Un-comment the next line if you do not want to checkin +# your web deploy settings because they may include unencrypted +# passwords +#*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# LightSwitch generated files +GeneratedArtifacts/ +ModelManifest.xml + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ +/Toolbar/cammodes.psd diff --git a/AboutForm.Designer.cs b/AboutForm.Designer.cs new file mode 100644 index 0000000..a9b9938 --- /dev/null +++ b/AboutForm.Designer.cs @@ -0,0 +1,96 @@ +namespace CodeWalker +{ + partial class AboutForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm)); + this.OkButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // OkButton + // + this.OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.OkButton.Location = new System.Drawing.Point(305, 136); + this.OkButton.Name = "OkButton"; + this.OkButton.Size = new System.Drawing.Size(75, 23); + this.OkButton.TabIndex = 0; + this.OkButton.Text = "Ok"; + this.OkButton.UseVisualStyleBackColor = true; + this.OkButton.Click += new System.EventHandler(this.OkButton_Click); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label1.Location = new System.Drawing.Point(12, 35); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(368, 127); + this.label1.TabIndex = 1; + this.label1.Text = resources.GetString("label1.Text"); + this.label1.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(12, 9); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(368, 26); + this.label2.TabIndex = 2; + this.label2.Text = "CodeWalker by dexyfex"; + this.label2.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // AboutForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(392, 171); + this.Controls.Add(this.label2); + this.Controls.Add(this.OkButton); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutForm"; + this.Text = "About CodeWalker by dexyfex"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button OkButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + } +} \ No newline at end of file diff --git a/AboutForm.cs b/AboutForm.cs new file mode 100644 index 0000000..4e7c34d --- /dev/null +++ b/AboutForm.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class AboutForm : Form + { + public AboutForm() + { + InitializeComponent(); + } + + private void OkButton_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/AboutForm.resx b/AboutForm.resx new file mode 100644 index 0000000..5360d58 --- /dev/null +++ b/AboutForm.resx @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + A tool for visualising data pertaining to the search for the next paradigm. + +Special thanks to: + +-- Neodymium -- tgascoigne -- CamxxCore -- +-- Tadden -- Gramz -- Kai -- Vertigo -- HL -- Pouaichh -- +-- The .White team -- CP -- Kilian -- +-- Dilapidated -- dav90 -- Neos7 -- + + + + + AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA + AABAAAAAAQAYAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv8/u3v+Pn6//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AP7+/vX3/rzA3OHl9fz9/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7//+zv+3Z6qcLI5Pr7/wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAP7+/+br+15in6+33vf5/wAAAAAAAAAAAAAAAP7+//7+/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//v8//v8//3+/wAAAAAAAAAAAAAAAAAAAP7+/+Ho+1dana20 + 4/b4/wAAAAAAAPz9//P2/+Tp/ezw/vz9/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///X4 + /9Pa+tPa+/H1//z9/wAAAAAAAAAAAAAAAP7+/93k+SsscaSr3PX3/wAAAP7+//L1/7W98AcWgrvC8Pj6 + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/+bs/xohiAEJdrvF9+7y//z9/wAAAAAAAAAA + AP7+/9rh+CEkapmh0/T3/wAAAPj6/9HZ/AEHcgEEb9LZ+/r7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAP7//+/z/3F+zAAAXwQLcZai3fb4/wAAAAAAAAAAAP3+/97l/E9Tmaau4fT3/wAAAO/0/1dd + sAAAV7a/8/H1//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPr8/+jv/46Y3QUUf6Ot + 5PX4/wAAAAAAAAAAAP3+/9zj+3Z6wLe/7fX4/wAAAPD0/212xnaAzerw//z9/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv8/+/z/+Dm+/D0//z9/wAAAAAAAP7+//j6/9Pd+UhLjb/H + 9/D0//3+//n7/+nt/+jt//n7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AP7///7+//7+//7+/wAAAAAAAPr8/+7z/83W+ImU2A0UdFNarr/K9env//X4//z9//3+//7//wAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///j6/+Pq/255 + xhckjE5XsVVftUlTqwAKeTA9nr3H8+7z//v8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+//b4/9Tc+Sc0mRonj8rV/crX/ZSb48rX/brG8wwWgQAEdJei + 4efu//n7//7+//z9//z9//z9//z9//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//f5/+3y/+nv/+ft + /8vV+io2mImU2M7c/7vG9yIvlQAOfCg4mM3Y/s/c/4aR1AQRfGtzwtni/ebt/9vi/tri/tXd+9Tc+O3x + /vz9/wAAAAAAAAAAAAAAAAAAAAAAAPn6/87V+FVftkRPrFlnvSEqjQoUfmJvwWFvvg0TfQQIcxEchwAD + cy89n19rvVVitQwZgwAAaiMrkT9NqTVBoiw3mhQihig1mNLX+fv8/wAAAAAAAAAAAAAAAAAAAAAAAPb5 + /52l4EFLqoCK03yF0VBctGhyw52o5GVrvQAAaneBzsHM+jA3mhYgiTtIpJOf3ouW2AAAbmh0wbbA8bS+ + 7qiz5pCb16+56e/z//3+/wAAAAAAAAAAAAAAAAAAAAAAAPv8//H1/+vw/+zx/+nv/7/J9YqP3MbP/8LM + +hwqkFZftaCp5EhRrcTQ+9jj/8rW/UJMqn6J0ebt//X3//f5//b4//X3//f5//z9/wAAAAAAAAAAAAAA + AAAAAAAAAP7+//z9//3+/wAAAAAAAP3+/+7z/6at64iP3aWs7XN8zRIfhyUykp2o5MHM+oKM0xonjY6X + 2+jv//v8/wAAAP7+//n7//b5//r7//7//wAAAAAAAAAAAAAAAP7+//f5/+rw/9Pa9fL0/v7//wAAAAAA + APv8//H1/+Tr/7i/91liu0NPq0VQrS06m0NNqDdCoYqU1+nv//v8/wAAAAAAAPn7/9zi/qSt59ri/fL1 + //v8//7//wAAAPz9//D0/8rT+h0sjkVQrPD0/wAAAAAAAAAAAAAAAAAAAPz9/+7z/8LL9Jqk4aGq6LW/ + 8c3W9+Xs/vH1//v8/wAAAAAAAAAAAPf5/6at5gAAbxIfh6u16+Po/fr7/wAAAPb5/6ev5gAIeAAPernC + 8fX4/wAAAAAAAP3+//v8//z9/wAAAP3+//j6//P3//P2//b4//r8//7+//7+//v8//r8//3+/wAAAPv8 + /+Xr/nuIzwAAbBseg5Sb2fb5/wAAAPf5/8DF8pWe3d/n/vT3//39/wAAAPv8/+zx/87V9+3x/v3+/wAA + AP3+//j6//X4//v8/wAAAAAAAPn7/+Dm/snR9fD0//39//z8/fv8/+3y/8LK9aGq4dfd9/n7/wAAAPz9 + //b5//X4//v8/wAAAAAAAP7+/+7z/4aP1gEPet7k/f39/wAAAPf5/83U+ZCZ2u3x/v7+/wAAAPP3/215 + wgAJd7fB8/L1//7+/wAAAP3+//j6//f5//r8//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAPj6/87W/AAA + X2duue3y//7+/wAAAPD0/05asBQfidzj/P39/wAAAPX4/6Su6AAAXBccgtff/vv8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPP3/3F8xhYli9Xe/fn6/wAAAAAAAO3y/1pltQAJd9be + /fv8/wAAAPz9/+rw/36I0Bknjs/W+vv8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAPf5/8HI7tnf+/X4//7+/wAAAAAAAO/0/3R7xgAAb9ng/Pz9/wAAAAAAAPn7/+Ln/dLY+fP2//3+ + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//r7//v8//7+/wAAAAAAAAAA + APb4/7/F84eP0e/0//7+/wAAAAAAAP7+//z9//v8//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz9//b5//X4//v8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////w////4 + P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA + AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA + AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v// + /////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/App.config b/App.config new file mode 100644 index 0000000..7082fcf --- /dev/null +++ b/App.config @@ -0,0 +1,192 @@ + + + + +
+ + + + + + + + + + + + C:\Program Files (x86)\Steam\SteamApps\common\Grand Theft Auto V + + + + + + + + + + + + + + + + + + + + + False + + + False + + + True + + + True + + + False + + + 4 + + + True + + + 5 + + + Glokon Marker + + + Glokon Debug + + + False + + + None + + + True + + + 100 + + + False + + + True + + + 6 + + + True + + + False + + + 2147483648 + + + 10 + + + 536870912 + + + 1073741824 + + + 134217728 + + + 1 + + + 0.1 + + + 10 + + + 0.005 + + + 1 + + + Default + + + DiffuseSampler + + + Texture coord 1 + + + Installers;_CommonRedist + + + True + + + True + + + False + + + False + + + + + + + + Move Forwards: W + Move Backwards: S + Move Left: A + Move Right: D + Move Up: R + Move Down: F + Move Slower / Zoom In: Z + Move Faster / Zoom Out: X + Toggle Mouse Select: C + Toggle Toolbar: T + Exit Edit Mode: Q + Edit Position: W + Edit Rotation: E + Edit Scale: R + + + + + True + + + False + + + 2 + + + 2 + + + 2 + + + 15 + + + + \ No newline at end of file diff --git a/BinarySearchForm.Designer.cs b/BinarySearchForm.Designer.cs new file mode 100644 index 0000000..9519234 --- /dev/null +++ b/BinarySearchForm.Designer.cs @@ -0,0 +1,170 @@ +namespace CodeWalker +{ + partial class BinarySearchForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BinarySearchForm)); + this.TextRadio = new System.Windows.Forms.RadioButton(); + this.HexRadio = new System.Windows.Forms.RadioButton(); + this.SearchAbortButton = new System.Windows.Forms.Button(); + this.SearchResultsTextBox = new System.Windows.Forms.TextBox(); + this.BinSearchTextBox = new System.Windows.Forms.TextBox(); + this.BinSearchFolderBrowseButton = new System.Windows.Forms.Button(); + this.BinSearchButton = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); + this.BinSearchFolderTextBox = new System.Windows.Forms.TextBox(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.SuspendLayout(); + // + // TextRadio + // + this.TextRadio.AutoSize = true; + this.TextRadio.Location = new System.Drawing.Point(169, 39); + this.TextRadio.Name = "TextRadio"; + this.TextRadio.Size = new System.Drawing.Size(46, 17); + this.TextRadio.TabIndex = 45; + this.TextRadio.Text = "Text"; + this.TextRadio.UseVisualStyleBackColor = true; + // + // HexRadio + // + this.HexRadio.AutoSize = true; + this.HexRadio.Checked = true; + this.HexRadio.Location = new System.Drawing.Point(119, 39); + this.HexRadio.Name = "HexRadio"; + this.HexRadio.Size = new System.Drawing.Size(44, 17); + this.HexRadio.TabIndex = 44; + this.HexRadio.TabStop = true; + this.HexRadio.Text = "Hex"; + this.HexRadio.UseVisualStyleBackColor = true; + // + // SearchAbortButton + // + this.SearchAbortButton.Location = new System.Drawing.Point(427, 36); + this.SearchAbortButton.Name = "SearchAbortButton"; + this.SearchAbortButton.Size = new System.Drawing.Size(75, 23); + this.SearchAbortButton.TabIndex = 43; + this.SearchAbortButton.Text = "Abort"; + this.SearchAbortButton.UseVisualStyleBackColor = true; + this.SearchAbortButton.Click += new System.EventHandler(this.SearchAbortButton_Click); + // + // SearchResultsTextBox + // + this.SearchResultsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SearchResultsTextBox.Location = new System.Drawing.Point(14, 64); + this.SearchResultsTextBox.Multiline = true; + this.SearchResultsTextBox.Name = "SearchResultsTextBox"; + this.SearchResultsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.SearchResultsTextBox.Size = new System.Drawing.Size(487, 247); + this.SearchResultsTextBox.TabIndex = 42; + this.SearchResultsTextBox.WordWrap = false; + // + // BinSearchTextBox + // + this.BinSearchTextBox.Location = new System.Drawing.Point(221, 38); + this.BinSearchTextBox.Name = "BinSearchTextBox"; + this.BinSearchTextBox.Size = new System.Drawing.Size(119, 20); + this.BinSearchTextBox.TabIndex = 41; + this.BinSearchTextBox.Text = "4a03746e"; + // + // BinSearchFolderBrowseButton + // + this.BinSearchFolderBrowseButton.Location = new System.Drawing.Point(346, 10); + this.BinSearchFolderBrowseButton.Name = "BinSearchFolderBrowseButton"; + this.BinSearchFolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.BinSearchFolderBrowseButton.TabIndex = 40; + this.BinSearchFolderBrowseButton.Text = "..."; + this.BinSearchFolderBrowseButton.UseVisualStyleBackColor = true; + this.BinSearchFolderBrowseButton.Click += new System.EventHandler(this.BinSearchFolderBrowseButton_Click); + // + // BinSearchButton + // + this.BinSearchButton.Location = new System.Drawing.Point(346, 36); + this.BinSearchButton.Name = "BinSearchButton"; + this.BinSearchButton.Size = new System.Drawing.Size(75, 23); + this.BinSearchButton.TabIndex = 39; + this.BinSearchButton.Text = "Search"; + this.BinSearchButton.UseVisualStyleBackColor = true; + this.BinSearchButton.Click += new System.EventHandler(this.BinSearchButton_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(11, 15); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(76, 13); + this.label2.TabIndex = 38; + this.label2.Text = "Binary Search:"; + // + // BinSearchFolderTextBox + // + this.BinSearchFolderTextBox.Location = new System.Drawing.Point(89, 12); + this.BinSearchFolderTextBox.Name = "BinSearchFolderTextBox"; + this.BinSearchFolderTextBox.Size = new System.Drawing.Size(251, 20); + this.BinSearchFolderTextBox.TabIndex = 37; + this.BinSearchFolderTextBox.Text = "Compiled944"; + // + // BinarySearchForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(513, 323); + this.Controls.Add(this.TextRadio); + this.Controls.Add(this.HexRadio); + this.Controls.Add(this.SearchAbortButton); + this.Controls.Add(this.SearchResultsTextBox); + this.Controls.Add(this.BinSearchTextBox); + this.Controls.Add(this.BinSearchFolderBrowseButton); + this.Controls.Add(this.BinSearchButton); + this.Controls.Add(this.label2); + this.Controls.Add(this.BinSearchFolderTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "BinarySearchForm"; + this.Text = "Binary Search - CodeWalker by dexyfex"; + this.Load += new System.EventHandler(this.SearchForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.RadioButton TextRadio; + private System.Windows.Forms.RadioButton HexRadio; + private System.Windows.Forms.Button SearchAbortButton; + private System.Windows.Forms.TextBox SearchResultsTextBox; + private System.Windows.Forms.TextBox BinSearchTextBox; + private System.Windows.Forms.Button BinSearchFolderBrowseButton; + private System.Windows.Forms.Button BinSearchButton; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox BinSearchFolderTextBox; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + } +} \ No newline at end of file diff --git a/BinarySearchForm.cs b/BinarySearchForm.cs new file mode 100644 index 0000000..26ce92b --- /dev/null +++ b/BinarySearchForm.cs @@ -0,0 +1,177 @@ +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class BinarySearchForm : Form + { + private volatile bool InProgress = false; + private volatile bool AbortOperation = false; + + public BinarySearchForm() + { + InitializeComponent(); + } + + private void SearchForm_Load(object sender, EventArgs e) + { + BinSearchFolderTextBox.Text = Settings.Default.CompiledScriptFolder; + } + + + private void BinSearchFolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = BinSearchFolderTextBox.Text; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + BinSearchFolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void BinSearchButton_Click(object sender, EventArgs e) + { + string searchtxt = BinSearchTextBox.Text; + string searchfolder = BinSearchFolderTextBox.Text; + AbortOperation = false; + + if (InProgress) return; + if (searchfolder.Length == 0) + { + MessageBox.Show("Please select a folder..."); + return; + } + if (!Directory.Exists(searchfolder)) + { + MessageBox.Show("Please select a valid folder!"); + return; + } + + SearchResultsTextBox.Clear(); + + byte[] searchbytes1; + byte[] searchbytes2; + int bytelen; + + if (HexRadio.Checked) + { + try + { + bytelen = searchtxt.Length / 2; + searchbytes1 = new byte[bytelen]; + searchbytes2 = new byte[bytelen]; + for (int i = 0; i < bytelen; i++) + { + searchbytes1[i] = Convert.ToByte(searchtxt.Substring(i * 2, 2), 16); + searchbytes2[bytelen - i - 1] = searchbytes1[i]; + } + } + catch + { + MessageBox.Show("Please enter a valid hex string."); + return; + } + } + else + { + bytelen = searchtxt.Length; + searchbytes1 = new byte[bytelen]; + searchbytes2 = new byte[bytelen]; + for (int i = 0; i < bytelen; i++) + { + searchbytes1[i] = (byte)searchtxt[i]; + searchbytes2[bytelen - i - 1] = searchbytes1[i]; + } + } + + InProgress = true; + + Task.Run(() => + { + + AddSearchResult("Searching " + searchfolder + "..."); + + string[] filenames = Directory.GetFiles(searchfolder); + + int matchcount = 0; + + foreach (string filename in filenames) + { + + + FileInfo finf = new FileInfo(filename); + byte[] filebytes = File.ReadAllBytes(filename); + + int hitlen1 = 0; + int hitlen2 = 0; + + for (int i = 0; i < filebytes.Length; i++) + { + byte b = filebytes[i]; + byte b1 = searchbytes1[hitlen1]; //current test byte 1 + byte b2 = searchbytes2[hitlen2]; + + if (b == b1) hitlen1++; else hitlen1 = 0; + if (b == b2) hitlen2++; else hitlen2 = 0; + + if (hitlen1 == bytelen) + { + AddSearchResult(finf.Name + ":" + (i - bytelen)); + matchcount++; + hitlen1 = 0; + } + if (hitlen2 == bytelen) + { + AddSearchResult(finf.Name + ":" + (i - bytelen)); + matchcount++; + hitlen2 = 0; + } + + if (AbortOperation) + { + InProgress = false; + AddSearchResult("Search aborted."); + return; + } + + } + + } + + AddSearchResult(string.Format("Search complete. {0} results found.", matchcount)); + InProgress = false; + }); + } + + private void AddSearchResult(string result) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { AddSearchResult(result); })); + } + else + { + SearchResultsTextBox.AppendText(result + "\r\n"); + } + } + catch { } + } + + private void SearchAbortButton_Click(object sender, EventArgs e) + { + AbortOperation = true; + } + + } +} diff --git a/BinarySearchForm.resx b/BinarySearchForm.resx new file mode 100644 index 0000000..bd12579 --- /dev/null +++ b/BinarySearchForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/BrowseForm.Designer.cs b/BrowseForm.Designer.cs new file mode 100644 index 0000000..6d53b64 --- /dev/null +++ b/BrowseForm.Designer.cs @@ -0,0 +1,846 @@ +namespace CodeWalker +{ + partial class BrowseForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BrowseForm)); + this.label1 = new System.Windows.Forms.Label(); + this.FolderBrowseButton = new System.Windows.Forms.Button(); + this.FolderTextBox = new System.Windows.Forms.TextBox(); + this.ScanButton = new System.Windows.Forms.Button(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.FlattenStructureCheckBox = new System.Windows.Forms.CheckBox(); + this.FindButton = new System.Windows.Forms.Button(); + this.MainTreeView = new System.Windows.Forms.TreeView(); + this.label2 = new System.Windows.Forms.Label(); + this.FindTextBox = new System.Windows.Forms.TextBox(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.SearchSaveResultsButton = new System.Windows.Forms.Button(); + this.SearchIgnoreTextBox = new System.Windows.Forms.TextBox(); + this.SearchIgnoreCheckBox = new System.Windows.Forms.CheckBox(); + this.SearchBothDirectionsCheckBox = new System.Windows.Forms.CheckBox(); + this.SearchCaseSensitiveCheckBox = new System.Windows.Forms.CheckBox(); + this.SearchHexRadioButton = new System.Windows.Forms.RadioButton(); + this.SearchTextRadioButton = new System.Windows.Forms.RadioButton(); + this.SearchResultsListView = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SearchAbortButton = new System.Windows.Forms.Button(); + this.SearchButton = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.SearchTextBox = new System.Windows.Forms.TextBox(); + this.ExportCompressCheckBox = new System.Windows.Forms.CheckBox(); + this.ExportButton = new System.Windows.Forms.Button(); + this.FileInfoLabel = new System.Windows.Forms.Label(); + this.SelectionTabControl = new System.Windows.Forms.TabControl(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.ShowLargeFileContentsCheckBox = new System.Windows.Forms.CheckBox(); + this.DataHexLineCombo = new System.Windows.Forms.ComboBox(); + this.DataTextRadio = new System.Windows.Forms.RadioButton(); + this.DataHexRadio = new System.Windows.Forms.RadioButton(); + this.DataTextBox = new System.Windows.Forms.TextBox(); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.DetailsPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.TexturesTabPage = new System.Windows.Forms.TabPage(); + this.splitContainer2 = new System.Windows.Forms.SplitContainer(); + this.SelTexturesListView = new System.Windows.Forms.ListView(); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SelTextureMipLabel = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.SelTextureDimensionsLabel = new System.Windows.Forms.Label(); + this.SelTextureMipTrackBar = new System.Windows.Forms.TrackBar(); + this.label4 = new System.Windows.Forms.Label(); + this.SelTextureNameTextBox = new System.Windows.Forms.TextBox(); + this.SelTexturePictureBox = new System.Windows.Forms.PictureBox(); + this.MainStatusStrip = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.TestAllButton = new System.Windows.Forms.Button(); + this.AbortButton = new System.Windows.Forms.Button(); + this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.SelectionTabControl.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.tabPage4.SuspendLayout(); + this.TexturesTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); + this.splitContainer2.Panel1.SuspendLayout(); + this.splitContainer2.Panel2.SuspendLayout(); + this.splitContainer2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.SelTextureMipTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.SelTexturePictureBox)).BeginInit(); + this.MainStatusStrip.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(68, 13); + this.label1.TabIndex = 47; + this.label1.Text = "GTAV folder:"; + // + // FolderBrowseButton + // + this.FolderBrowseButton.Location = new System.Drawing.Point(347, 4); + this.FolderBrowseButton.Name = "FolderBrowseButton"; + this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.FolderBrowseButton.TabIndex = 2; + this.FolderBrowseButton.Text = "..."; + this.FolderBrowseButton.UseVisualStyleBackColor = true; + this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click); + // + // FolderTextBox + // + this.FolderTextBox.Location = new System.Drawing.Point(90, 6); + this.FolderTextBox.Name = "FolderTextBox"; + this.FolderTextBox.Size = new System.Drawing.Size(251, 20); + this.FolderTextBox.TabIndex = 1; + this.FolderTextBox.TextChanged += new System.EventHandler(this.FolderTextBox_TextChanged); + // + // ScanButton + // + this.ScanButton.Location = new System.Drawing.Point(380, 4); + this.ScanButton.Name = "ScanButton"; + this.ScanButton.Size = new System.Drawing.Size(75, 23); + this.ScanButton.TabIndex = 0; + this.ScanButton.Text = "Scan"; + this.ScanButton.UseVisualStyleBackColor = true; + this.ScanButton.Click += new System.EventHandler(this.ScanButton_Click); + // + // splitContainer1 + // + this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer1.Location = new System.Drawing.Point(0, 32); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.tabControl1); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.ExportCompressCheckBox); + this.splitContainer1.Panel2.Controls.Add(this.ExportButton); + this.splitContainer1.Panel2.Controls.Add(this.FileInfoLabel); + this.splitContainer1.Panel2.Controls.Add(this.SelectionTabControl); + this.splitContainer1.Size = new System.Drawing.Size(855, 492); + this.splitContainer1.SplitterDistance = 281; + this.splitContainer1.TabIndex = 5; + // + // tabControl1 + // + this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Location = new System.Drawing.Point(0, 3); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(278, 489); + this.tabControl1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.FlattenStructureCheckBox); + this.tabPage1.Controls.Add(this.FindButton); + this.tabPage1.Controls.Add(this.MainTreeView); + this.tabPage1.Controls.Add(this.label2); + this.tabPage1.Controls.Add(this.FindTextBox); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(270, 463); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Browse"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // FlattenStructureCheckBox + // + this.FlattenStructureCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.FlattenStructureCheckBox.AutoSize = true; + this.FlattenStructureCheckBox.Location = new System.Drawing.Point(3, 443); + this.FlattenStructureCheckBox.Name = "FlattenStructureCheckBox"; + this.FlattenStructureCheckBox.Size = new System.Drawing.Size(128, 17); + this.FlattenStructureCheckBox.TabIndex = 50; + this.FlattenStructureCheckBox.Text = "Flatten RPF Structure"; + this.FlattenStructureCheckBox.UseVisualStyleBackColor = true; + this.FlattenStructureCheckBox.CheckedChanged += new System.EventHandler(this.FlattenStructureCheckBox_CheckedChanged); + // + // FindButton + // + this.FindButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.FindButton.Location = new System.Drawing.Point(240, 4); + this.FindButton.Name = "FindButton"; + this.FindButton.Size = new System.Drawing.Size(27, 22); + this.FindButton.TabIndex = 11; + this.FindButton.Text = ">"; + this.FindButton.UseVisualStyleBackColor = true; + this.FindButton.Click += new System.EventHandler(this.FindButton_Click); + // + // MainTreeView + // + this.MainTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTreeView.HideSelection = false; + this.MainTreeView.Location = new System.Drawing.Point(0, 32); + this.MainTreeView.Name = "MainTreeView"; + this.MainTreeView.Size = new System.Drawing.Size(267, 408); + this.MainTreeView.TabIndex = 12; + this.MainTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.MainTreeView_AfterSelect); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(4, 8); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(30, 13); + this.label2.TabIndex = 49; + this.label2.Text = "Find:"; + // + // FindTextBox + // + this.FindTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FindTextBox.Location = new System.Drawing.Point(38, 5); + this.FindTextBox.Name = "FindTextBox"; + this.FindTextBox.Size = new System.Drawing.Size(199, 20); + this.FindTextBox.TabIndex = 10; + this.FindTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.FindTextBox_KeyPress); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.SearchSaveResultsButton); + this.tabPage2.Controls.Add(this.SearchIgnoreTextBox); + this.tabPage2.Controls.Add(this.SearchIgnoreCheckBox); + this.tabPage2.Controls.Add(this.SearchBothDirectionsCheckBox); + this.tabPage2.Controls.Add(this.SearchCaseSensitiveCheckBox); + this.tabPage2.Controls.Add(this.SearchHexRadioButton); + this.tabPage2.Controls.Add(this.SearchTextRadioButton); + this.tabPage2.Controls.Add(this.SearchResultsListView); + this.tabPage2.Controls.Add(this.SearchAbortButton); + this.tabPage2.Controls.Add(this.SearchButton); + this.tabPage2.Controls.Add(this.label3); + this.tabPage2.Controls.Add(this.SearchTextBox); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(270, 463); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Search"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // SearchSaveResultsButton + // + this.SearchSaveResultsButton.Enabled = false; + this.SearchSaveResultsButton.Location = new System.Drawing.Point(178, 95); + this.SearchSaveResultsButton.Name = "SearchSaveResultsButton"; + this.SearchSaveResultsButton.Size = new System.Drawing.Size(86, 22); + this.SearchSaveResultsButton.TabIndex = 19; + this.SearchSaveResultsButton.Text = "Save results..."; + this.SearchSaveResultsButton.UseVisualStyleBackColor = true; + this.SearchSaveResultsButton.Click += new System.EventHandler(this.SearchSaveResultsButton_Click); + // + // SearchIgnoreTextBox + // + this.SearchIgnoreTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SearchIgnoreTextBox.Location = new System.Drawing.Point(65, 70); + this.SearchIgnoreTextBox.Name = "SearchIgnoreTextBox"; + this.SearchIgnoreTextBox.Size = new System.Drawing.Size(202, 20); + this.SearchIgnoreTextBox.TabIndex = 16; + this.SearchIgnoreTextBox.Text = ".ydr, .ydd, .ytd, .yft, .ybn, .ycd, .awc, .bik"; + // + // SearchIgnoreCheckBox + // + this.SearchIgnoreCheckBox.AutoSize = true; + this.SearchIgnoreCheckBox.Checked = true; + this.SearchIgnoreCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.SearchIgnoreCheckBox.Location = new System.Drawing.Point(6, 72); + this.SearchIgnoreCheckBox.Name = "SearchIgnoreCheckBox"; + this.SearchIgnoreCheckBox.Size = new System.Drawing.Size(59, 17); + this.SearchIgnoreCheckBox.TabIndex = 15; + this.SearchIgnoreCheckBox.Text = "Ignore:"; + this.SearchIgnoreCheckBox.UseVisualStyleBackColor = true; + this.SearchIgnoreCheckBox.CheckedChanged += new System.EventHandler(this.SearchIgnoreCheckBox_CheckedChanged); + // + // SearchBothDirectionsCheckBox + // + this.SearchBothDirectionsCheckBox.AutoSize = true; + this.SearchBothDirectionsCheckBox.Checked = true; + this.SearchBothDirectionsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.SearchBothDirectionsCheckBox.Location = new System.Drawing.Point(106, 50); + this.SearchBothDirectionsCheckBox.Name = "SearchBothDirectionsCheckBox"; + this.SearchBothDirectionsCheckBox.Size = new System.Drawing.Size(96, 17); + this.SearchBothDirectionsCheckBox.TabIndex = 14; + this.SearchBothDirectionsCheckBox.Text = "Both directions"; + this.SearchBothDirectionsCheckBox.UseVisualStyleBackColor = true; + // + // SearchCaseSensitiveCheckBox + // + this.SearchCaseSensitiveCheckBox.AutoSize = true; + this.SearchCaseSensitiveCheckBox.Location = new System.Drawing.Point(6, 50); + this.SearchCaseSensitiveCheckBox.Name = "SearchCaseSensitiveCheckBox"; + this.SearchCaseSensitiveCheckBox.Size = new System.Drawing.Size(94, 17); + this.SearchCaseSensitiveCheckBox.TabIndex = 13; + this.SearchCaseSensitiveCheckBox.Text = "Case-sensitive"; + this.SearchCaseSensitiveCheckBox.UseVisualStyleBackColor = true; + // + // SearchHexRadioButton + // + this.SearchHexRadioButton.AutoSize = true; + this.SearchHexRadioButton.Location = new System.Drawing.Point(155, 7); + this.SearchHexRadioButton.Name = "SearchHexRadioButton"; + this.SearchHexRadioButton.Size = new System.Drawing.Size(44, 17); + this.SearchHexRadioButton.TabIndex = 12; + this.SearchHexRadioButton.Text = "Hex"; + this.SearchHexRadioButton.UseVisualStyleBackColor = true; + this.SearchHexRadioButton.CheckedChanged += new System.EventHandler(this.SearchHexRadioButton_CheckedChanged); + // + // SearchTextRadioButton + // + this.SearchTextRadioButton.AutoSize = true; + this.SearchTextRadioButton.Checked = true; + this.SearchTextRadioButton.Location = new System.Drawing.Point(103, 7); + this.SearchTextRadioButton.Name = "SearchTextRadioButton"; + this.SearchTextRadioButton.Size = new System.Drawing.Size(46, 17); + this.SearchTextRadioButton.TabIndex = 11; + this.SearchTextRadioButton.TabStop = true; + this.SearchTextRadioButton.Text = "Text"; + this.SearchTextRadioButton.UseVisualStyleBackColor = true; + this.SearchTextRadioButton.CheckedChanged += new System.EventHandler(this.SearchTextRadioButton_CheckedChanged); + // + // SearchResultsListView + // + this.SearchResultsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SearchResultsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.SearchResultsListView.FullRowSelect = true; + this.SearchResultsListView.HideSelection = false; + this.SearchResultsListView.Location = new System.Drawing.Point(0, 123); + this.SearchResultsListView.MultiSelect = false; + this.SearchResultsListView.Name = "SearchResultsListView"; + this.SearchResultsListView.Size = new System.Drawing.Size(267, 340); + this.SearchResultsListView.TabIndex = 20; + this.SearchResultsListView.UseCompatibleStateImageBehavior = false; + this.SearchResultsListView.View = System.Windows.Forms.View.Details; + this.SearchResultsListView.VirtualMode = true; + this.SearchResultsListView.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.SearchResultsListView_RetrieveVirtualItem); + this.SearchResultsListView.SelectedIndexChanged += new System.EventHandler(this.SearchResultsListView_SelectedIndexChanged); + // + // columnHeader1 + // + this.columnHeader1.Text = "File"; + this.columnHeader1.Width = 176; + // + // columnHeader2 + // + this.columnHeader2.Text = "Offset"; + // + // SearchAbortButton + // + this.SearchAbortButton.Location = new System.Drawing.Point(87, 95); + this.SearchAbortButton.Name = "SearchAbortButton"; + this.SearchAbortButton.Size = new System.Drawing.Size(75, 22); + this.SearchAbortButton.TabIndex = 18; + this.SearchAbortButton.Text = "Abort"; + this.SearchAbortButton.UseVisualStyleBackColor = true; + this.SearchAbortButton.Click += new System.EventHandler(this.SearchAbortButton_Click); + // + // SearchButton + // + this.SearchButton.Location = new System.Drawing.Point(6, 95); + this.SearchButton.Name = "SearchButton"; + this.SearchButton.Size = new System.Drawing.Size(75, 22); + this.SearchButton.TabIndex = 17; + this.SearchButton.Text = "Search"; + this.SearchButton.UseVisualStyleBackColor = true; + this.SearchButton.Click += new System.EventHandler(this.SearchButton_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(4, 9); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(91, 13); + this.label3.TabIndex = 52; + this.label3.Text = "Search in files for:"; + // + // SearchTextBox + // + this.SearchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SearchTextBox.Location = new System.Drawing.Point(3, 27); + this.SearchTextBox.Name = "SearchTextBox"; + this.SearchTextBox.Size = new System.Drawing.Size(264, 20); + this.SearchTextBox.TabIndex = 10; + // + // ExportCompressCheckBox + // + this.ExportCompressCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ExportCompressCheckBox.AutoSize = true; + this.ExportCompressCheckBox.Location = new System.Drawing.Point(414, 5); + this.ExportCompressCheckBox.Name = "ExportCompressCheckBox"; + this.ExportCompressCheckBox.Size = new System.Drawing.Size(72, 17); + this.ExportCompressCheckBox.TabIndex = 105; + this.ExportCompressCheckBox.Text = "Compress"; + this.ExportCompressCheckBox.UseVisualStyleBackColor = true; + // + // ExportButton + // + this.ExportButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ExportButton.Location = new System.Drawing.Point(488, 2); + this.ExportButton.Name = "ExportButton"; + this.ExportButton.Size = new System.Drawing.Size(75, 23); + this.ExportButton.TabIndex = 104; + this.ExportButton.Text = "Export..."; + this.ExportButton.UseVisualStyleBackColor = true; + this.ExportButton.Click += new System.EventHandler(this.ExportButton_Click); + // + // FileInfoLabel + // + this.FileInfoLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FileInfoLabel.AutoEllipsis = true; + this.FileInfoLabel.Location = new System.Drawing.Point(7, 6); + this.FileInfoLabel.Name = "FileInfoLabel"; + this.FileInfoLabel.Size = new System.Drawing.Size(401, 16); + this.FileInfoLabel.TabIndex = 51; + this.FileInfoLabel.Text = "[Nothing selected]"; + // + // SelectionTabControl + // + this.SelectionTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectionTabControl.Controls.Add(this.tabPage3); + this.SelectionTabControl.Controls.Add(this.tabPage4); + this.SelectionTabControl.Controls.Add(this.TexturesTabPage); + this.SelectionTabControl.Location = new System.Drawing.Point(3, 30); + this.SelectionTabControl.Name = "SelectionTabControl"; + this.SelectionTabControl.SelectedIndex = 0; + this.SelectionTabControl.Size = new System.Drawing.Size(564, 462); + this.SelectionTabControl.TabIndex = 0; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.ShowLargeFileContentsCheckBox); + this.tabPage3.Controls.Add(this.DataHexLineCombo); + this.tabPage3.Controls.Add(this.DataTextRadio); + this.tabPage3.Controls.Add(this.DataHexRadio); + this.tabPage3.Controls.Add(this.DataTextBox); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(556, 436); + this.tabPage3.TabIndex = 0; + this.tabPage3.Text = "Data"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // ShowLargeFileContentsCheckBox + // + this.ShowLargeFileContentsCheckBox.AutoSize = true; + this.ShowLargeFileContentsCheckBox.Location = new System.Drawing.Point(395, 7); + this.ShowLargeFileContentsCheckBox.Name = "ShowLargeFileContentsCheckBox"; + this.ShowLargeFileContentsCheckBox.Size = new System.Drawing.Size(139, 17); + this.ShowLargeFileContentsCheckBox.TabIndex = 104; + this.ShowLargeFileContentsCheckBox.Text = "Show large file contents"; + this.ShowLargeFileContentsCheckBox.UseVisualStyleBackColor = true; + this.ShowLargeFileContentsCheckBox.CheckedChanged += new System.EventHandler(this.ShowLargeFileContentsCheckBox_CheckedChanged); + // + // DataHexLineCombo + // + this.DataHexLineCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.DataHexLineCombo.FormattingEnabled = true; + this.DataHexLineCombo.Items.AddRange(new object[] { + "8", + "16", + "32"}); + this.DataHexLineCombo.Location = new System.Drawing.Point(56, 5); + this.DataHexLineCombo.Name = "DataHexLineCombo"; + this.DataHexLineCombo.Size = new System.Drawing.Size(49, 21); + this.DataHexLineCombo.TabIndex = 101; + this.DataHexLineCombo.SelectedIndexChanged += new System.EventHandler(this.DataHexLineCombo_SelectedIndexChanged); + // + // DataTextRadio + // + this.DataTextRadio.AutoSize = true; + this.DataTextRadio.Location = new System.Drawing.Point(176, 6); + this.DataTextRadio.Name = "DataTextRadio"; + this.DataTextRadio.Size = new System.Drawing.Size(46, 17); + this.DataTextRadio.TabIndex = 102; + this.DataTextRadio.Text = "Text"; + this.DataTextRadio.UseVisualStyleBackColor = true; + this.DataTextRadio.CheckedChanged += new System.EventHandler(this.DataTextRadio_CheckedChanged); + // + // DataHexRadio + // + this.DataHexRadio.AutoSize = true; + this.DataHexRadio.Checked = true; + this.DataHexRadio.Location = new System.Drawing.Point(6, 6); + this.DataHexRadio.Name = "DataHexRadio"; + this.DataHexRadio.Size = new System.Drawing.Size(44, 17); + this.DataHexRadio.TabIndex = 100; + this.DataHexRadio.TabStop = true; + this.DataHexRadio.Text = "Hex"; + this.DataHexRadio.UseVisualStyleBackColor = true; + this.DataHexRadio.CheckedChanged += new System.EventHandler(this.DataHexRadio_CheckedChanged); + // + // DataTextBox + // + this.DataTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.DataTextBox.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.DataTextBox.HideSelection = false; + this.DataTextBox.Location = new System.Drawing.Point(6, 29); + this.DataTextBox.Multiline = true; + this.DataTextBox.Name = "DataTextBox"; + this.DataTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.DataTextBox.Size = new System.Drawing.Size(544, 401); + this.DataTextBox.TabIndex = 103; + this.DataTextBox.Text = "[Please select a data file]"; + this.DataTextBox.WordWrap = false; + // + // tabPage4 + // + this.tabPage4.Controls.Add(this.DetailsPropertyGrid); + this.tabPage4.Location = new System.Drawing.Point(4, 22); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Padding = new System.Windows.Forms.Padding(3); + this.tabPage4.Size = new System.Drawing.Size(556, 436); + this.tabPage4.TabIndex = 1; + this.tabPage4.Text = "Details"; + this.tabPage4.UseVisualStyleBackColor = true; + // + // DetailsPropertyGrid + // + this.DetailsPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.DetailsPropertyGrid.Location = new System.Drawing.Point(6, 6); + this.DetailsPropertyGrid.Name = "DetailsPropertyGrid"; + this.DetailsPropertyGrid.Size = new System.Drawing.Size(544, 424); + this.DetailsPropertyGrid.TabIndex = 104; + // + // TexturesTabPage + // + this.TexturesTabPage.Controls.Add(this.splitContainer2); + this.TexturesTabPage.Location = new System.Drawing.Point(4, 22); + this.TexturesTabPage.Name = "TexturesTabPage"; + this.TexturesTabPage.Size = new System.Drawing.Size(556, 436); + this.TexturesTabPage.TabIndex = 2; + this.TexturesTabPage.Text = "Textures"; + this.TexturesTabPage.UseVisualStyleBackColor = true; + // + // splitContainer2 + // + this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer2.Location = new System.Drawing.Point(0, 0); + this.splitContainer2.Name = "splitContainer2"; + // + // splitContainer2.Panel1 + // + this.splitContainer2.Panel1.Controls.Add(this.SelTexturesListView); + // + // splitContainer2.Panel2 + // + this.splitContainer2.Panel2.Controls.Add(this.SelTextureMipLabel); + this.splitContainer2.Panel2.Controls.Add(this.label5); + this.splitContainer2.Panel2.Controls.Add(this.SelTextureDimensionsLabel); + this.splitContainer2.Panel2.Controls.Add(this.SelTextureMipTrackBar); + this.splitContainer2.Panel2.Controls.Add(this.label4); + this.splitContainer2.Panel2.Controls.Add(this.SelTextureNameTextBox); + this.splitContainer2.Panel2.Controls.Add(this.SelTexturePictureBox); + this.splitContainer2.Size = new System.Drawing.Size(556, 436); + this.splitContainer2.SplitterDistance = 177; + this.splitContainer2.TabIndex = 0; + // + // SelTexturesListView + // + this.SelTexturesListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelTexturesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader5}); + this.SelTexturesListView.FullRowSelect = true; + this.SelTexturesListView.HideSelection = false; + this.SelTexturesListView.Location = new System.Drawing.Point(3, 3); + this.SelTexturesListView.MultiSelect = false; + this.SelTexturesListView.Name = "SelTexturesListView"; + this.SelTexturesListView.Size = new System.Drawing.Size(171, 430); + this.SelTexturesListView.TabIndex = 21; + this.SelTexturesListView.UseCompatibleStateImageBehavior = false; + this.SelTexturesListView.View = System.Windows.Forms.View.Details; + this.SelTexturesListView.SelectedIndexChanged += new System.EventHandler(this.SelTexturesListView_SelectedIndexChanged); + // + // columnHeader5 + // + this.columnHeader5.Text = "Texture"; + this.columnHeader5.Width = 146; + // + // SelTextureMipLabel + // + this.SelTextureMipLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.SelTextureMipLabel.AutoSize = true; + this.SelTextureMipLabel.Location = new System.Drawing.Point(41, 401); + this.SelTextureMipLabel.Name = "SelTextureMipLabel"; + this.SelTextureMipLabel.Size = new System.Drawing.Size(13, 13); + this.SelTextureMipLabel.TabIndex = 44; + this.SelTextureMipLabel.Text = "0"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(10, 10); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(38, 13); + this.label5.TabIndex = 43; + this.label5.Text = "Name:"; + // + // SelTextureDimensionsLabel + // + this.SelTextureDimensionsLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.SelTextureDimensionsLabel.AutoSize = true; + this.SelTextureDimensionsLabel.Location = new System.Drawing.Point(301, 401); + this.SelTextureDimensionsLabel.Name = "SelTextureDimensionsLabel"; + this.SelTextureDimensionsLabel.Size = new System.Drawing.Size(10, 13); + this.SelTextureDimensionsLabel.TabIndex = 42; + this.SelTextureDimensionsLabel.Text = "-"; + // + // SelTextureMipTrackBar + // + this.SelTextureMipTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelTextureMipTrackBar.AutoSize = false; + this.SelTextureMipTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.SelTextureMipTrackBar.LargeChange = 1; + this.SelTextureMipTrackBar.Location = new System.Drawing.Point(60, 395); + this.SelTextureMipTrackBar.Maximum = 0; + this.SelTextureMipTrackBar.Name = "SelTextureMipTrackBar"; + this.SelTextureMipTrackBar.Size = new System.Drawing.Size(234, 31); + this.SelTextureMipTrackBar.TabIndex = 41; + this.SelTextureMipTrackBar.Scroll += new System.EventHandler(this.SelTextureMipTrackBar_Scroll); + // + // label4 + // + this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(10, 401); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(27, 13); + this.label4.TabIndex = 40; + this.label4.Text = "Mip:"; + // + // SelTextureNameTextBox + // + this.SelTextureNameTextBox.Location = new System.Drawing.Point(60, 7); + this.SelTextureNameTextBox.Name = "SelTextureNameTextBox"; + this.SelTextureNameTextBox.Size = new System.Drawing.Size(192, 20); + this.SelTextureNameTextBox.TabIndex = 39; + // + // SelTexturePictureBox + // + this.SelTexturePictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelTexturePictureBox.BackColor = System.Drawing.Color.DarkGray; + this.SelTexturePictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.SelTexturePictureBox.Location = new System.Drawing.Point(3, 33); + this.SelTexturePictureBox.Name = "SelTexturePictureBox"; + this.SelTexturePictureBox.Size = new System.Drawing.Size(369, 351); + this.SelTexturePictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.SelTexturePictureBox.TabIndex = 38; + this.SelTexturePictureBox.TabStop = false; + // + // MainStatusStrip + // + this.MainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel}); + this.MainStatusStrip.Location = new System.Drawing.Point(0, 527); + this.MainStatusStrip.Name = "MainStatusStrip"; + this.MainStatusStrip.Size = new System.Drawing.Size(855, 22); + this.MainStatusStrip.TabIndex = 50; + this.MainStatusStrip.Text = "statusStrip1"; + // + // StatusLabel + // + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(840, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.Text = "Scan the GTAV folder to begin."; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // TestAllButton + // + this.TestAllButton.Location = new System.Drawing.Point(537, 4); + this.TestAllButton.Name = "TestAllButton"; + this.TestAllButton.Size = new System.Drawing.Size(75, 23); + this.TestAllButton.TabIndex = 3; + this.TestAllButton.Text = "Test all files"; + this.TestAllButton.UseVisualStyleBackColor = true; + this.TestAllButton.Click += new System.EventHandler(this.TestAllButton_Click); + // + // AbortButton + // + this.AbortButton.Location = new System.Drawing.Point(618, 4); + this.AbortButton.Name = "AbortButton"; + this.AbortButton.Size = new System.Drawing.Size(75, 23); + this.AbortButton.TabIndex = 4; + this.AbortButton.Text = "Abort"; + this.AbortButton.UseVisualStyleBackColor = true; + this.AbortButton.Click += new System.EventHandler(this.AbortButton_Click); + // + // SaveFileDialog + // + this.SaveFileDialog.AddExtension = false; + // + // BrowseForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(855, 549); + this.Controls.Add(this.AbortButton); + this.Controls.Add(this.TestAllButton); + this.Controls.Add(this.MainStatusStrip); + this.Controls.Add(this.splitContainer1); + this.Controls.Add(this.ScanButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.FolderBrowseButton); + this.Controls.Add(this.FolderTextBox); + this.DoubleBuffered = true; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "BrowseForm"; + this.Text = "RPF Browser - CodeWalker by dexyfex"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.BrowseForm_FormClosed); + this.Load += new System.EventHandler(this.BrowseForm_Load); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + this.splitContainer1.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage1.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.tabPage2.PerformLayout(); + this.SelectionTabControl.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + this.tabPage4.ResumeLayout(false); + this.TexturesTabPage.ResumeLayout(false); + this.splitContainer2.Panel1.ResumeLayout(false); + this.splitContainer2.Panel2.ResumeLayout(false); + this.splitContainer2.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); + this.splitContainer2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.SelTextureMipTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.SelTexturePictureBox)).EndInit(); + this.MainStatusStrip.ResumeLayout(false); + this.MainStatusStrip.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button FolderBrowseButton; + private System.Windows.Forms.TextBox FolderTextBox; + private System.Windows.Forms.Button ScanButton; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.TreeView MainTreeView; + private System.Windows.Forms.StatusStrip MainStatusStrip; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabControl SelectionTabControl; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.TabPage tabPage4; + private System.Windows.Forms.RadioButton DataTextRadio; + private System.Windows.Forms.RadioButton DataHexRadio; + private System.Windows.Forms.TextBox DataTextBox; + private System.Windows.Forms.ComboBox DataHexLineCombo; + private System.Windows.Forms.Label FileInfoLabel; + private System.Windows.Forms.Button TestAllButton; + private System.Windows.Forms.Button AbortButton; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox FindTextBox; + private System.Windows.Forms.Button FindButton; + private System.Windows.Forms.Button ExportButton; + private System.Windows.Forms.SaveFileDialog SaveFileDialog; + private CodeWalker.WinForms.PropertyGridFix DetailsPropertyGrid; + private System.Windows.Forms.Button SearchAbortButton; + private System.Windows.Forms.Button SearchButton; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox SearchTextBox; + private System.Windows.Forms.RadioButton SearchHexRadioButton; + private System.Windows.Forms.RadioButton SearchTextRadioButton; + private System.Windows.Forms.ListView SearchResultsListView; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.CheckBox SearchBothDirectionsCheckBox; + private System.Windows.Forms.CheckBox SearchCaseSensitiveCheckBox; + private System.Windows.Forms.TextBox SearchIgnoreTextBox; + private System.Windows.Forms.CheckBox SearchIgnoreCheckBox; + private System.Windows.Forms.TabPage TexturesTabPage; + private System.Windows.Forms.SplitContainer splitContainer2; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label SelTextureDimensionsLabel; + private System.Windows.Forms.TrackBar SelTextureMipTrackBar; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox SelTextureNameTextBox; + private System.Windows.Forms.PictureBox SelTexturePictureBox; + private System.Windows.Forms.ListView SelTexturesListView; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.Label SelTextureMipLabel; + private System.Windows.Forms.CheckBox ShowLargeFileContentsCheckBox; + private System.Windows.Forms.CheckBox ExportCompressCheckBox; + private System.Windows.Forms.CheckBox FlattenStructureCheckBox; + private System.Windows.Forms.Button SearchSaveResultsButton; + } +} \ No newline at end of file diff --git a/BrowseForm.cs b/BrowseForm.cs new file mode 100644 index 0000000..43513be --- /dev/null +++ b/BrowseForm.cs @@ -0,0 +1,1295 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using CodeWalker.Utils; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class BrowseForm : Form + { + private volatile bool KeysLoaded = false; + private volatile bool InProgress = false; + private volatile bool AbortOperation = false; + + private int TotalFileCount = 0; + private List ScannedFiles = new List(); + private List RootFiles = new List(); + + private List SearchResults = new List(); + private RpfEntry SelectedEntry = null; + private int SelectedOffset = -1; + private int SelectedLength = 0; + + private bool TextureTabPageVisible = false; + + private bool FlatStructure = false; + + public BrowseForm() + { + InitializeComponent(); + } + + private void BrowseForm_Load(object sender, EventArgs e) + { + var info = DetailsPropertyGrid.GetType().GetProperty("Controls"); + var collection = info.GetValue(DetailsPropertyGrid, null) as Control.ControlCollection; + foreach (var control in collection) + { + var ctyp = control.GetType(); + if (ctyp.Name == "PropertyGridView") + { + var prop = ctyp.GetField("labelRatio"); + var val = prop.GetValue(control); + prop.SetValue(control, 4.0); //somehow this sets the width of the property grid's label column... + } + } + + FolderTextBox.Text = Settings.Default.GTAFolder; + DataHexLineCombo.Text = "16"; + + DataTextBox.SetTabStopWidth(3); + + HideTexturesTab(); + + try + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); + KeysLoaded = true; + UpdateStatus("Ready to scan..."); + } + catch + { + UpdateStatus("Keys not loaded! This should not happen."); + } + } + + private void BrowseForm_FormClosed(object sender, FormClosedEventArgs e) + { + if (!TextureTabPageVisible) + { + TexturesTabPage.Dispose(); + } + } + + private void FolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.GTAFolder = FolderTextBox.Text; + } + + private void FolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = Settings.Default.GTAFolder; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + FolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void ScanButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + + if (!KeysLoaded) //this shouldn't ever really happen anymore + { + MessageBox.Show("Please scan a GTA 5 exe dump for keys first, or include key files in this app's folder!"); + return; + } + if (!Directory.Exists(FolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + FolderTextBox.Text); + return; + } + + InProgress = true; + AbortOperation = false; + ScannedFiles.Clear(); + RootFiles.Clear(); + + MainTreeView.Nodes.Clear(); + + string searchpath = FolderTextBox.Text; + string replpath = searchpath + "\\"; + + Task.Run(() => + { + + UpdateStatus("Starting scan..."); + + string[] allfiles = Directory.GetFiles(searchpath, "*.rpf", SearchOption.AllDirectories); + + uint totrpfs = 0; + uint totfiles = 0; + uint totfolders = 0; + uint totresfiles = 0; + uint totbinfiles = 0; + + foreach (string rpfpath in allfiles) + { + if (AbortOperation) + { + UpdateStatus("Scan aborted!"); + InProgress = false; + return; + } + + RpfFile rf = new RpfFile(rpfpath, rpfpath.Replace(replpath, "")); + + UpdateStatus("Scanning " + rf.Name + "..."); + + rf.ScanStructure(UpdateStatus, UpdateStatus); + + totrpfs += rf.GrandTotalRpfCount; + totfiles += rf.GrandTotalFileCount; + totfolders += rf.GrandTotalFolderCount; + totresfiles += rf.GrandTotalResourceCount; + totbinfiles += rf.GrandTotalBinaryFileCount; + + AddScannedFile(rf, null, true); + + RootFiles.Add(rf); + } + + UpdateStatus(string.Format("Scan complete. {0} RPF files, {1} total files, {2} total folders, {3} resources, {4} binary files.", totrpfs, totfiles, totfolders, totresfiles, totbinfiles)); + InProgress = false; + TotalFileCount = (int)totfiles; + }); + + } + + + + private void UpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { UpdateStatus(text); })); + } + else + { + StatusLabel.Text = text; + } + } + catch { } + } + + private void ClearFiles() + { + MainTreeView.Nodes.Clear(); + } + private void AddScannedFile(RpfFile file, TreeNode node, bool addToList = false) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { AddScannedFile(file, node, addToList); })); + } + else + { + + var cnode = AddFileNode(file, node); + + if (FlatStructure) cnode = null; + + foreach (RpfFile cfile in file.Children) + { + AddScannedFile(cfile, cnode, addToList); + } + if (addToList) + { + ScannedFiles.Add(file); + } + } + } + catch { } + } + private TreeNode AddFileNode(RpfFile file, TreeNode n) + { + var nodes = (n == null) ? MainTreeView.Nodes : n.Nodes; + TreeNode node = nodes.Add(file.Path); + node.Tag = file; + + foreach (RpfEntry entry in file.AllEntries) + { + if (entry is RpfFileEntry) + { + bool show = !entry.NameLower.EndsWith(".rpf"); //rpf entries get their own root node.. + if (show) + { + //string text = entry.Path.Substring(file.Path.Length + 1); //includes \ on the end + //TreeNode cnode = node.Nodes.Add(text); + //cnode.Tag = entry; + TreeNode cnode = AddEntryNode(entry, node); + } + } + } + + + //make sure it's all in jenkindex... + JenkIndex.Ensure(file.Name); + foreach (RpfEntry entry in file.AllEntries) + { + if (string.IsNullOrEmpty(entry.Name)) continue; + JenkIndex.Ensure(entry.Name); + JenkIndex.Ensure(entry.NameLower); + int ind = entry.Name.LastIndexOf('.'); + if (ind > 0) + { + JenkIndex.Ensure(entry.Name.Substring(0, ind)); + JenkIndex.Ensure(entry.NameLower.Substring(0, ind)); + } + } + + return node; + + + + + //TreeNode lastNode = null; + //string subPathAgg; + //subPathAgg = string.Empty; + //foreach (string subPath in file.Path.Split('\\')) + //{ + // subPathAgg += subPath + '\\'; + // TreeNode[] nodes = MainTreeView.Nodes.Find(subPathAgg, true); + // if (nodes.Length == 0) + // { + // if (lastNode == null) + // { + // lastNode = MainTreeView.Nodes.Add(subPathAgg, subPath); + // } + // else + // { + // lastNode = lastNode.Nodes.Add(subPathAgg, subPath); + // } + // } + // else + // { + // lastNode = nodes[0]; + // } + //} + //lastNode.Tag = file; + + } + private TreeNode AddEntryNode(RpfEntry entry, TreeNode node) + { + string text = entry.Path.Substring(entry.File.Path.Length + 1); //includes \ on the end + TreeNode cnode = (node != null) ? node.Nodes.Add(text) : MainTreeView.Nodes.Add(text); + cnode.Tag = entry; + return cnode; + } + + + private void MainTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + if (e.Node == null) return; + if (!e.Node.IsSelected) return; //only do this for selected node + if (MainTreeView.SelectedNode == null) return; + + SelectedEntry = MainTreeView.SelectedNode.Tag as RpfEntry; + SelectedOffset = -1; + SelectedLength = 0; + + SelectFile(); + } + private void DataTextRadio_CheckedChanged(object sender, EventArgs e) + { + SelectFile(); + } + private void DataHexLineCombo_SelectedIndexChanged(object sender, EventArgs e) + { + SelectFile(); + } + private void DataHexRadio_CheckedChanged(object sender, EventArgs e) + { + SelectFile(); + } + + + private void SelectFile() + { + SelectFile(SelectedEntry, SelectedOffset, SelectedLength); + } + private void SelectFile(RpfEntry entry, int offset, int length) + { + SelectedEntry = entry; + SelectedOffset = offset; + SelectedLength = length; + + RpfFileEntry rfe = entry as RpfFileEntry; + if (rfe == null) + { + RpfDirectoryEntry rde = entry as RpfDirectoryEntry; + if (rde != null) + { + FileInfoLabel.Text = rde.Path + " (Directory)"; + DataTextBox.Text = "[Please select a data file]"; + } + else + { + FileInfoLabel.Text = "[Nothing selected]"; + DataTextBox.Text = "[Please select a data file]"; + } + ShowTextures(null); + return; + } + + + Cursor = Cursors.WaitCursor; + + string typestr = "Resource"; + if (rfe is RpfBinaryFileEntry) + { + typestr = "Binary"; + } + + byte[] data = rfe.File.ExtractFile(rfe); + + int datalen = (data != null) ? data.Length : 0; + FileInfoLabel.Text = rfe.Path + " (" + typestr + " file) - " + TextUtil.GetBytesReadable(datalen); + + + if (ShowLargeFileContentsCheckBox.Checked || (datalen < 524287)) //512K + { + DisplayFileContentsText(rfe, data, length, offset); + } + else + { + DataTextBox.Text = "[Filesize >512KB. Select the Show large files option to view its contents]"; + } + + + + bool istexdict = false; + + + if (rfe.NameLower.EndsWith(".ymap")) + { + YmapFile ymap = new YmapFile(rfe); + ymap.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ymap; + } + else if (rfe.NameLower.EndsWith(".ytyp")) + { + YtypFile ytyp = new YtypFile(); + ytyp.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ytyp; + } + else if (rfe.NameLower.EndsWith(".ymf")) + { + YmfFile ymf = new YmfFile(); + ymf.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ymf; + } + else if (rfe.NameLower.EndsWith(".ymt")) + { + YmtFile ymt = new YmtFile(); + ymt.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ymt; + } + else if (rfe.NameLower.EndsWith(".ybn")) + { + YbnFile ybn = new YbnFile(); + ybn.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ybn; + } + else if (rfe.NameLower.EndsWith(".fxc")) + { + FxcFile fxc = new FxcFile(); + fxc.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = fxc; + } + else if (rfe.NameLower.EndsWith(".yft")) + { + YftFile yft = new YftFile(); + yft.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = yft; + + if ((yft.Fragment != null) && (yft.Fragment.Drawable != null) && (yft.Fragment.Drawable.ShaderGroup != null) && (yft.Fragment.Drawable.ShaderGroup.TextureDictionary != null)) + { + ShowTextures(yft.Fragment.Drawable.ShaderGroup.TextureDictionary); + istexdict = true; + } + } + else if (rfe.NameLower.EndsWith(".ydr")) + { + YdrFile ydr = new YdrFile(); + ydr.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ydr; + + if ((ydr.Drawable != null) && (ydr.Drawable.ShaderGroup != null) && (ydr.Drawable.ShaderGroup.TextureDictionary != null)) + { + ShowTextures(ydr.Drawable.ShaderGroup.TextureDictionary); + istexdict = true; + } + } + else if (rfe.NameLower.EndsWith(".ydd")) + { + YddFile ydd = new YddFile(); + ydd.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ydd; + //todo: show embedded texdicts in ydd's? is this possible? + } + else if (rfe.NameLower.EndsWith(".ytd")) + { + YtdFile ytd = new YtdFile(); + ytd.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ytd; + ShowTextures(ytd.TextureDict); + istexdict = true; + } + else if (rfe.NameLower.EndsWith(".ycd")) + { + YcdFile ycd = new YcdFile(); + ycd.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ycd; + } + else if (rfe.NameLower.EndsWith(".ynd")) + { + YndFile ynd = new YndFile(); + ynd.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ynd; + } + else if (rfe.NameLower.EndsWith(".ynv")) + { + YnvFile ynv = new YnvFile(); + ynv.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = ynv; + } + else if (rfe.NameLower.EndsWith("_cache_y.dat")) + { + CacheDatFile cdf = new CacheDatFile(); + cdf.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = cdf; + } + else if (rfe.NameLower.EndsWith(".rel")) + { + RelFile rel = new RelFile(rfe); + rel.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = rel; + } + else if (rfe.NameLower.EndsWith(".gxt2")) + { + Gxt2File gxt2 = new Gxt2File(); + gxt2.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = gxt2; + } + else if (rfe.NameLower.EndsWith(".pso")) + { + JPsoFile pso = new JPsoFile(); + pso.Load(data, rfe); + DetailsPropertyGrid.SelectedObject = pso; + } + else + { + DetailsPropertyGrid.SelectedObject = null; + + } + + + if (!istexdict) + { + ShowTextures(null); + } + + + Cursor = Cursors.Default; + + + } + + private void DisplayFileContentsText(RpfFileEntry rfe, byte[] data, int length, int offset) + { + if (data == null) + { + Cursor = Cursors.Default; + DataTextBox.Text = "[Error extracting file! " + rfe.File.LastError + "]"; + return; + } + + int selline = -1; + int selstartc = -1; + int selendc = -1; + + if (DataHexRadio.Checked) + { + int charsperln = int.Parse(DataHexLineCombo.Text); + int lines = (data.Length / charsperln) + (((data.Length % charsperln) > 0) ? 1 : 0); + StringBuilder hexb = new StringBuilder(); + StringBuilder texb = new StringBuilder(); + StringBuilder finb = new StringBuilder(); + + if (offset > 0) + { + selline = offset / charsperln; + } + for (int i = 0; i < lines; i++) + { + int pos = i * charsperln; + int poslim = pos + charsperln; + hexb.Clear(); + texb.Clear(); + hexb.AppendFormat("{0:X4}: ", pos); + for (int c = pos; c < poslim; c++) + { + if (c < data.Length) + { + byte b = data[c]; + hexb.AppendFormat("{0:X2} ", b); + if (char.IsControl((char)b)) + { + texb.Append("."); + } + else + { + texb.Append(Encoding.ASCII.GetString(data, c, 1)); + } + } + else + { + hexb.Append(" "); + texb.Append(" "); + } + } + + if (i == selline) selstartc = finb.Length; + + finb.AppendLine(hexb.ToString() + "| " + texb.ToString()); + + if (i == selline) selendc = finb.Length - 1; + } + + DataTextBox.Text = finb.ToString(); + } + else + { + + string text = Encoding.UTF8.GetString(data); + + + DataTextBox.Text = text; + + if (offset > 0) + { + selstartc = offset; + selendc = offset + length; + } + } + + if ((selstartc > 0) && (selendc > 0)) + { + DataTextBox.SelectionStart = selstartc; + DataTextBox.SelectionLength = selendc - selstartc; + DataTextBox.ScrollToCaret(); + } + + } + + private void ShowTextures(TextureDictionary td) + { + SelTexturesListView.Items.Clear(); + SelTexturePictureBox.Image = null; + SelTextureNameTextBox.Text = string.Empty; + SelTextureDimensionsLabel.Text = "-"; + SelTextureMipLabel.Text = "0"; + SelTextureMipTrackBar.Value = 0; + SelTextureMipTrackBar.Maximum = 0; + + if (td == null) + { + HideTexturesTab(); + return; + } + if (!SelectionTabControl.TabPages.Contains(TexturesTabPage)) + { + SelectionTabControl.TabPages.Add(TexturesTabPage); + } + + + if ((td.Textures == null) || (td.Textures.data_items == null)) return; + var texs = td.Textures.data_items; + + for (int i = 0; i < texs.Length; i++) + { + var tex = texs[i]; + ListViewItem lvi = SelTexturesListView.Items.Add(tex.Name); + lvi.Tag = tex; + } + + } + + private void HideTexturesTab() + { + if (SelectionTabControl.TabPages.Contains(TexturesTabPage)) + { + SelectionTabControl.TabPages.Remove(TexturesTabPage); + } + } + + private void ShowTextureMip(Texture tex, int mip, bool mipchange) + { + if (tex == null) + { + SelTexturePictureBox.Image = null; + SelTextureNameTextBox.Text = string.Empty; + SelTextureDimensionsLabel.Text = "-"; + SelTextureMipLabel.Text = "0"; + SelTextureMipTrackBar.Value = 0; + SelTextureMipTrackBar.Maximum = 0; + return; + } + + + if (mipchange) + { + if (mip >= tex.Levels) mip = tex.Levels - 1; + } + else + { + SelTextureMipTrackBar.Maximum = tex.Levels - 1; + } + + SelTextureNameTextBox.Text = tex.Name; + + try + { + int cmip = Math.Min(Math.Max(mip, 0), tex.Levels - 1); + byte[] pixels = DDSIO.GetPixels(tex, cmip); + int w = tex.Width >> cmip; + int h = tex.Height >> cmip; + Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); + + if (pixels != null) + { + var BoundsRect = new System.Drawing.Rectangle(0, 0, w, h); + BitmapData bmpData = bmp.LockBits(BoundsRect, ImageLockMode.WriteOnly, bmp.PixelFormat); + IntPtr ptr = bmpData.Scan0; + int bytes = bmpData.Stride * bmp.Height; + Marshal.Copy(pixels, 0, ptr, bytes); + bmp.UnlockBits(bmpData); + } + + SelTexturePictureBox.Image = bmp; + SelTextureDimensionsLabel.Text = w.ToString() + " x " + h.ToString(); + } + catch (Exception ex) + { + MessageBox.Show("Error reading texture mip:\n" + ex.ToString()); + SelTexturePictureBox.Image = null; + } + + } + + + + private void AbortButton_Click(object sender, EventArgs e) + { + AbortOperation = true; + } + + + private void TestAllButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + if (ScannedFiles.Count == 0) + { + MessageBox.Show("Please scan the GTAV folder first."); + return; + } + + AbortOperation = false; + InProgress = true; + + DataTextBox.Text = string.Empty; + FileInfoLabel.Text = "[File test results]"; + + Task.Run(() => + { + + UpdateStatus("Starting test..."); + + StringBuilder sbout = new StringBuilder(); + int errcount = 0; + int curfile = 1; + int totrpfs = ScannedFiles.Count; + long totbytes = 0; + + foreach (RpfFile file in ScannedFiles) + { + if (AbortOperation) + { + UpdateStatus("Test aborted."); + InProgress = false; + return; + } + + UpdateStatus(curfile.ToString() + "/" + totrpfs.ToString() + ": Testing " + file.FilePath + "..."); + + string errorstr = file.TestExtractAllFiles(); + + if (!string.IsNullOrEmpty(errorstr)) + { + AddTestError(errorstr); + sbout.Append(errorstr); + errcount++; + } + + totbytes += file.ExtractedByteCount; + curfile++; + } + + + UpdateStatus("Test complete. " + errcount.ToString() + " problems encountered, " + totbytes.ToString() + " total bytes extracted."); + InProgress = false; + }); + } + private void AddTestError(string error) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { AddTestError(error); })); + } + else + { + DataTextBox.AppendText(error); + + } + } + catch { } + } + + + + + + + private void Find() + { + if (InProgress) return; + if (ScannedFiles.Count == 0) + { + MessageBox.Show("Please scan the GTAV folder first."); + return; + } + + + string find = FindTextBox.Text.ToLower(); + Cursor = Cursors.WaitCursor; + if (string.IsNullOrEmpty(find)) + { + ClearFiles(); + foreach (RpfFile file in RootFiles) + { + AddScannedFile(file, null); //reset the file tree... slow :( + } + } + else + { + ClearFiles(); + int count = 0; + int max = 500; + foreach (RpfFile file in ScannedFiles) + { + if (file.Name.ToLower().Contains(find)) + { + AddFileNode(file, null); + count++; + } + foreach (RpfEntry entry in file.AllEntries) + { + if (entry.NameLower.Contains(find)) + { + if (entry is RpfDirectoryEntry) + { + RpfDirectoryEntry direntry = entry as RpfDirectoryEntry; + + TreeNode node = AddEntryNode(entry, null); + + foreach (RpfFileEntry cfentry in direntry.Files) + { + //if (cfentry.Name.EndsWith(".rpf", StringComparison.InvariantCultureIgnoreCase)) continue; + AddEntryNode(cfentry, node); + } + count++; + } + else if (entry is RpfBinaryFileEntry) + { + if (entry.NameLower.EndsWith(".rpf", StringComparison.InvariantCultureIgnoreCase)) continue; + AddEntryNode(entry, null); + count++; + } + else if (entry is RpfResourceFileEntry) + { + AddEntryNode(entry, null); + count++; + } + } + if (count >= max) + { + MessageBox.Show("Search results limited to " + max.ToString() + " entries."); + break; + } + } + if (count >= max) + { + break; + } + } + } + Cursor = Cursors.Default; + } + private void FindTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == 13) + { + Find(); + e.Handled = true; + } + } + private void FindButton_Click(object sender, EventArgs e) + { + Find(); + } + + + + private void ExportButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + if (ScannedFiles.Count == 0) + { + MessageBox.Show("Please scan the GTAV folder first."); + return; + } + TreeNode node = MainTreeView.SelectedNode; + if (node == null) + { + MessageBox.Show("Please select a file to export."); + return; + } + + RpfFileEntry rfe = node.Tag as RpfFileEntry; + if (rfe == null) + { + MessageBox.Show("Please select a file to export."); + return; + } + + SaveFileDialog.FileName = rfe.Name; + if (SaveFileDialog.ShowDialog() == DialogResult.OK) + { + string fpath = SaveFileDialog.FileName; + + byte[] data = rfe.File.ExtractFile(rfe); + + + if (ExportCompressCheckBox.Checked) + { + data = ResourceBuilder.Compress(data); + } + + + RpfResourceFileEntry rrfe = rfe as RpfResourceFileEntry; + if (rrfe != null) //add resource header if this is a resource file. + { + data = ResourceBuilder.AddResourceHeader(rrfe, data); + } + + if (data == null) + { + MessageBox.Show("Error extracting file! " + rfe.File.LastError); + return; + } + + try + { + + File.WriteAllBytes(fpath, data); + + } + catch (Exception ex) + { + MessageBox.Show("Error saving file! " + ex.ToString()); + } + + } + + + + } + + + + + private class SearchResult + { + public RpfFileEntry FileEntry { get; set; } + public int Offset { get; set; } + public int Length { get; set; } + + public SearchResult(RpfFileEntry entry, int offset, int length) + { + FileEntry = entry; + Offset = offset; + Length = length; + } + } + private byte LowerCaseByte(byte b) + { + if ((b >= 65) && (b <= 90)) //upper case alphabet... + { + b += 32; + } + return b; + } + + private void AddSearchResult(SearchResult result) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { AddSearchResult(result); })); + } + else + { + SearchResults.Add(result); + SearchResultsListView.VirtualListSize = SearchResults.Count; + } + } + catch { } + } + + private void Search() + { + if (InProgress) return; + if (ScannedFiles.Count == 0) + { + MessageBox.Show("Please scan the GTAV folder first."); + return; + } + if (SearchTextBox.Text.Length == 0) + { + MessageBox.Show("Please enter a search term."); + return; + } + + string searchtxt = SearchTextBox.Text; + bool hex = SearchHexRadioButton.Checked; + bool casesen = SearchCaseSensitiveCheckBox.Checked || hex; + bool bothdirs = SearchBothDirectionsCheckBox.Checked; + string[] ignoreexts = null; + byte[] searchbytes1; + byte[] searchbytes2; + int bytelen; + + if (!casesen) searchtxt = searchtxt.ToLower(); //case sensitive search in lower case. + + if (SearchIgnoreCheckBox.Checked) + { + ignoreexts = SearchIgnoreTextBox.Text.Split(','); + for (int i = 0; i < ignoreexts.Length; i++) + { + ignoreexts[i] = ignoreexts[i].Trim(); + } + } + + if (hex) + { + if (searchtxt.Length < 2) + { + MessageBox.Show("Please enter at least one byte of hex (2 characters)."); + return; + } + try + { + bytelen = searchtxt.Length / 2; + searchbytes1 = new byte[bytelen]; + searchbytes2 = new byte[bytelen]; + for (int i = 0; i < bytelen; i++) + { + searchbytes1[i] = Convert.ToByte(searchtxt.Substring(i * 2, 2), 16); + searchbytes2[bytelen - i - 1] = searchbytes1[i]; + } + } + catch + { + MessageBox.Show("Please enter a valid hex string."); + return; + } + } + else + { + bytelen = searchtxt.Length; + searchbytes1 = new byte[bytelen]; + searchbytes2 = new byte[bytelen]; //reversed text... + for (int i = 0; i < bytelen; i++) + { + searchbytes1[i] = (byte)searchtxt[i]; + searchbytes2[bytelen - i - 1] = searchbytes1[i]; + } + } + + SearchTextBox.Enabled = false; + SearchHexRadioButton.Enabled = false; + SearchTextRadioButton.Enabled = false; + SearchCaseSensitiveCheckBox.Enabled = false; + SearchBothDirectionsCheckBox.Enabled = false; + SearchIgnoreCheckBox.Enabled = false; + SearchIgnoreTextBox.Enabled = false; + SearchButton.Enabled = false; + SearchSaveResultsButton.Enabled = false; + + InProgress = true; + AbortOperation = false; + SearchResultsListView.VirtualListSize = 0; + SearchResults.Clear(); + int totfiles = TotalFileCount; + int curfile = 0; + Task.Run(() => + { + + DateTime starttime = DateTime.Now; + int resultcount = 0; + + for (int f = 0; f < ScannedFiles.Count; f++) + { + var rpffile = ScannedFiles[f]; + + //UpdateStatus(string.Format("Searching {0}/{1} : {2}", f, ScannedFiles.Count, rpffile.Path)); + + foreach (var entry in rpffile.AllEntries) + { + var duration = DateTime.Now - starttime; + if (AbortOperation) + { + UpdateStatus(duration.ToString(@"hh\:mm\:ss") + " - Search aborted."); + InProgress = false; + SearchComplete(); + return; + } + + RpfFileEntry fentry = entry as RpfFileEntry; + if (fentry == null) continue; + + curfile++; + + if (fentry.NameLower.EndsWith(".rpf")) + { continue; } + + if (ignoreexts != null) + { + bool ignore = false; + for (int i = 0; i < ignoreexts.Length; i++) + { + if (fentry.NameLower.EndsWith(ignoreexts[i])) + { + ignore = true; + break; + } + } + if (ignore) + { continue; } + } + + UpdateStatus(string.Format("{0} - Searching {1}/{2} : {3}", duration.ToString(@"hh\:mm\:ss"), curfile, totfiles, fentry.Path)); + + byte[] filebytes = fentry.File.ExtractFile(fentry); + if (filebytes == null) continue; + + + int hitlen1 = 0; + int hitlen2 = 0; + + for (int i = 0; i < filebytes.Length; i++) + { + byte b = casesen ? filebytes[i] : LowerCaseByte(filebytes[i]); + byte b1 = searchbytes1[hitlen1]; //current test byte 1 + byte b2 = searchbytes2[hitlen2]; + + if (b == b1) hitlen1++; else hitlen1 = 0; + if (b == b2) hitlen2++; else hitlen2 = 0; + + if (hitlen1 == bytelen) + { + AddSearchResult(new SearchResult(fentry, (i - bytelen), bytelen)); + resultcount++; + hitlen1 = 0; + } + if (hitlen2 == bytelen) + { + AddSearchResult(new SearchResult(fentry, (i - bytelen), bytelen)); + resultcount++; + hitlen2 = 0; + } + } + } + } + + var totdur = DateTime.Now - starttime; + UpdateStatus(totdur.ToString(@"hh\:mm\:ss") + " - Search complete. " + resultcount.ToString() + " results found."); + InProgress = false; + SearchComplete(); + }); + } + private void SearchComplete() + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { SearchComplete(); })); + } + else + { + SearchTextBox.Enabled = true; + SearchHexRadioButton.Enabled = true; + SearchTextRadioButton.Enabled = true; + SearchCaseSensitiveCheckBox.Enabled = SearchTextRadioButton.Checked; + SearchBothDirectionsCheckBox.Enabled = true; + SearchIgnoreCheckBox.Enabled = true; + SearchIgnoreTextBox.Enabled = SearchIgnoreCheckBox.Checked; + SearchButton.Enabled = true; + SearchSaveResultsButton.Enabled = true; + } + } + catch { } + } + private void SearchButton_Click(object sender, EventArgs e) + { + Search(); + } + private void SearchAbortButton_Click(object sender, EventArgs e) + { + AbortOperation = true; + } + private void SearchSaveResultsButton_Click(object sender, EventArgs e) + { + SaveFileDialog.FileName = "SearchResults.txt"; + if (SaveFileDialog.ShowDialog() == DialogResult.OK) + { + string fpath = SaveFileDialog.FileName; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine("CodeWalker Search Results for \"" + SearchTextBox.Text + "\""); + sb.AppendLine("[File path], [Byte offset]"); + if (SearchResults != null) + { + foreach (var r in SearchResults) + { + sb.AppendLine(r.FileEntry.Path + ", " + r.Offset.ToString()); + } + } + + File.WriteAllText(fpath, sb.ToString()); + + } + } + private void SearchTextRadioButton_CheckedChanged(object sender, EventArgs e) + { + SearchCaseSensitiveCheckBox.Enabled = SearchTextRadioButton.Checked; + } + private void SearchHexRadioButton_CheckedChanged(object sender, EventArgs e) + { + + } + private void SearchResultsListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) + { + var item = new ListViewItem(); + if (e.ItemIndex < SearchResults.Count) + { + SearchResult r = SearchResults[e.ItemIndex]; + item.Text = r.FileEntry.Name; + item.SubItems.Add(r.Offset.ToString()); + item.Tag = r; + } + e.Item = item; + } + private void SearchResultsListView_SelectedIndexChanged(object sender, EventArgs e) + { + if (SearchResultsListView.SelectedIndices.Count == 1) + { + var i = SearchResultsListView.SelectedIndices[0]; + if ((i >= 0) && (i < SearchResults.Count)) + { + var r = SearchResults[i]; + SelectFile(r.FileEntry, r.Offset+1, r.Length); + } + else + { + SelectFile(null, -1, 0); + } + } + else + { + SelectFile(null, -1, 0); + } + } + private void SearchIgnoreCheckBox_CheckedChanged(object sender, EventArgs e) + { + SearchIgnoreTextBox.Enabled = SearchIgnoreCheckBox.Checked; + } + + private void SelTexturesListView_SelectedIndexChanged(object sender, EventArgs e) + { + Texture tex = null; + if (SelTexturesListView.SelectedItems.Count == 1) + { + tex = SelTexturesListView.SelectedItems[0].Tag as Texture; + } + ShowTextureMip(tex, 0, false); + } + + private void SelTextureMipTrackBar_Scroll(object sender, EventArgs e) + { + Texture tex = null; + if (SelTexturesListView.SelectedItems.Count == 1) + { + tex = SelTexturesListView.SelectedItems[0].Tag as Texture; + } + SelTextureMipLabel.Text = SelTextureMipTrackBar.Value.ToString(); + ShowTextureMip(tex, SelTextureMipTrackBar.Value, true); + } + + private void ShowLargeFileContentsCheckBox_CheckedChanged(object sender, EventArgs e) + { + SelectFile(); + } + + private void FlattenStructureCheckBox_CheckedChanged(object sender, EventArgs e) + { + FlatStructure = FlattenStructureCheckBox.Checked; + + if (InProgress) return; + if (ScannedFiles.Count == 0) return; + + Cursor = Cursors.WaitCursor; + + SearchTextBox.Clear(); + + ClearFiles(); + foreach (RpfFile file in RootFiles) + { + AddScannedFile(file, null); + } + + Cursor = Cursors.Default; + } + } +} diff --git a/BrowseForm.resx b/BrowseForm.resx new file mode 100644 index 0000000..6337549 --- /dev/null +++ b/BrowseForm.resx @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 182, 17 + + + 320, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/CodeWalker Explorer.bat b/CodeWalker Explorer.bat new file mode 100644 index 0000000..23f0854 --- /dev/null +++ b/CodeWalker Explorer.bat @@ -0,0 +1 @@ +start codewalker explorer \ No newline at end of file diff --git a/CodeWalker.WinForms/CodeWalker.WinForms.csproj b/CodeWalker.WinForms/CodeWalker.WinForms.csproj new file mode 100644 index 0000000..4fd6b21 --- /dev/null +++ b/CodeWalker.WinForms/CodeWalker.WinForms.csproj @@ -0,0 +1,109 @@ + + + + + Debug + AnyCPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3} + Library + Properties + CodeWalker.WinForms + CodeWalker.WinForms + v4.5.2 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + Component + + + MenuStripFix.cs + + + + Component + + + PropertyGridFix.cs + + + Component + + + ReadOnlyPropertyGrid.cs + + + Component + + + TextBoxFix.cs + + + Component + + + TextBoxScrollSyncFix.cs + + + Component + + + ToolStripFix.cs + + + Component + + + ToolStripSplitButtonFix.cs + + + Component + + + ToolStripSpringTextBox.cs + + + Component + + + TreeViewFix.cs + + + + + \ No newline at end of file diff --git a/CodeWalker.WinForms/MenuStripFix.Designer.cs b/CodeWalker.WinForms/MenuStripFix.Designer.cs new file mode 100644 index 0000000..c570cf6 --- /dev/null +++ b/CodeWalker.WinForms/MenuStripFix.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class MenuStripFix + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/MenuStripFix.cs b/CodeWalker.WinForms/MenuStripFix.cs new file mode 100644 index 0000000..bf11852 --- /dev/null +++ b/CodeWalker.WinForms/MenuStripFix.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class MenuStripFix : MenuStrip + { + public MenuStripFix() + { + InitializeComponent(); + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + } + + + + + const uint WM_LBUTTONDOWN = 0x201; + const uint WM_LBUTTONUP = 0x202; + + static private bool down = false; + + protected override void WndProc(ref Message m) + { + //fix to properly handle the mouse down event when the form isn't currently focused... + if (m.Msg == WM_LBUTTONUP && !down) + { + m.Msg = (int)WM_LBUTTONDOWN; + base.WndProc(ref m); + m.Msg = (int)WM_LBUTTONUP; + } + + if (m.Msg == WM_LBUTTONDOWN) down = true; + if (m.Msg == WM_LBUTTONUP) down = false; + + base.WndProc(ref m); + } + } +} diff --git a/CodeWalker.WinForms/Properties/AssemblyInfo.cs b/CodeWalker.WinForms/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7bff769 --- /dev/null +++ b/CodeWalker.WinForms/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CodeWalker.WinForms")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CodeWalker.WinForms")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9702c58d-f52f-45cf-9456-9ce5af40f5c3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CodeWalker.WinForms/PropertyGridFix.Designer.cs b/CodeWalker.WinForms/PropertyGridFix.Designer.cs new file mode 100644 index 0000000..6d96a50 --- /dev/null +++ b/CodeWalker.WinForms/PropertyGridFix.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class PropertyGridFix + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/PropertyGridFix.cs b/CodeWalker.WinForms/PropertyGridFix.cs new file mode 100644 index 0000000..cb95c0b --- /dev/null +++ b/CodeWalker.WinForms/PropertyGridFix.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class PropertyGridFix : PropertyGrid + { + public PropertyGridFix() + { + InitializeComponent(); + LineColor = SystemColors.InactiveBorder; //makes it consistent across windows 10 versions........ + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + } + } +} diff --git a/CodeWalker.WinForms/ReadOnlyPropertyGrid.Designer.cs b/CodeWalker.WinForms/ReadOnlyPropertyGrid.Designer.cs new file mode 100644 index 0000000..958ef32 --- /dev/null +++ b/CodeWalker.WinForms/ReadOnlyPropertyGrid.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class ReadOnlyPropertyGrid + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/ReadOnlyPropertyGrid.cs b/CodeWalker.WinForms/ReadOnlyPropertyGrid.cs new file mode 100644 index 0000000..0898420 --- /dev/null +++ b/CodeWalker.WinForms/ReadOnlyPropertyGrid.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class ReadOnlyPropertyGrid : PropertyGridFix + { + public ReadOnlyPropertyGrid() + { + InitializeComponent(); + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + } + + + + private bool _readOnly = true; + public bool ReadOnly + { + get { return _readOnly; } + set + { + _readOnly = value; + SetObjectAsReadOnly(SelectedObject, _readOnly); + } + } + + private TypeDescriptionProvider provider = null; + private object providedObject = null; + + protected override void OnSelectedObjectsChanged(EventArgs e) + { + if (providedObject != null) + { + SetObjectAsReadOnly(providedObject, false); + } + SetObjectAsReadOnly(SelectedObject, _readOnly); + base.OnSelectedObjectsChanged(e); + } + + private void SetObjectAsReadOnly(object selectedObject, bool isReadOnly) + { + if (SelectedObject != null) + { + if (isReadOnly) + { + provider = TypeDescriptor.AddAttributes(SelectedObject, new Attribute[] { new ReadOnlyAttribute(_readOnly) }); + providedObject = SelectedObject; + } + else if (provider != null) + { + TypeDescriptor.RemoveProvider(provider, this.SelectedObject); + provider = null; + providedObject = null; + } + Refresh(); + } + } + } +} diff --git a/CodeWalker.WinForms/TextBoxFix.Designer.cs b/CodeWalker.WinForms/TextBoxFix.Designer.cs new file mode 100644 index 0000000..49e0d32 --- /dev/null +++ b/CodeWalker.WinForms/TextBoxFix.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class TextBoxFix + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/TextBoxFix.cs b/CodeWalker.WinForms/TextBoxFix.cs new file mode 100644 index 0000000..a01eadd --- /dev/null +++ b/CodeWalker.WinForms/TextBoxFix.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class TextBoxFix : TextBox + { + public TextBoxFix() + { + InitializeComponent(); + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + } + + protected override bool ProcessCmdKey(ref Message msg, Keys keyData) + { + //Fix for Ctrl-A not working in multiline textboxes. + const int WM_KEYDOWN = 0x100; + var keyCode = (Keys)(msg.WParam.ToInt32() & Convert.ToInt32(Keys.KeyCode)); + if ((msg.Msg == WM_KEYDOWN && keyCode == Keys.A) && (ModifierKeys == Keys.Control) && Focused) + { + SelectAll(); + return true; + } + return base.ProcessCmdKey(ref msg, keyData); + } + } +} diff --git a/CodeWalker.WinForms/TextBoxScrollSyncFix.Designer.cs b/CodeWalker.WinForms/TextBoxScrollSyncFix.Designer.cs new file mode 100644 index 0000000..a3bde36 --- /dev/null +++ b/CodeWalker.WinForms/TextBoxScrollSyncFix.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class TextBoxScrollSyncFix + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/TextBoxScrollSyncFix.cs b/CodeWalker.WinForms/TextBoxScrollSyncFix.cs new file mode 100644 index 0000000..3696ece --- /dev/null +++ b/CodeWalker.WinForms/TextBoxScrollSyncFix.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class TextBoxScrollSyncFix : TextBoxFix + { + public TextBoxScrollSyncFix() + { + InitializeComponent(); + } + + public const int WM_VSCROLL = 0x115; + + List peers = new List(); + + public void AddPeer(TextBoxScrollSyncFix peer) + { + peers.Add(peer); + } + + private void DirectWndProc(ref Message m) + { + base.WndProc(ref m); + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == WM_VSCROLL) + { + foreach (var peer in this.peers) + { + var peerMessage = Message.Create(peer.Handle, m.Msg, m.WParam, m.LParam); + peer.DirectWndProc(ref peerMessage); + } + } + + base.WndProc(ref m); + } + } +} diff --git a/CodeWalker.WinForms/ToolStripFix.Designer.cs b/CodeWalker.WinForms/ToolStripFix.Designer.cs new file mode 100644 index 0000000..709a60a --- /dev/null +++ b/CodeWalker.WinForms/ToolStripFix.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class ToolStripFix + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/ToolStripFix.cs b/CodeWalker.WinForms/ToolStripFix.cs new file mode 100644 index 0000000..f4cdb51 --- /dev/null +++ b/CodeWalker.WinForms/ToolStripFix.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class ToolStripFix : ToolStrip + { + public ToolStripFix() + { + InitializeComponent(); + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + } + + + const uint WM_LBUTTONDOWN = 0x201; + const uint WM_LBUTTONUP = 0x202; + + static private bool down = false; + + protected override void WndProc(ref Message m) + { + //fix to properly handle the mouse down event when the form isn't currently focused... + if (m.Msg == WM_LBUTTONUP && !down) + { + m.Msg = (int)WM_LBUTTONDOWN; + base.WndProc(ref m); + m.Msg = (int)WM_LBUTTONUP; + } + + if (m.Msg == WM_LBUTTONDOWN) down = true; + if (m.Msg == WM_LBUTTONUP) down = false; + + base.WndProc(ref m); + } + + } +} diff --git a/CodeWalker.WinForms/ToolStripSplitButtonFix.Designer.cs b/CodeWalker.WinForms/ToolStripSplitButtonFix.Designer.cs new file mode 100644 index 0000000..78b9089 --- /dev/null +++ b/CodeWalker.WinForms/ToolStripSplitButtonFix.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class ToolStripSplitButtonFix + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/ToolStripSplitButtonFix.cs b/CodeWalker.WinForms/ToolStripSplitButtonFix.cs new file mode 100644 index 0000000..29c833b --- /dev/null +++ b/CodeWalker.WinForms/ToolStripSplitButtonFix.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class ToolStripSplitButtonFix : ToolStripSplitButton + { + //this allows the ToolStripSplitButton to have a "Checked" shaded appearance. + private bool ischecked = false; + + /// + /// Indictates the Checked state of the button. + /// + [Category("Behavior"), + Description("Indicates whether or not the ToolStripSplitButtonFix is checked."), + DefaultValue(false)] + public bool Checked + { + get + { + return ischecked; + } + set + { + ischecked = value; + this.Invalidate(); + } + } + + public ToolStripSplitButtonFix() + { + InitializeComponent(); + } + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + if (ischecked) + { + ControlPaint.DrawBorder(e.Graphics, + e.ClipRectangle, // To draw around the button + drop-down + //ButtonBounds, // To draw only around the button + SystemColors.MenuHighlight, + ButtonBorderStyle.Solid); + } + } + } +} diff --git a/CodeWalker.WinForms/ToolStripSpringTextBox.Designer.cs b/CodeWalker.WinForms/ToolStripSpringTextBox.Designer.cs new file mode 100644 index 0000000..e897fde --- /dev/null +++ b/CodeWalker.WinForms/ToolStripSpringTextBox.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class ToolStripSpringTextBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/ToolStripSpringTextBox.cs b/CodeWalker.WinForms/ToolStripSpringTextBox.cs new file mode 100644 index 0000000..5ee2675 --- /dev/null +++ b/CodeWalker.WinForms/ToolStripSpringTextBox.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class ToolStripSpringTextBox : ToolStripTextBox + { + public override Size GetPreferredSize(Size constrainingSize) + { + // Use the default size if the text box is on the overflow menu + // or is on a vertical ToolStrip. + if (IsOnOverflow || Owner.Orientation == Orientation.Vertical) + { + return DefaultSize; + } + + // Declare a variable to store the total available width as + // it is calculated, starting with the display width of the + // owning ToolStrip. + Int32 width = Owner.DisplayRectangle.Width; + + // Subtract the width of the overflow button if it is displayed. + if (Owner.OverflowButton.Visible) + { + width = width - Owner.OverflowButton.Width - + Owner.OverflowButton.Margin.Horizontal; + } + + // Declare a variable to maintain a count of ToolStripSpringTextBox + // items currently displayed in the owning ToolStrip. + Int32 springBoxCount = 0; + + foreach (ToolStripItem item in Owner.Items) + { + // Ignore items on the overflow menu. + if (item.IsOnOverflow) continue; + + if (item is ToolStripSpringTextBox) + { + // For ToolStripSpringTextBox items, increment the count and + // subtract the margin width from the total available width. + springBoxCount++; + width -= item.Margin.Horizontal; + } + else if (item is ToolStripSplitButton) + { + width = width - 32 - item.Margin.Horizontal; //dexyfex bugfix for changing split button image... + } + else + { + // For all other items, subtract the full width from the total + // available width. + width = width - item.Width - item.Margin.Horizontal; + } + } + + // If there are multiple ToolStripSpringTextBox items in the owning + // ToolStrip, divide the total available width between them. + if (springBoxCount > 1) width /= springBoxCount; + + // If the available width is less than the default width, use the + // default width, forcing one or more items onto the overflow menu. + if (width < DefaultSize.Width) width = DefaultSize.Width; + + // Retrieve the preferred size from the base class, but change the + // width to the calculated width. + Size size = base.GetPreferredSize(constrainingSize); + size.Width = width; + return size; + } + } +} diff --git a/CodeWalker.WinForms/TreeViewFix.Designer.cs b/CodeWalker.WinForms/TreeViewFix.Designer.cs new file mode 100644 index 0000000..aa5cbaa --- /dev/null +++ b/CodeWalker.WinForms/TreeViewFix.Designer.cs @@ -0,0 +1,36 @@ +namespace CodeWalker.WinForms +{ + partial class TreeViewFix + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/CodeWalker.WinForms/TreeViewFix.cs b/CodeWalker.WinForms/TreeViewFix.cs new file mode 100644 index 0000000..c5f75ae --- /dev/null +++ b/CodeWalker.WinForms/TreeViewFix.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.WinForms +{ + public partial class TreeViewFix : TreeView + { + public TreeViewFix() + { + InitializeComponent(); + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == 0x203) // double click + { + var localPos = PointToClient(Cursor.Position); + var hitTestInfo = HitTest(localPos); + if (hitTestInfo.Location == TreeViewHitTestLocations.StateImage) + m.Result = IntPtr.Zero; + else + base.WndProc(ref m); + } + else base.WndProc(ref m); + } + + } +} diff --git a/CodeWalker.csproj b/CodeWalker.csproj new file mode 100644 index 0000000..434cf41 --- /dev/null +++ b/CodeWalker.csproj @@ -0,0 +1,589 @@ + + + + + Debug + AnyCPU + {3BB16320-99BF-4E30-9065-CA0877A36BF4} + WinExe + Properties + CodeWalker + CodeWalker + v4.5.2 + 512 + true + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + none + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + Resources\CW.ico + + + + packages\FCTB.2.16.21.0\lib\FastColoredTextBox.dll + False + + + packages\SharpDX.4.0.1\lib\net45\SharpDX.dll + + + packages\SharpDX.D3DCompiler.4.0.1\lib\net45\SharpDX.D3DCompiler.dll + + + packages\SharpDX.Direct2D1.4.0.1\lib\net45\SharpDX.Direct2D1.dll + + + packages\SharpDX.Direct3D11.4.0.1\lib\net45\SharpDX.Direct3D11.dll + + + packages\SharpDX.DXGI.4.0.1\lib\net45\SharpDX.DXGI.dll + + + packages\SharpDX.Mathematics.4.0.1\lib\net45\SharpDX.Mathematics.dll + + + packages\SharpDX.XAudio2.4.0.1\lib\net45\SharpDX.XAudio2.dll + + + packages\SharpDX.XInput.4.0.1\lib\net45\SharpDX.XInput.dll + + + + + + + + + + + + + + + + Form + + + AboutForm.cs + + + Form + + + BrowseForm.cs + + + Form + + + ExploreForm.cs + + + Form + + + ExtractKeysForm.cs + + + Form + + + ExtractScriptsForm.cs + + + Form + + + ExtractRawForm.cs + + + Form + + + ExtractShadersForm.cs + + + Form + + + ExtractTexForm.cs + + + Form + + + AwcForm.cs + + + Form + + + FxcForm.cs + + + Form + + + GxtForm.cs + + + Form + + + HexForm.cs + + + Form + + + MetaForm.cs + + + Form + + + ModelForm.cs + + + Form + + + RelForm.cs + + + Form + + + TextForm.cs + + + Form + + + XmlForm.cs + + + Form + + + YtdForm.cs + + + Form + + + YvrForm.cs + + + Form + + + YwrForm.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + JenkGenForm.cs + + + Form + + + JenkIndForm.cs + + + Form + + + KeyBindForm.cs + + + Form + + + MainForm.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + SelectFolderForm.cs + + + + Form + + + SettingsForm.cs + + + + + + + + + + Form + + + ProjectForm.cs + + + Form + + + WorldInfoForm.cs + + + Form + + + WorldSearchForm.cs + + + + + + + Form + + + BinarySearchForm.cs + + + + Form + + + WorldForm.cs + + + + + + + + + + + + + + + AboutForm.cs + + + BrowseForm.cs + + + ExploreForm.cs + + + ExtractKeysForm.cs + + + ExtractScriptsForm.cs + + + ExtractRawForm.cs + + + ExtractShadersForm.cs + + + ExtractTexForm.cs + + + AwcForm.cs + + + FxcForm.cs + + + GxtForm.cs + + + HexForm.cs + + + MetaForm.cs + + + ModelForm.cs + + + RelForm.cs + + + TextForm.cs + + + XmlForm.cs + + + YtdForm.cs + + + YvrForm.cs + + + YwrForm.cs + + + JenkGenForm.cs + + + JenkIndForm.cs + + + KeyBindForm.cs + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + BinarySearchForm.cs + + + SelectFolderForm.cs + + + ProjectForm.cs + + + SettingsForm.cs + + + WorldForm.cs + + + WorldInfoForm.cs + + + WorldSearchForm.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + Designer + + + True + Settings.settings + True + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4.5.2 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + {9702c58d-f52f-45cf-9456-9ce5af40f5c3} + CodeWalker.WinForms + + + + + \ No newline at end of file diff --git a/CodeWalker.sln b/CodeWalker.sln new file mode 100644 index 0000000..ca2af1b --- /dev/null +++ b/CodeWalker.sln @@ -0,0 +1,65 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeWalker", "CodeWalker.csproj", "{3BB16320-99BF-4E30-9065-CA0877A36BF4}" + ProjectSection(ProjectDependencies) = postProject + {0D14B076-0ABF-434E-AB9F-36E7800D8887} = {0D14B076-0ABF-434E-AB9F-36E7800D8887} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CodeWalkerShaders", "Shaders\CodeWalkerShaders.vcxproj", "{0D14B076-0ABF-434E-AB9F-36E7800D8887}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeWalker.WinForms", "CodeWalker.WinForms\CodeWalker.WinForms.csproj", "{9702C58D-F52F-45CF-9456-9CE5AF40F5C3}" +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 + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Debug|x64.ActiveCfg = Debug|x64 + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Debug|x64.Build.0 = Debug|x64 + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Debug|x86.ActiveCfg = Debug|x86 + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Debug|x86.Build.0 = Debug|x86 + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Release|Any CPU.Build.0 = Release|Any CPU + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Release|x64.ActiveCfg = Release|x64 + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Release|x64.Build.0 = Release|x64 + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Release|x86.ActiveCfg = Release|x86 + {3BB16320-99BF-4E30-9065-CA0877A36BF4}.Release|x86.Build.0 = Release|x86 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Debug|Any CPU.Build.0 = Debug|Win32 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Debug|x64.ActiveCfg = Debug|x64 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Debug|x64.Build.0 = Debug|x64 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Debug|x86.ActiveCfg = Debug|Win32 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Debug|x86.Build.0 = Debug|Win32 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Release|Any CPU.ActiveCfg = Release|Win32 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Release|Any CPU.Build.0 = Release|Win32 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Release|x64.ActiveCfg = Release|x64 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Release|x64.Build.0 = Release|x64 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Release|x86.ActiveCfg = Release|Win32 + {0D14B076-0ABF-434E-AB9F-36E7800D8887}.Release|x86.Build.0 = Release|Win32 + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Debug|x64.ActiveCfg = Debug|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Debug|x64.Build.0 = Debug|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Debug|x86.ActiveCfg = Debug|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Debug|x86.Build.0 = Debug|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Release|Any CPU.Build.0 = Release|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Release|x64.ActiveCfg = Release|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Release|x64.Build.0 = Release|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Release|x86.ActiveCfg = Release|Any CPU + {9702C58D-F52F-45CF-9456-9CE5AF40F5C3}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ExploreForm.Designer.cs b/ExploreForm.Designer.cs new file mode 100644 index 0000000..cf2f9ad --- /dev/null +++ b/ExploreForm.Designer.cs @@ -0,0 +1,1074 @@ +namespace CodeWalker +{ + partial class ExploreForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExploreForm)); + this.MainMenu = new System.Windows.Forms.MenuStrip(); + this.FileMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileExitMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditViewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditViewHexMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.EditExportXmlMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditExtractRawMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditExtractAllMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.EditImportXmlMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditImportRawMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditImportMenuSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.EditCopyMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditCopyPathMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditCopyFileListMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); + this.EditRenameMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditReplaceMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditDeleteMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditEditModeMenuSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.EditSelectAllMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewLargeIconsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewSmallIconsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewListMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewDetailsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsRpfBrowserMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); + this.ToolsOptionsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.MainToolbar = new System.Windows.Forms.ToolStrip(); + this.BackButton = new System.Windows.Forms.ToolStripSplitButton(); + this.BackListButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ForwardButton = new System.Windows.Forms.ToolStripSplitButton(); + this.ForwardListButton = new System.Windows.Forms.ToolStripMenuItem(); + this.UpButton = new System.Windows.Forms.ToolStripSplitButton(); + this.UpListButton = new System.Windows.Forms.ToolStripMenuItem(); + this.LocationTextBox = new CodeWalker.WinForms.ToolStripSpringTextBox(); + this.GoButton = new System.Windows.Forms.ToolStripButton(); + this.RefreshButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.SearchTextBox = new System.Windows.Forms.ToolStripTextBox(); + this.SearchButton = new System.Windows.Forms.ToolStripSplitButton(); + this.SearchGlobalButton = new System.Windows.Forms.ToolStripMenuItem(); + this.SearchFilterButton = new System.Windows.Forms.ToolStripMenuItem(); + this.StatusBar = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.FileImageList16 = new System.Windows.Forms.ImageList(this.components); + this.MainSplitContainer = new System.Windows.Forms.SplitContainer(); + this.MainTreeView = new System.Windows.Forms.TreeView(); + this.MainListView = new System.Windows.Forms.ListView(); + this.MainNameColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.MainTypeColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.MainSizeColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.MainAttrColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.MainPathColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.ListContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.ListContextViewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextViewHexMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.ListContextExportXmlMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextExtractRawMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextExtractAllMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); + this.ListContextImportXmlMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextImportRawMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextImportSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.ListContextCopyMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextCopyPathMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextCopyFileListMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.ListContextRenameMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextReplaceMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextDeleteMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ListContextEditSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.ListContextSelectAllMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.TreeContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.TreeContextCopyPathMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.TreeContextWinExplorerMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); + this.TreeContextExpandMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.TreeContextCollapseMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.TreeContextCollapseAllMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.ListContextOpenFileLocationSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.ListContextOpenFileLocationMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.MainMenu.SuspendLayout(); + this.MainToolbar.SuspendLayout(); + this.StatusBar.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.MainSplitContainer)).BeginInit(); + this.MainSplitContainer.Panel1.SuspendLayout(); + this.MainSplitContainer.Panel2.SuspendLayout(); + this.MainSplitContainer.SuspendLayout(); + this.ListContextMenu.SuspendLayout(); + this.TreeContextMenu.SuspendLayout(); + this.SuspendLayout(); + // + // MainMenu + // + this.MainMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileMenu, + this.EditMenu, + this.ViewMenu, + this.ToolsMenu}); + this.MainMenu.Location = new System.Drawing.Point(0, 0); + this.MainMenu.Name = "MainMenu"; + this.MainMenu.Size = new System.Drawing.Size(876, 24); + this.MainMenu.TabIndex = 0; + this.MainMenu.Text = "menuStrip1"; + // + // FileMenu + // + this.FileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileExitMenu}); + this.FileMenu.Name = "FileMenu"; + this.FileMenu.Size = new System.Drawing.Size(37, 20); + this.FileMenu.Text = "File"; + // + // FileExitMenu + // + this.FileExitMenu.Name = "FileExitMenu"; + this.FileExitMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); + this.FileExitMenu.Size = new System.Drawing.Size(134, 22); + this.FileExitMenu.Text = "Exit"; + this.FileExitMenu.Click += new System.EventHandler(this.FileExitMenu_Click); + // + // EditMenu + // + this.EditMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.EditViewMenu, + this.EditViewHexMenu, + this.toolStripSeparator3, + this.EditExportXmlMenu, + this.EditExtractRawMenu, + this.EditExtractAllMenu, + this.toolStripSeparator4, + this.EditImportXmlMenu, + this.EditImportRawMenu, + this.EditImportMenuSeparator, + this.EditCopyMenu, + this.EditCopyPathMenu, + this.EditCopyFileListMenu, + this.toolStripSeparator9, + this.EditRenameMenu, + this.EditReplaceMenu, + this.EditDeleteMenu, + this.EditEditModeMenuSeparator, + this.EditSelectAllMenu}); + this.EditMenu.Name = "EditMenu"; + this.EditMenu.Size = new System.Drawing.Size(39, 20); + this.EditMenu.Text = "Edit"; + // + // EditViewMenu + // + this.EditViewMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditViewMenu.Image"))); + this.EditViewMenu.Name = "EditViewMenu"; + this.EditViewMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); + this.EditViewMenu.Size = new System.Drawing.Size(207, 22); + this.EditViewMenu.Text = "View..."; + this.EditViewMenu.Click += new System.EventHandler(this.EditViewMenu_Click); + // + // EditViewHexMenu + // + this.EditViewHexMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditViewHexMenu.Image"))); + this.EditViewHexMenu.Name = "EditViewHexMenu"; + this.EditViewHexMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.H))); + this.EditViewHexMenu.Size = new System.Drawing.Size(207, 22); + this.EditViewHexMenu.Text = "View Hex..."; + this.EditViewHexMenu.Click += new System.EventHandler(this.EditViewHexMenu_Click); + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(204, 6); + // + // EditExportXmlMenu + // + this.EditExportXmlMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditExportXmlMenu.Image"))); + this.EditExportXmlMenu.Name = "EditExportXmlMenu"; + this.EditExportXmlMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.EditExportXmlMenu.Size = new System.Drawing.Size(207, 22); + this.EditExportXmlMenu.Text = "Export XML..."; + this.EditExportXmlMenu.Click += new System.EventHandler(this.EditExportXmlMenu_Click); + // + // EditExtractRawMenu + // + this.EditExtractRawMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditExtractRawMenu.Image"))); + this.EditExtractRawMenu.Name = "EditExtractRawMenu"; + this.EditExtractRawMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); + this.EditExtractRawMenu.Size = new System.Drawing.Size(207, 22); + this.EditExtractRawMenu.Text = "Extract Raw..."; + this.EditExtractRawMenu.Click += new System.EventHandler(this.EditExtractRawMenu_Click); + // + // EditExtractAllMenu + // + this.EditExtractAllMenu.Name = "EditExtractAllMenu"; + this.EditExtractAllMenu.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.E))); + this.EditExtractAllMenu.Size = new System.Drawing.Size(207, 22); + this.EditExtractAllMenu.Text = "Extract All..."; + this.EditExtractAllMenu.Click += new System.EventHandler(this.EditExtractAllMenu_Click); + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(204, 6); + // + // EditImportXmlMenu + // + this.EditImportXmlMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditImportXmlMenu.Image"))); + this.EditImportXmlMenu.Name = "EditImportXmlMenu"; + this.EditImportXmlMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Insert))); + this.EditImportXmlMenu.Size = new System.Drawing.Size(207, 22); + this.EditImportXmlMenu.Text = "Import XML..."; + this.EditImportXmlMenu.Visible = false; + this.EditImportXmlMenu.Click += new System.EventHandler(this.EditImportXmlMenu_Click); + // + // EditImportRawMenu + // + this.EditImportRawMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditImportRawMenu.Image"))); + this.EditImportRawMenu.Name = "EditImportRawMenu"; + this.EditImportRawMenu.ShortcutKeys = System.Windows.Forms.Keys.Insert; + this.EditImportRawMenu.Size = new System.Drawing.Size(207, 22); + this.EditImportRawMenu.Text = "Import Raw..."; + this.EditImportRawMenu.Visible = false; + this.EditImportRawMenu.Click += new System.EventHandler(this.EditImportRawMenu_Click); + // + // EditImportMenuSeparator + // + this.EditImportMenuSeparator.Name = "EditImportMenuSeparator"; + this.EditImportMenuSeparator.Size = new System.Drawing.Size(204, 6); + this.EditImportMenuSeparator.Visible = false; + // + // EditCopyMenu + // + this.EditCopyMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditCopyMenu.Image"))); + this.EditCopyMenu.Name = "EditCopyMenu"; + this.EditCopyMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); + this.EditCopyMenu.Size = new System.Drawing.Size(207, 22); + this.EditCopyMenu.Text = "Copy"; + this.EditCopyMenu.Click += new System.EventHandler(this.EditCopyMenu_Click); + // + // EditCopyPathMenu + // + this.EditCopyPathMenu.Name = "EditCopyPathMenu"; + this.EditCopyPathMenu.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.C))); + this.EditCopyPathMenu.Size = new System.Drawing.Size(207, 22); + this.EditCopyPathMenu.Text = "Copy Path"; + this.EditCopyPathMenu.Click += new System.EventHandler(this.EditCopyPathMenu_Click); + // + // EditCopyFileListMenu + // + this.EditCopyFileListMenu.Name = "EditCopyFileListMenu"; + this.EditCopyFileListMenu.Size = new System.Drawing.Size(207, 22); + this.EditCopyFileListMenu.Text = "Copy File List"; + this.EditCopyFileListMenu.Click += new System.EventHandler(this.EditCopyFileListMenu_Click); + // + // toolStripSeparator9 + // + this.toolStripSeparator9.Name = "toolStripSeparator9"; + this.toolStripSeparator9.Size = new System.Drawing.Size(204, 6); + // + // EditRenameMenu + // + this.EditRenameMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditRenameMenu.Image"))); + this.EditRenameMenu.Name = "EditRenameMenu"; + this.EditRenameMenu.ShortcutKeys = System.Windows.Forms.Keys.F2; + this.EditRenameMenu.Size = new System.Drawing.Size(207, 22); + this.EditRenameMenu.Text = "Rename..."; + this.EditRenameMenu.Visible = false; + this.EditRenameMenu.Click += new System.EventHandler(this.EditRenameMenu_Click); + // + // EditReplaceMenu + // + this.EditReplaceMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditReplaceMenu.Image"))); + this.EditReplaceMenu.Name = "EditReplaceMenu"; + this.EditReplaceMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Insert))); + this.EditReplaceMenu.Size = new System.Drawing.Size(207, 22); + this.EditReplaceMenu.Text = "Replace..."; + this.EditReplaceMenu.Visible = false; + this.EditReplaceMenu.Click += new System.EventHandler(this.EditReplaceMenu_Click); + // + // EditDeleteMenu + // + this.EditDeleteMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditDeleteMenu.Image"))); + this.EditDeleteMenu.Name = "EditDeleteMenu"; + this.EditDeleteMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Delete))); + this.EditDeleteMenu.Size = new System.Drawing.Size(207, 22); + this.EditDeleteMenu.Text = "Delete"; + this.EditDeleteMenu.Visible = false; + this.EditDeleteMenu.Click += new System.EventHandler(this.EditDeleteMenu_Click); + // + // EditEditModeMenuSeparator + // + this.EditEditModeMenuSeparator.Name = "EditEditModeMenuSeparator"; + this.EditEditModeMenuSeparator.Size = new System.Drawing.Size(204, 6); + this.EditEditModeMenuSeparator.Visible = false; + // + // EditSelectAllMenu + // + this.EditSelectAllMenu.Name = "EditSelectAllMenu"; + this.EditSelectAllMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A))); + this.EditSelectAllMenu.Size = new System.Drawing.Size(207, 22); + this.EditSelectAllMenu.Text = "Select All"; + this.EditSelectAllMenu.Click += new System.EventHandler(this.EditSelectAllMenu_Click); + // + // ViewMenu + // + this.ViewMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ViewLargeIconsMenu, + this.ViewSmallIconsMenu, + this.ViewListMenu, + this.ViewDetailsMenu}); + this.ViewMenu.Name = "ViewMenu"; + this.ViewMenu.Size = new System.Drawing.Size(44, 20); + this.ViewMenu.Text = "View"; + // + // ViewLargeIconsMenu + // + this.ViewLargeIconsMenu.Name = "ViewLargeIconsMenu"; + this.ViewLargeIconsMenu.Size = new System.Drawing.Size(134, 22); + this.ViewLargeIconsMenu.Text = "Large Icons"; + this.ViewLargeIconsMenu.Click += new System.EventHandler(this.ViewLargeIconsMenu_Click); + // + // ViewSmallIconsMenu + // + this.ViewSmallIconsMenu.Name = "ViewSmallIconsMenu"; + this.ViewSmallIconsMenu.Size = new System.Drawing.Size(134, 22); + this.ViewSmallIconsMenu.Text = "Small Icons"; + this.ViewSmallIconsMenu.Click += new System.EventHandler(this.ViewSmallIconsMenu_Click); + // + // ViewListMenu + // + this.ViewListMenu.Name = "ViewListMenu"; + this.ViewListMenu.Size = new System.Drawing.Size(134, 22); + this.ViewListMenu.Text = "List"; + this.ViewListMenu.Click += new System.EventHandler(this.ViewListMenu_Click); + // + // ViewDetailsMenu + // + this.ViewDetailsMenu.Checked = true; + this.ViewDetailsMenu.CheckState = System.Windows.Forms.CheckState.Checked; + this.ViewDetailsMenu.Name = "ViewDetailsMenu"; + this.ViewDetailsMenu.Size = new System.Drawing.Size(134, 22); + this.ViewDetailsMenu.Text = "Details"; + this.ViewDetailsMenu.Click += new System.EventHandler(this.ViewDetailsMenu_Click); + // + // ToolsMenu + // + this.ToolsMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolsRpfBrowserMenu, + this.toolStripSeparator7, + this.ToolsOptionsMenu}); + this.ToolsMenu.Name = "ToolsMenu"; + this.ToolsMenu.Size = new System.Drawing.Size(47, 20); + this.ToolsMenu.Text = "Tools"; + // + // ToolsRpfBrowserMenu + // + this.ToolsRpfBrowserMenu.Name = "ToolsRpfBrowserMenu"; + this.ToolsRpfBrowserMenu.Size = new System.Drawing.Size(161, 22); + this.ToolsRpfBrowserMenu.Text = "Old RPF Browser"; + this.ToolsRpfBrowserMenu.Click += new System.EventHandler(this.ToolsRpfBrowserMenu_Click); + // + // toolStripSeparator7 + // + this.toolStripSeparator7.Name = "toolStripSeparator7"; + this.toolStripSeparator7.Size = new System.Drawing.Size(158, 6); + // + // ToolsOptionsMenu + // + this.ToolsOptionsMenu.Name = "ToolsOptionsMenu"; + this.ToolsOptionsMenu.Size = new System.Drawing.Size(161, 22); + this.ToolsOptionsMenu.Text = "Options..."; + this.ToolsOptionsMenu.Click += new System.EventHandler(this.ToolsOptionsMenu_Click); + // + // MainToolbar + // + this.MainToolbar.CanOverflow = false; + this.MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.BackButton, + this.ForwardButton, + this.UpButton, + this.LocationTextBox, + this.GoButton, + this.RefreshButton, + this.toolStripSeparator1, + this.SearchTextBox, + this.SearchButton}); + this.MainToolbar.Location = new System.Drawing.Point(0, 24); + this.MainToolbar.Name = "MainToolbar"; + this.MainToolbar.Size = new System.Drawing.Size(876, 25); + this.MainToolbar.TabIndex = 1; + this.MainToolbar.Text = "Main Toolbar"; + // + // BackButton + // + this.BackButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.BackButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.BackListButton}); + this.BackButton.Enabled = false; + this.BackButton.Image = ((System.Drawing.Image)(resources.GetObject("BackButton.Image"))); + this.BackButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.BackButton.Name = "BackButton"; + this.BackButton.Size = new System.Drawing.Size(32, 22); + this.BackButton.Text = "Back"; + this.BackButton.ButtonClick += new System.EventHandler(this.BackButton_ButtonClick); + // + // BackListButton + // + this.BackListButton.Name = "BackListButton"; + this.BackListButton.Size = new System.Drawing.Size(100, 22); + this.BackListButton.Text = "[List]"; + this.BackListButton.Click += new System.EventHandler(this.BackListButton_Click); + // + // ForwardButton + // + this.ForwardButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ForwardButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ForwardListButton}); + this.ForwardButton.Enabled = false; + this.ForwardButton.Image = ((System.Drawing.Image)(resources.GetObject("ForwardButton.Image"))); + this.ForwardButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ForwardButton.Name = "ForwardButton"; + this.ForwardButton.Size = new System.Drawing.Size(32, 22); + this.ForwardButton.Text = "Forward"; + this.ForwardButton.ButtonClick += new System.EventHandler(this.ForwardButton_ButtonClick); + // + // ForwardListButton + // + this.ForwardListButton.Name = "ForwardListButton"; + this.ForwardListButton.Size = new System.Drawing.Size(100, 22); + this.ForwardListButton.Text = "[List]"; + this.ForwardListButton.Click += new System.EventHandler(this.ForwardListButton_Click); + // + // UpButton + // + this.UpButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.UpButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.UpListButton}); + this.UpButton.Enabled = false; + this.UpButton.Image = ((System.Drawing.Image)(resources.GetObject("UpButton.Image"))); + this.UpButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.UpButton.Name = "UpButton"; + this.UpButton.Size = new System.Drawing.Size(32, 22); + this.UpButton.Text = "Up"; + this.UpButton.ButtonClick += new System.EventHandler(this.UpButton_ButtonClick); + // + // UpListButton + // + this.UpListButton.Name = "UpListButton"; + this.UpListButton.Size = new System.Drawing.Size(100, 22); + this.UpListButton.Text = "[List]"; + this.UpListButton.Click += new System.EventHandler(this.UpListButton_Click); + // + // LocationTextBox + // + this.LocationTextBox.Name = "LocationTextBox"; + this.LocationTextBox.Size = new System.Drawing.Size(510, 25); + this.LocationTextBox.Enter += new System.EventHandler(this.LocationTextBox_Enter); + this.LocationTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.LocationTextBox_KeyPress); + // + // GoButton + // + this.GoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.GoButton.Enabled = false; + this.GoButton.Image = ((System.Drawing.Image)(resources.GetObject("GoButton.Image"))); + this.GoButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.GoButton.Name = "GoButton"; + this.GoButton.Size = new System.Drawing.Size(23, 22); + this.GoButton.Text = "Go"; + this.GoButton.Click += new System.EventHandler(this.GoButton_Click); + // + // RefreshButton + // + this.RefreshButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.RefreshButton.Enabled = false; + this.RefreshButton.Image = ((System.Drawing.Image)(resources.GetObject("RefreshButton.Image"))); + this.RefreshButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.RefreshButton.Name = "RefreshButton"; + this.RefreshButton.Size = new System.Drawing.Size(23, 22); + this.RefreshButton.Text = "Refresh All"; + this.RefreshButton.Click += new System.EventHandler(this.RefreshButton_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); + // + // SearchTextBox + // + this.SearchTextBox.Name = "SearchTextBox"; + this.SearchTextBox.Size = new System.Drawing.Size(140, 25); + this.SearchTextBox.Enter += new System.EventHandler(this.SearchTextBox_Enter); + this.SearchTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.SearchTextBox_KeyPress); + // + // SearchButton + // + this.SearchButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.SearchButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SearchGlobalButton, + this.SearchFilterButton}); + this.SearchButton.Enabled = false; + this.SearchButton.Image = ((System.Drawing.Image)(resources.GetObject("SearchButton.Image"))); + this.SearchButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.SearchButton.Margin = new System.Windows.Forms.Padding(0, 1, 1, 2); + this.SearchButton.Name = "SearchButton"; + this.SearchButton.Size = new System.Drawing.Size(32, 22); + this.SearchButton.Text = "Global Search"; + this.SearchButton.ButtonClick += new System.EventHandler(this.SearchButton_ButtonClick); + // + // SearchGlobalButton + // + this.SearchGlobalButton.Checked = true; + this.SearchGlobalButton.CheckState = System.Windows.Forms.CheckState.Checked; + this.SearchGlobalButton.Image = ((System.Drawing.Image)(resources.GetObject("SearchGlobalButton.Image"))); + this.SearchGlobalButton.Name = "SearchGlobalButton"; + this.SearchGlobalButton.Size = new System.Drawing.Size(146, 22); + this.SearchGlobalButton.Text = "Global Search"; + this.SearchGlobalButton.Click += new System.EventHandler(this.SearchGlobalButton_Click); + // + // SearchFilterButton + // + this.SearchFilterButton.Image = ((System.Drawing.Image)(resources.GetObject("SearchFilterButton.Image"))); + this.SearchFilterButton.Name = "SearchFilterButton"; + this.SearchFilterButton.Size = new System.Drawing.Size(146, 22); + this.SearchFilterButton.Text = "Filter"; + this.SearchFilterButton.Click += new System.EventHandler(this.SearchFilterButton_Click); + // + // StatusBar + // + this.StatusBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel}); + this.StatusBar.Location = new System.Drawing.Point(0, 565); + this.StatusBar.Name = "StatusBar"; + this.StatusBar.Size = new System.Drawing.Size(876, 22); + this.StatusBar.TabIndex = 2; + this.StatusBar.Text = "statusStrip1"; + // + // StatusLabel + // + this.StatusLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(861, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.Text = "Initialising..."; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // FileImageList16 + // + this.FileImageList16.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("FileImageList16.ImageStream"))); + this.FileImageList16.TransparentColor = System.Drawing.Color.Transparent; + this.FileImageList16.Images.SetKeyName(0, "CW16.ico"); + this.FileImageList16.Images.SetKeyName(1, "Folder_16x16.png"); + this.FileImageList16.Images.SetKeyName(2, "FolderOpen_16x16_72.png"); + this.FileImageList16.Images.SetKeyName(3, "OrganizerHS.png"); + this.FileImageList16.Images.SetKeyName(4, "document_16xLG.png"); + this.FileImageList16.Images.SetKeyName(5, "Textfile_818_16x.png"); + this.FileImageList16.Images.SetKeyName(6, "XMLFile_828_16x.png"); + this.FileImageList16.Images.SetKeyName(7, "ImageMapFile(map)_459.png"); + this.FileImageList16.Images.SetKeyName(8, "ChangeNodeURLfromFile_358.png"); + this.FileImageList16.Images.SetKeyName(9, "ID_FILE_PAGE_SETUP.png"); + this.FileImageList16.Images.SetKeyName(10, "WindowsForm_817_16x.png"); + this.FileImageList16.Images.SetKeyName(11, "ASCube_16xLG.png"); + this.FileImageList16.Images.SetKeyName(12, "3DScene_16x.png"); + this.FileImageList16.Images.SetKeyName(13, "script_16xLG.png"); + this.FileImageList16.Images.SetKeyName(14, "manifest_16xLG.png"); + this.FileImageList16.Images.SetKeyName(15, "filmstrip_16xLG.png"); + this.FileImageList16.Images.SetKeyName(16, "resource_16xLG.png"); + this.FileImageList16.Images.SetKeyName(17, "CanvasElement_10701.png"); + this.FileImageList16.Images.SetKeyName(18, "animation_16xLG.png"); + this.FileImageList16.Images.SetKeyName(19, "Assembly_6212.png"); + this.FileImageList16.Images.SetKeyName(20, "Library_6213.png"); + this.FileImageList16.Images.SetKeyName(21, "process_16xLG.png"); + this.FileImageList16.Images.SetKeyName(22, "Soundfile_461.png"); + this.FileImageList16.Images.SetKeyName(23, "AudioPlayback_AudioDRMSupport.png"); + // + // MainSplitContainer + // + this.MainSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.MainSplitContainer.Location = new System.Drawing.Point(0, 49); + this.MainSplitContainer.Name = "MainSplitContainer"; + // + // MainSplitContainer.Panel1 + // + this.MainSplitContainer.Panel1.Controls.Add(this.MainTreeView); + // + // MainSplitContainer.Panel2 + // + this.MainSplitContainer.Panel2.Controls.Add(this.MainListView); + this.MainSplitContainer.Size = new System.Drawing.Size(876, 516); + this.MainSplitContainer.SplitterDistance = 309; + this.MainSplitContainer.TabIndex = 3; + // + // MainTreeView + // + this.MainTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.MainTreeView.FullRowSelect = true; + this.MainTreeView.HideSelection = false; + this.MainTreeView.ImageIndex = 0; + this.MainTreeView.ImageList = this.FileImageList16; + this.MainTreeView.ItemHeight = 20; + this.MainTreeView.Location = new System.Drawing.Point(3, 3); + this.MainTreeView.Name = "MainTreeView"; + this.MainTreeView.SelectedImageIndex = 0; + this.MainTreeView.ShowLines = false; + this.MainTreeView.ShowNodeToolTips = true; + this.MainTreeView.Size = new System.Drawing.Size(305, 513); + this.MainTreeView.TabIndex = 0; + this.MainTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.MainTreeView_AfterSelect); + this.MainTreeView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MainTreeView_MouseUp); + // + // MainListView + // + this.MainListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainListView.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.MainListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.MainNameColumnHeader, + this.MainTypeColumnHeader, + this.MainSizeColumnHeader, + this.MainAttrColumnHeader, + this.MainPathColumnHeader}); + this.MainListView.FullRowSelect = true; + this.MainListView.HideSelection = false; + this.MainListView.Location = new System.Drawing.Point(1, 3); + this.MainListView.Name = "MainListView"; + this.MainListView.ShowItemToolTips = true; + this.MainListView.Size = new System.Drawing.Size(559, 513); + this.MainListView.SmallImageList = this.FileImageList16; + this.MainListView.TabIndex = 0; + this.MainListView.UseCompatibleStateImageBehavior = false; + this.MainListView.View = System.Windows.Forms.View.Details; + this.MainListView.VirtualMode = true; + this.MainListView.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.MainListView_ColumnClick); + this.MainListView.ItemActivate += new System.EventHandler(this.MainListView_ItemActivate); + this.MainListView.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.MainListView_RetrieveVirtualItem); + this.MainListView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MainListView_KeyDown); + this.MainListView.KeyUp += new System.Windows.Forms.KeyEventHandler(this.MainListView_KeyUp); + this.MainListView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MainListView_MouseUp); + // + // MainNameColumnHeader + // + this.MainNameColumnHeader.Text = "Name"; + this.MainNameColumnHeader.Width = 225; + // + // MainTypeColumnHeader + // + this.MainTypeColumnHeader.Text = "Type"; + this.MainTypeColumnHeader.Width = 120; + // + // MainSizeColumnHeader + // + this.MainSizeColumnHeader.Text = "Size"; + this.MainSizeColumnHeader.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; + this.MainSizeColumnHeader.Width = 70; + // + // MainAttrColumnHeader + // + this.MainAttrColumnHeader.Text = "Attributes"; + this.MainAttrColumnHeader.Width = 118; + // + // MainPathColumnHeader + // + this.MainPathColumnHeader.Text = "Path"; + this.MainPathColumnHeader.Width = 225; + // + // ListContextMenu + // + this.ListContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ListContextViewMenu, + this.ListContextViewHexMenu, + this.toolStripSeparator2, + this.ListContextExportXmlMenu, + this.ListContextExtractRawMenu, + this.ListContextExtractAllMenu, + this.toolStripSeparator5, + this.ListContextImportXmlMenu, + this.ListContextImportRawMenu, + this.ListContextImportSeparator, + this.ListContextCopyMenu, + this.ListContextCopyPathMenu, + this.ListContextCopyFileListMenu, + this.toolStripSeparator6, + this.ListContextOpenFileLocationMenu, + this.ListContextOpenFileLocationSeparator, + this.ListContextRenameMenu, + this.ListContextReplaceMenu, + this.ListContextDeleteMenu, + this.ListContextEditSeparator, + this.ListContextSelectAllMenu}); + this.ListContextMenu.Name = "MainContextMenu"; + this.ListContextMenu.Size = new System.Drawing.Size(208, 392); + // + // ListContextViewMenu + // + this.ListContextViewMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextViewMenu.Image"))); + this.ListContextViewMenu.Name = "ListContextViewMenu"; + this.ListContextViewMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); + this.ListContextViewMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextViewMenu.Text = "View..."; + this.ListContextViewMenu.Click += new System.EventHandler(this.ListContextViewMenu_Click); + // + // ListContextViewHexMenu + // + this.ListContextViewHexMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextViewHexMenu.Image"))); + this.ListContextViewHexMenu.Name = "ListContextViewHexMenu"; + this.ListContextViewHexMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.H))); + this.ListContextViewHexMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextViewHexMenu.Text = "View Hex..."; + this.ListContextViewHexMenu.Click += new System.EventHandler(this.ListContextViewHexMenu_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(204, 6); + // + // ListContextExportXmlMenu + // + this.ListContextExportXmlMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextExportXmlMenu.Image"))); + this.ListContextExportXmlMenu.Name = "ListContextExportXmlMenu"; + this.ListContextExportXmlMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.ListContextExportXmlMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextExportXmlMenu.Text = "Export XML..."; + this.ListContextExportXmlMenu.Click += new System.EventHandler(this.ListContextExportXmlMenu_Click); + // + // ListContextExtractRawMenu + // + this.ListContextExtractRawMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextExtractRawMenu.Image"))); + this.ListContextExtractRawMenu.Name = "ListContextExtractRawMenu"; + this.ListContextExtractRawMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); + this.ListContextExtractRawMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextExtractRawMenu.Text = "Extract Raw..."; + this.ListContextExtractRawMenu.Click += new System.EventHandler(this.ListContextExtractRawMenu_Click); + // + // ListContextExtractAllMenu + // + this.ListContextExtractAllMenu.Name = "ListContextExtractAllMenu"; + this.ListContextExtractAllMenu.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.E))); + this.ListContextExtractAllMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextExtractAllMenu.Text = "Extract All..."; + this.ListContextExtractAllMenu.Click += new System.EventHandler(this.ListContextExtractAllMenu_Click); + // + // toolStripSeparator5 + // + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new System.Drawing.Size(204, 6); + // + // ListContextImportXmlMenu + // + this.ListContextImportXmlMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextImportXmlMenu.Image"))); + this.ListContextImportXmlMenu.Name = "ListContextImportXmlMenu"; + this.ListContextImportXmlMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Insert))); + this.ListContextImportXmlMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextImportXmlMenu.Text = "Import XML..."; + this.ListContextImportXmlMenu.Click += new System.EventHandler(this.ListContextImportXmlMenu_Click); + // + // ListContextImportRawMenu + // + this.ListContextImportRawMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextImportRawMenu.Image"))); + this.ListContextImportRawMenu.Name = "ListContextImportRawMenu"; + this.ListContextImportRawMenu.ShortcutKeys = System.Windows.Forms.Keys.Insert; + this.ListContextImportRawMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextImportRawMenu.Text = "Import Raw..."; + this.ListContextImportRawMenu.Click += new System.EventHandler(this.ListContextImportRawMenu_Click); + // + // ListContextImportSeparator + // + this.ListContextImportSeparator.Name = "ListContextImportSeparator"; + this.ListContextImportSeparator.Size = new System.Drawing.Size(204, 6); + // + // ListContextCopyMenu + // + this.ListContextCopyMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextCopyMenu.Image"))); + this.ListContextCopyMenu.Name = "ListContextCopyMenu"; + this.ListContextCopyMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); + this.ListContextCopyMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextCopyMenu.Text = "Copy"; + this.ListContextCopyMenu.Click += new System.EventHandler(this.ListContextCopyMenu_Click); + // + // ListContextCopyPathMenu + // + this.ListContextCopyPathMenu.Name = "ListContextCopyPathMenu"; + this.ListContextCopyPathMenu.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.C))); + this.ListContextCopyPathMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextCopyPathMenu.Text = "Copy Path"; + this.ListContextCopyPathMenu.Click += new System.EventHandler(this.ListContextCopyPathMenu_Click); + // + // ListContextCopyFileListMenu + // + this.ListContextCopyFileListMenu.Name = "ListContextCopyFileListMenu"; + this.ListContextCopyFileListMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextCopyFileListMenu.Text = "Copy File List"; + this.ListContextCopyFileListMenu.Click += new System.EventHandler(this.ListContextCopyFileListMenu_Click); + // + // toolStripSeparator6 + // + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new System.Drawing.Size(204, 6); + // + // ListContextRenameMenu + // + this.ListContextRenameMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextRenameMenu.Image"))); + this.ListContextRenameMenu.Name = "ListContextRenameMenu"; + this.ListContextRenameMenu.ShortcutKeys = System.Windows.Forms.Keys.F2; + this.ListContextRenameMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextRenameMenu.Text = "Rename"; + this.ListContextRenameMenu.Click += new System.EventHandler(this.ListContextRenameMenu_Click); + // + // ListContextReplaceMenu + // + this.ListContextReplaceMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextReplaceMenu.Image"))); + this.ListContextReplaceMenu.Name = "ListContextReplaceMenu"; + this.ListContextReplaceMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Insert))); + this.ListContextReplaceMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextReplaceMenu.Text = "Replace..."; + this.ListContextReplaceMenu.Click += new System.EventHandler(this.ListContextReplaceMenu_Click); + // + // ListContextDeleteMenu + // + this.ListContextDeleteMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextDeleteMenu.Image"))); + this.ListContextDeleteMenu.Name = "ListContextDeleteMenu"; + this.ListContextDeleteMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Delete))); + this.ListContextDeleteMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextDeleteMenu.Text = "Delete"; + this.ListContextDeleteMenu.Click += new System.EventHandler(this.ListContextDeleteMenu_Click); + // + // ListContextEditSeparator + // + this.ListContextEditSeparator.Name = "ListContextEditSeparator"; + this.ListContextEditSeparator.Size = new System.Drawing.Size(204, 6); + // + // ListContextSelectAllMenu + // + this.ListContextSelectAllMenu.Name = "ListContextSelectAllMenu"; + this.ListContextSelectAllMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A))); + this.ListContextSelectAllMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextSelectAllMenu.Text = "Select All"; + this.ListContextSelectAllMenu.Click += new System.EventHandler(this.ListContextSelectAllMenu_Click); + // + // TreeContextMenu + // + this.TreeContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.TreeContextCopyPathMenu, + this.TreeContextWinExplorerMenu, + this.toolStripSeparator8, + this.TreeContextExpandMenu, + this.TreeContextCollapseMenu, + this.TreeContextCollapseAllMenu}); + this.TreeContextMenu.Name = "MainContextMenu"; + this.TreeContextMenu.Size = new System.Drawing.Size(214, 120); + // + // TreeContextCopyPathMenu + // + this.TreeContextCopyPathMenu.Image = ((System.Drawing.Image)(resources.GetObject("TreeContextCopyPathMenu.Image"))); + this.TreeContextCopyPathMenu.Name = "TreeContextCopyPathMenu"; + this.TreeContextCopyPathMenu.Size = new System.Drawing.Size(213, 22); + this.TreeContextCopyPathMenu.Text = "Copy Path"; + this.TreeContextCopyPathMenu.Click += new System.EventHandler(this.TreeContextCopyPathMenu_Click); + // + // TreeContextWinExplorerMenu + // + this.TreeContextWinExplorerMenu.Image = ((System.Drawing.Image)(resources.GetObject("TreeContextWinExplorerMenu.Image"))); + this.TreeContextWinExplorerMenu.Name = "TreeContextWinExplorerMenu"; + this.TreeContextWinExplorerMenu.Size = new System.Drawing.Size(213, 22); + this.TreeContextWinExplorerMenu.Text = "Show in Windows Explorer"; + this.TreeContextWinExplorerMenu.Click += new System.EventHandler(this.TreeContextWinExplorerMenu_Click); + // + // toolStripSeparator8 + // + this.toolStripSeparator8.Name = "toolStripSeparator8"; + this.toolStripSeparator8.Size = new System.Drawing.Size(210, 6); + // + // TreeContextExpandMenu + // + this.TreeContextExpandMenu.Name = "TreeContextExpandMenu"; + this.TreeContextExpandMenu.Size = new System.Drawing.Size(213, 22); + this.TreeContextExpandMenu.Text = "Expand"; + this.TreeContextExpandMenu.Click += new System.EventHandler(this.TreeContextExpandMenu_Click); + // + // TreeContextCollapseMenu + // + this.TreeContextCollapseMenu.Name = "TreeContextCollapseMenu"; + this.TreeContextCollapseMenu.Size = new System.Drawing.Size(213, 22); + this.TreeContextCollapseMenu.Text = "Collapse"; + this.TreeContextCollapseMenu.Click += new System.EventHandler(this.TreeContextCollapseMenu_Click); + // + // TreeContextCollapseAllMenu + // + this.TreeContextCollapseAllMenu.Name = "TreeContextCollapseAllMenu"; + this.TreeContextCollapseAllMenu.Size = new System.Drawing.Size(213, 22); + this.TreeContextCollapseAllMenu.Text = "Collapse All"; + this.TreeContextCollapseAllMenu.Click += new System.EventHandler(this.TreeContextCollapseAllMenu_Click); + // + // ListContextOpenFileLocationSeparator + // + this.ListContextOpenFileLocationSeparator.Name = "ListContextOpenFileLocationSeparator"; + this.ListContextOpenFileLocationSeparator.Size = new System.Drawing.Size(204, 6); + // + // ListContextOpenFileLocationMenu + // + this.ListContextOpenFileLocationMenu.Name = "ListContextOpenFileLocationMenu"; + this.ListContextOpenFileLocationMenu.Size = new System.Drawing.Size(207, 22); + this.ListContextOpenFileLocationMenu.Text = "Open File Location"; + this.ListContextOpenFileLocationMenu.Click += new System.EventHandler(this.ListContextOpenFileLocationMenu_Click); + // + // ExploreForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(876, 587); + this.Controls.Add(this.MainSplitContainer); + this.Controls.Add(this.StatusBar); + this.Controls.Add(this.MainToolbar); + this.Controls.Add(this.MainMenu); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.MainMenu; + this.Name = "ExploreForm"; + this.Text = "RPF Explorer - CodeWalker by dexyfex"; + this.Load += new System.EventHandler(this.ExploreForm_Load); + this.MainMenu.ResumeLayout(false); + this.MainMenu.PerformLayout(); + this.MainToolbar.ResumeLayout(false); + this.MainToolbar.PerformLayout(); + this.StatusBar.ResumeLayout(false); + this.StatusBar.PerformLayout(); + this.MainSplitContainer.Panel1.ResumeLayout(false); + this.MainSplitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.MainSplitContainer)).EndInit(); + this.MainSplitContainer.ResumeLayout(false); + this.ListContextMenu.ResumeLayout(false); + this.TreeContextMenu.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip MainMenu; + private System.Windows.Forms.ToolStripMenuItem FileMenu; + private System.Windows.Forms.ToolStripMenuItem EditMenu; + private System.Windows.Forms.ToolStripMenuItem ViewMenu; + private System.Windows.Forms.ToolStrip MainToolbar; + private System.Windows.Forms.StatusStrip StatusBar; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.ImageList FileImageList16; + private System.Windows.Forms.ToolStripSplitButton BackButton; + private System.Windows.Forms.ToolStripSplitButton ForwardButton; + private System.Windows.Forms.ToolStripSplitButton UpButton; + private WinForms.ToolStripSpringTextBox LocationTextBox; + private System.Windows.Forms.ToolStripButton RefreshButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripTextBox SearchTextBox; + private System.Windows.Forms.SplitContainer MainSplitContainer; + private System.Windows.Forms.TreeView MainTreeView; + private System.Windows.Forms.ListView MainListView; + private System.Windows.Forms.ColumnHeader MainNameColumnHeader; + private System.Windows.Forms.ColumnHeader MainTypeColumnHeader; + private System.Windows.Forms.ColumnHeader MainSizeColumnHeader; + private System.Windows.Forms.ColumnHeader MainAttrColumnHeader; + private System.Windows.Forms.ContextMenuStrip ListContextMenu; + private System.Windows.Forms.ToolStripMenuItem BackListButton; + private System.Windows.Forms.ToolStripMenuItem ForwardListButton; + private System.Windows.Forms.ToolStripMenuItem UpListButton; + private System.Windows.Forms.ToolStripButton GoButton; + private System.Windows.Forms.ToolStripSplitButton SearchButton; + private System.Windows.Forms.ToolStripMenuItem SearchGlobalButton; + private System.Windows.Forms.ToolStripMenuItem SearchFilterButton; + private System.Windows.Forms.ToolStripMenuItem ListContextViewMenu; + private System.Windows.Forms.ToolStripMenuItem ListContextViewHexMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem ListContextExportXmlMenu; + private System.Windows.Forms.ToolStripMenuItem ListContextExtractAllMenu; + private System.Windows.Forms.ToolStripSeparator ListContextImportSeparator; + private System.Windows.Forms.ToolStripMenuItem ListContextCopyPathMenu; + private System.Windows.Forms.ToolStripSeparator ListContextEditSeparator; + private System.Windows.Forms.ToolStripMenuItem ListContextSelectAllMenu; + private System.Windows.Forms.ToolStripMenuItem ListContextExtractRawMenu; + private System.Windows.Forms.ToolStripMenuItem ListContextCopyFileListMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.ToolStripMenuItem ListContextImportXmlMenu; + private System.Windows.Forms.ToolStripMenuItem ListContextImportRawMenu; + private System.Windows.Forms.ToolStripMenuItem ListContextCopyMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; + private System.Windows.Forms.ToolStripMenuItem ListContextRenameMenu; + private System.Windows.Forms.ToolStripMenuItem ListContextReplaceMenu; + private System.Windows.Forms.ToolStripMenuItem ListContextDeleteMenu; + private System.Windows.Forms.ContextMenuStrip TreeContextMenu; + private System.Windows.Forms.ToolStripMenuItem TreeContextCopyPathMenu; + private System.Windows.Forms.ToolStripMenuItem TreeContextWinExplorerMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator8; + private System.Windows.Forms.ToolStripMenuItem TreeContextExpandMenu; + private System.Windows.Forms.ToolStripMenuItem TreeContextCollapseMenu; + private System.Windows.Forms.ToolStripMenuItem TreeContextCollapseAllMenu; + private System.Windows.Forms.SaveFileDialog SaveFileDialog; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.ToolStripMenuItem FileExitMenu; + private System.Windows.Forms.ToolStripMenuItem EditViewMenu; + private System.Windows.Forms.ToolStripMenuItem EditViewHexMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripMenuItem EditExportXmlMenu; + private System.Windows.Forms.ToolStripMenuItem EditExtractRawMenu; + private System.Windows.Forms.ToolStripMenuItem EditExtractAllMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripMenuItem EditImportXmlMenu; + private System.Windows.Forms.ToolStripMenuItem EditImportRawMenu; + private System.Windows.Forms.ToolStripSeparator EditImportMenuSeparator; + private System.Windows.Forms.ToolStripMenuItem EditCopyMenu; + private System.Windows.Forms.ToolStripMenuItem EditCopyPathMenu; + private System.Windows.Forms.ToolStripMenuItem EditCopyFileListMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator9; + private System.Windows.Forms.ToolStripMenuItem EditRenameMenu; + private System.Windows.Forms.ToolStripMenuItem EditReplaceMenu; + private System.Windows.Forms.ToolStripMenuItem EditDeleteMenu; + private System.Windows.Forms.ToolStripSeparator EditEditModeMenuSeparator; + private System.Windows.Forms.ToolStripMenuItem EditSelectAllMenu; + private System.Windows.Forms.ToolStripMenuItem ViewLargeIconsMenu; + private System.Windows.Forms.ToolStripMenuItem ViewSmallIconsMenu; + private System.Windows.Forms.ToolStripMenuItem ViewListMenu; + private System.Windows.Forms.ToolStripMenuItem ViewDetailsMenu; + private System.Windows.Forms.ToolStripMenuItem ToolsMenu; + private System.Windows.Forms.ToolStripMenuItem ToolsOptionsMenu; + private System.Windows.Forms.ToolStripMenuItem ToolsRpfBrowserMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; + private System.Windows.Forms.ColumnHeader MainPathColumnHeader; + private System.Windows.Forms.ToolStripMenuItem ListContextOpenFileLocationMenu; + private System.Windows.Forms.ToolStripSeparator ListContextOpenFileLocationSeparator; + } +} \ No newline at end of file diff --git a/ExploreForm.cs b/ExploreForm.cs new file mode 100644 index 0000000..0f6f18e --- /dev/null +++ b/ExploreForm.cs @@ -0,0 +1,2568 @@ +using CodeWalker.Forms; +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using CodeWalker.World; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class ExploreForm : Form + { + private volatile bool Ready = false; + + private Dictionary FileTypes; + + private MainTreeFolder RootFolder; + private MainTreeFolder CurrentFolder; + private List CurrentFiles; + + private Stack BackSteps = new Stack(); + private Stack ForwardSteps = new Stack(); + private bool HistoryNavigating = false; + + private int SortColumnIndex = 0; + private SortOrder SortDirection = SortOrder.Ascending; + private int PreviousPathColumnWidth = 0; + + public volatile bool Searching = false; + private MainTreeFolder SearchResults; + + private List AllRpfs { get; set; } + private GameFileCache FileCache { get; set; } = new GameFileCache(); + private object FileCacheSyncRoot = new object(); + + private bool EditMode = false; + + + public ExploreForm() + { + InitializeComponent(); + + ShowMainListViewPathColumn(false); + } + + private void Init() + { + //called from ExploreForm_Load + + InitFileTypes(); + + if (!EnsureGTAFolder()) + { + Close(); + return; + } + + + Task.Run(() => + { + try + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); + } + catch + { + UpdateStatus("Unable to load gta5.exe!"); + return; + } + + UpdateStatus("Scanning..."); + + RefreshMainTreeView(); + + UpdateStatus("Scan complete."); + + InitFileCache(); + + + while (!IsDisposed) //run the file cache content thread until the form exits. + { + if (FileCache.IsInited) + { + FileCache.ContentThreadProc(); + + if (!FileCache.ItemsStillPending) + { + Thread.Sleep(10); + } + } + else + { + Thread.Sleep(20); + } + } + }); + } + + private void InitFileCache() + { + Task.Run(() => + { + lock (FileCacheSyncRoot) + { + if (!FileCache.IsInited) + { + UpdateStatus("Loading file cache..."); + var allRpfs = AllRpfs; + FileCache.Init(UpdateStatus, UpdateErrorLog, allRpfs); //inits main dicts and archetypes only... + + UpdateStatus("Loading materials..."); + BoundsMaterialTypes.Init(FileCache); + + UpdateStatus("Loading scenario types..."); + Scenarios.EnsureScenarioTypes(FileCache); + + UpdateStatus("File cache loaded."); + } + } + }); + } + public GameFileCache GetFileCache() + { + lock (FileCacheSyncRoot) + { + if (FileCache.IsInited) return FileCache; + } + InitFileCache(); //if we got here, it's not inited yet - init it! + return FileCache; //return it even though it's probably not inited yet.. + } + + private void InitFileTypes() + { + FileTypes = new Dictionary(); + InitFileType(".rpf", "Rage Package File", 3); + InitFileType("", "File", 4); + InitFileType(".dat", "Data File", 4); + InitFileType(".cab", "CAB File", 4); + InitFileType(".txt", "Text File", 5, FileTypeAction.ViewText); + InitFileType(".gxt2", "Global Text Table", 5, FileTypeAction.ViewGxt); + InitFileType(".log", "LOG File", 5, FileTypeAction.ViewText); + InitFileType(".ini", "Config Text", 5, FileTypeAction.ViewText); + InitFileType(".vdf", "Steam Script File", 5, FileTypeAction.ViewText); + InitFileType(".sps", "Shader Preset", 5, FileTypeAction.ViewText); + InitFileType(".xml", "XML File", 6, FileTypeAction.ViewXml); + InitFileType(".meta", "Metadata (XML)", 6, FileTypeAction.ViewXml); + InitFileType(".ymt", "Metadata (Binary)", 6, FileTypeAction.ViewYmt); + InitFileType(".pso", "Metadata (PSO)", 6, FileTypeAction.ViewJPso); + InitFileType(".gfx", "Scaleform Flash", 7); + InitFileType(".ynd", "Path Nodes", 8); + InitFileType(".ynv", "Nav Mesh", 9, FileTypeAction.ViewModel); + InitFileType(".yvr", "Vehicle Record", 9, FileTypeAction.ViewYvr); + InitFileType(".ywr", "Waypoint Record", 9, FileTypeAction.ViewYwr); + InitFileType(".fxc", "Compiled Shaders", 9, FileTypeAction.ViewFxc); + InitFileType(".yed", "Expression Dictionary", 9); + InitFileType(".asi", "ASI Plugin", 9); + InitFileType(".dll", "Dynamic Link Library", 9); + InitFileType(".exe", "Executable", 10); + InitFileType(".yft", "Fragment", 11, FileTypeAction.ViewModel); + InitFileType(".ydr", "Drawable", 11, FileTypeAction.ViewModel); + InitFileType(".ydd", "Drawable Dictionary", 12, FileTypeAction.ViewModel); + InitFileType(".cut", "Cutscene", 12, FileTypeAction.ViewCut); + InitFileType(".ysc", "Script", 13); + InitFileType(".ymf", "Manifest", 14, FileTypeAction.ViewYmf); + InitFileType(".bik", "Bink Video", 15); + InitFileType(".jpg", "JPEG Image", 16); + InitFileType(".jpeg", "JPEG Image", 16); + InitFileType(".gif", "GIF Image", 16); + InitFileType(".png", "Portable Network Graphics", 16); + InitFileType(".dds", "DirectDraw Surface", 16); + InitFileType(".ytd", "Texture Dictionary", 16, FileTypeAction.ViewYtd); + InitFileType(".mrf", "MRF File", 18); + InitFileType(".ycd", "Clip Dictionary", 18); + InitFileType(".ypt", "Particle Effect", 18, FileTypeAction.ViewModel); + InitFileType(".ybn", "Static Collisions", 19, FileTypeAction.ViewModel); + InitFileType(".ide", "Item Definitions", 20, FileTypeAction.ViewText); + InitFileType(".ytyp", "Archetype Definitions", 20, FileTypeAction.ViewYtyp); + InitFileType(".ymap", "Map Data", 21, FileTypeAction.ViewYmap); + InitFileType(".ipl", "Item Placements", 21, FileTypeAction.ViewText); + InitFileType(".awc", "Audio Wave Container", 22, FileTypeAction.ViewAwc); + InitFileType(".rel", "Audio Data (REL)", 23, FileTypeAction.ViewRel); + + } + private void InitFileType(string ext, string name, int imgidx, FileTypeAction defaultAction = FileTypeAction.ViewHex) + { + var ft = new FileTypeInfo(ext, name, imgidx, defaultAction); + FileTypes[ext] = ft; + } + public FileTypeInfo GetFileType(string fn) + { + var fi = new FileInfo(fn); + var ext = fi.Extension.ToLower(); + if (!string.IsNullOrEmpty(ext)) + { + FileTypeInfo ft; + if (FileTypes.TryGetValue(ext, out ft)) + { + return ft; + } + else + { + ft = new FileTypeInfo(ext, ext.Substring(1).ToUpperInvariant() + " File", 4, FileTypeAction.ViewHex); + FileTypes[ft.Extension] = ft; //save it for later! + return ft; + } + } + else + { + return FileTypes[""]; + } + } + + private bool EnsureGTAFolder() + { + string fldr = Settings.Default.GTAFolder; + if (string.IsNullOrEmpty(fldr) || !Directory.Exists(fldr)) + { + if (!ChangeGTAFolder()) + { + return false; + } + fldr = Settings.Default.GTAFolder; + } + if (!Directory.Exists(fldr)) + { + MessageBox.Show("The specified folder does not exist:\n" + fldr); + return false; + } + if (!File.Exists(fldr + "\\gta5.exe")) + { + MessageBox.Show("GTA5.exe not found in folder:\n" + fldr); + return false; + } + Settings.Default.GTAFolder = fldr; //seems ok, save it for later + return true; + } + private bool ChangeGTAFolder() + { + SelectFolderForm f = new SelectFolderForm(); + f.ShowDialog(); + if (f.Result == DialogResult.OK) + { + Settings.Default.GTAFolder = f.SelectedFolder; + return true; + } + else + { + return false; + } + } + + + public void UpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateStatus(text); })); + } + else + { + StatusLabel.Text = text; + } + } + catch { } + } + public void UpdateErrorLog(string text) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateErrorLog(text); })); + } + else + { + //StatusLabel.Text = text; + } + } + catch { } + } + + + public static string GetRootPath() + { + var path = Settings.Default.GTAFolder; + return path.EndsWith("\\") ? path : path + "\\"; + } + + + public void Navigate(MainTreeFolder f) + { + if (!Ready) return; + if (f == CurrentFolder) return; //already there! + if (f.IsSearchResults) + { + foreach (TreeNode tn in MainTreeView.Nodes) + { + var tnf = tn.Tag as MainTreeFolder; + if ((tnf != null) && (tnf.IsSearchResults)) + { + MainTreeView.Nodes.Remove(tn); //remove existing search result node + break; + } + } + + AddMainTreeViewRoot(f); //add the current search result node + + TreeNode sr = FindTreeNode(f, null); + if (sr != null) + { + MainTreeView.SelectedNode = sr; //navigate to the new search results node + } + return; + } + List hierarchy = new List(); + var pf = f; + while (pf != null) + { + hierarchy.Add(pf); + pf = pf.Parent; + } + TreeNode n = null; + for (int i = hierarchy.Count - 1; i >= 0; i--) + { + n = FindTreeNode(hierarchy[i], n); + } + if (n != null) + { + if (MainTreeView.SelectedNode != n) + { + MainTreeView.SelectedNode = n; //this will trigger everything else + } + } + else + { + Navigate(f.Path); //try again using the path string... + //NavigateFailed(f.Path); //unable to navigate... + } + } + public void Navigate(string path) + { + if (!Ready) return; + var pathl = path.ToLowerInvariant().Replace('/', '\\'); + if ((CurrentFolder != null) && (CurrentFolder.Path.ToLowerInvariant() == pathl)) return; //already there + var hierarchy = pathl.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); + TreeNode n = MainTreeView.Nodes[0];// FindTreeNode("gta v", null); + if (!string.IsNullOrEmpty(path)) + { + for (int i = 0; i < hierarchy.Length; i++) + { + n = FindTreeNode(hierarchy[i], n); + } + } + if (n != null) + { + if (MainTreeView.SelectedNode != n) + { + MainTreeView.SelectedNode = n; //this will trigger everything else + } + } + else + { + NavigateFailed(path); //unable to navigate... + } + } + private void NavigateFailed(string path) + { + MessageBox.Show("Unable to navigate to \"" + path + "\"."); + } + private void NavigateComplete(MainTreeFolder prevFolder) + { + //called after the CurrentFolder and CurrentFiles have changed. + + UpdateNavigateUI(); + + if (!HistoryNavigating) //only do this if not currently navigating forward or back + { + if (prevFolder != null) + { + ForwardSteps.Clear(); + BackSteps.Push(prevFolder); + } + UpdateHistoryUI(); + } + + GoButton.Enabled = true; + RefreshButton.Enabled = true; + SearchButton.Enabled = true; + } + + public void GoUp(MainTreeFolder toFolder = null) + { + var fld = (toFolder == null) ? CurrentFolder?.Parent : toFolder; + if (fld == null) return; + Navigate(fld); + } + public void GoBack(MainTreeFolder toFolder = null) + { + if (BackSteps.Count == 0) return; + var s = BackSteps.Pop(); + ForwardSteps.Push(CurrentFolder); + while ((toFolder != null) && (s != toFolder) && (BackSteps.Count > 0)) + { + ForwardSteps.Push(s); + s = BackSteps.Pop(); + } + HistoryNavigating = true; + Navigate(s); + HistoryNavigating = false; + UpdateHistoryUI(); + } + public void GoForward(MainTreeFolder toFolder = null) + { + if (ForwardSteps.Count == 0) return; + var s = ForwardSteps.Pop(); + BackSteps.Push(CurrentFolder); + while ((toFolder != null) && (s != toFolder) && (ForwardSteps.Count > 0)) + { + BackSteps.Push(s); + s = ForwardSteps.Pop(); + } + HistoryNavigating = true; + Navigate(s); + HistoryNavigating = false; + UpdateHistoryUI(); + } + + private void UpdateNavigateUI() + { + UpButton.DropDownItems.Clear(); + var pf = CurrentFolder?.Parent; + int i = 0; + while (pf != null) + { + var button = UpButton.DropDownItems.Add(pf.GetToolText()); + button.Tag = pf; + button.Click += UpListButton_Click; + pf = pf.Parent; + if (i >= 10) break; + } + UpButton.Enabled = (UpButton.DropDownItems.Count > 0); + } + private void UpdateHistoryUI() + { + BackButton.DropDownItems.Clear(); + ForwardButton.DropDownItems.Clear(); + int i = 0; + foreach (var step in BackSteps) + { + var button = BackButton.DropDownItems.Add(step.GetToolText()); + button.Tag = step; + button.Click += BackListButton_Click; + i++; + if (i >= 10) break; + } + i = 0; + foreach (var step in ForwardSteps) + { + var button = ForwardButton.DropDownItems.Add(step.GetToolText()); + button.Tag = step; + button.Click += ForwardListButton_Click; + i++; + if (i >= 10) break; + } + BackButton.Enabled = (BackSteps.Count > 0); + ForwardButton.Enabled = (ForwardSteps.Count > 0); + } + private void UpdateSelectionUI() + { + var ic = MainListView.VirtualListSize; + var sc = MainListView.SelectedIndices.Count; + var str = ic.ToString() + " item" + ((ic != 1) ? "s" : "") + " shown"; + bool isitem = false; + bool isfile = false; + bool canview = false; + bool canedit = false; + bool canexportxml = false; + bool canimport = false; + if (sc != 0) + { + long bc = 0; + if (CurrentFiles != null) + { + foreach (int idx in MainListView.SelectedIndices) + { + if ((idx < 0) || (idx >= CurrentFiles.Count)) continue; + var file = CurrentFiles[idx]; + if ((file.Folder == null) || (file.Folder.RpfFile != null)) + { + bc += file.FileSize; + } + + isitem = true; + isfile = isfile || (file.Folder == null); + canview = canview || CanViewFile(file); + + } + } + str += ", " + sc.ToString() + " selected"; + if (bc > 0) + { + str += ", " + TextUtil.GetBytesReadable(bc); + } + } + UpdateStatus(str); + + + + EditViewMenu.Enabled = canview; + EditViewHexMenu.Enabled = isfile; + + EditExportXmlMenu.Enabled = canexportxml; + EditExtractRawMenu.Enabled = isfile; + + EditImportRawMenu.Visible = canimport; + EditImportXmlMenu.Visible = canimport; + EditImportMenuSeparator.Visible = canimport; + + EditCopyMenu.Enabled = isfile; + EditCopyPathMenu.Enabled = isitem; + + EditRenameMenu.Visible = canedit; + EditReplaceMenu.Visible = canedit; + EditDeleteMenu.Visible = canedit; + EditEditModeMenuSeparator.Visible = canedit; + + } + + private TreeNode FindTreeNode(MainTreeFolder f, TreeNode parent) + { + var tnc = (parent != null) ? parent.Nodes : MainTreeView.Nodes; + foreach (TreeNode node in tnc) + { + if (node.Tag == f) + { + return node; + } + } + return null; + } + private TreeNode FindTreeNode(string text, TreeNode parent) + { + var tnc = (parent != null) ? parent.Nodes : MainTreeView.Nodes; + foreach (TreeNode node in tnc) + { + if (node.Text.ToLowerInvariant() == text) + { + return node; + } + } + return null; + } + + + + private void RefreshMainTreeView() + { + Ready = false; + + var allRpfs = new List(); + + ClearMainTreeView(); + + var path = Settings.Default.GTAFolder; + var replpath = path.EndsWith("\\") ? path : path + "\\"; + + string[] allfiles = Directory.GetFiles(path, "*", SearchOption.AllDirectories); + + Dictionary nodes = new Dictionary(); + + MainTreeFolder root = new MainTreeFolder(); + root.FullPath = GetRootPath(); + root.Path = ""; + root.Name = "GTA V"; + RootFolder = root; + + UpdateStatus("Scanning..."); + + foreach (var filepath in allfiles) + { + var relpath = filepath.Replace(replpath, ""); + var filepathl = filepath.ToLowerInvariant(); + + UpdateStatus("Scanning " + relpath + "..."); + + MainTreeFolder parentnode = null, prevnode = null, node = null; + var prevnodepath = ""; + var idx = relpath.LastIndexOf('\\'); + while (idx > 0) //create the folder tree nodes and build up the hierarchy + { + var parentpath = relpath.Substring(0, idx); + var parentidx = parentpath.LastIndexOf('\\'); + var parentname = parentpath.Substring(parentidx + 1); + var exists = nodes.TryGetValue(parentpath, out node); + if (!exists) + { + node = new MainTreeFolder(); + node.Name = parentname; + node.Path = parentpath; + node.FullPath = replpath + parentpath; + nodes[parentpath] = node; + } + if (parentnode == null) + { + parentnode = node; + } + if (prevnode != null) + { + node.AddChild(prevnode); + } + prevnode = node; + prevnodepath = parentpath; + idx = relpath.LastIndexOf('\\', idx - 1); + if (exists) break; + if (idx < 0) + { + root.AddChild(node); + } + } + + if (filepathl.EndsWith(".rpf")) //add RPF nodes + { + RpfFile rpf = new RpfFile(filepath, relpath); + + rpf.ScanStructure(UpdateStatus, UpdateErrorLog); + + node = new MainTreeFolder(); + node.RpfFile = rpf; + node.RpfFolder = rpf.Root; + node.Name = rpf.Name; + node.Path = relpath; + node.FullPath = filepath; + + RecurseMainTreeViewRPF(node, allRpfs); + + if (parentnode != null) + { + parentnode.AddChild(node); + } + else + { + root.AddChild(node); + } + } + else + { + if (parentnode != null) + { + parentnode.AddFile(filepath); + } + else + { + root.AddFile(filepath); + } + } + } + + + AddMainTreeViewRoot(root); + + if (root.Children != null) + { + root.Children.Sort((n1, n2) => n1.Name.CompareTo(n2.Name)); + + foreach (var node in root.Children) + { + AddMainTreeViewNode(node); + } + } + + AllRpfs = allRpfs; + + Ready = true; + + MainTreeViewRefreshComplete(); + } + private void RecurseMainTreeViewRPF(MainTreeFolder f, List allRpfs) + { + var rootpath = GetRootPath(); + + var fld = f.RpfFolder; + if (fld != null) + { + if (fld.Directories != null) + { + foreach (var dir in fld.Directories) + { + MainTreeFolder dtnf = new MainTreeFolder(); + dtnf.RpfFolder = dir; + dtnf.Name = dir.Name; + dtnf.Path = dir.Path; + dtnf.FullPath = rootpath + dir.Path; + f.AddChild(dtnf); + RecurseMainTreeViewRPF(dtnf, allRpfs); + } + } + } + + var rpf = f.RpfFile; + if (rpf != null) + { + allRpfs.Add(rpf); + + if (rpf.Children != null) + { + foreach (var child in rpf.Children) + { + MainTreeFolder ctnf = new MainTreeFolder(); + ctnf.RpfFile = child; + ctnf.RpfFolder = child.Root; + ctnf.Name = child.Name; + ctnf.Path = child.Path; + ctnf.FullPath = rootpath + child.Path; + f.AddChildToHierarchy(ctnf); + RecurseMainTreeViewRPF(ctnf, allRpfs); + } + } + + JenkIndex.Ensure(rpf.Name); + if (rpf.AllEntries != null) + { + foreach (RpfEntry entry in rpf.AllEntries) + { + if (string.IsNullOrEmpty(entry.NameLower)) continue; + JenkIndex.Ensure(entry.Name); + JenkIndex.Ensure(entry.NameLower); + entry.NameHash = JenkHash.GenHash(entry.NameLower); + int ind = entry.Name.LastIndexOf('.'); + if (ind > 0) + { + var shortname = entry.Name.Substring(0, ind); + var shortnamel = entry.NameLower.Substring(0, ind); + JenkIndex.Ensure(shortname); + JenkIndex.Ensure(shortnamel); + entry.ShortNameHash = JenkHash.GenHash(shortnamel); + } + } + } + } + } + private void ClearMainTreeView() + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { ClearMainTreeView(); })); + } + else + { + GoButton.Enabled = false; + UpButton.Enabled = false; + BackButton.Enabled = false; + ForwardButton.Enabled = false; + RefreshButton.Enabled = false; + SearchButton.Enabled = false; + MainTreeView.Nodes.Clear(); + MainListView.VirtualListSize = 0; //also clear the list view... + } + } + catch { } + } + private void AddMainTreeViewRoot(MainTreeFolder f) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { AddMainTreeViewRoot(f); })); + } + else + { + var rn = MainTreeView.Nodes.Add(f.Path, f.Name, 0, 0); //ROOT imageIndex + rn.ToolTipText = f.FullPath; + rn.Tag = f; + } + } + catch { } + } + private void AddMainTreeViewNode(MainTreeFolder f) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { AddMainTreeViewNode(f); })); + } + else + { + string n = f.Name; + var root = (MainTreeView.Nodes.Count > 0) ? MainTreeView.Nodes[0] : null; + + RecurseAddMainTreeViewNodes(f, root); + + root.Expand(); + } + } + catch { } + } + private void RecurseAddMainTreeViewNodes(MainTreeFolder f, TreeNode parent) + { + int imgIndex = 1; //FOLDER imageIndex + if (f.RpfFile != null) imgIndex = 3; //RPF FILE imageIndex + + var nc = (parent != null) ? parent.Nodes : MainTreeView.Nodes; + + var tn = nc.Add(f.Path, f.Name, imgIndex, imgIndex); + + tn.ToolTipText = f.Path; + tn.Tag = f; + + if (f.Children != null) + { + f.Children.Sort((n1, n2) => n1.Name.CompareTo(n2.Name)); + + foreach (var child in f.Children) + { + RecurseAddMainTreeViewNodes(child, tn); + } + } + } + private void MainTreeViewRefreshComplete() + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { MainTreeViewRefreshComplete(); })); + } + else + { + if (CurrentFolder != null) + { + if (CurrentFolder.IsSearchResults) + { + Search(CurrentFolder.SearchTerm); + } + else + { + var path = CurrentFolder.Path; + CurrentFolder = null; + Navigate(path); + } + } + else + { + Navigate(RootFolder); + } + } + } + catch { } + } + + private void RefreshMainListView() + { + MainListView.VirtualListSize = 0; + if (CurrentFolder != null) + { + CurrentFiles = CurrentFolder.GetListItems(); + + foreach (var file in CurrentFiles) //cache all the data for use by the list view. + { + file.CacheDetails(this); + } + + SortMainListView(SortColumnIndex, SortDirection); //sorts CurrentItems and sets VirtualListSize + + ShowMainListViewPathColumn(CurrentFolder.IsSearchResults); + } + else + { + UpdateSelectionUI(); + + ShowMainListViewPathColumn(false); + } + } + private void SortMainListView(int col, SortOrder dir) + { + if (dir == SortOrder.None) dir = SortOrder.Ascending; //none not supported for actual sorting! + + SortColumnIndex = col; + SortDirection = dir; + + MainListView.SetSortIcon(col, dir); + + MainListView.VirtualListSize = 0; + + if (CurrentFiles == null) return; + + CurrentFiles.Sort((i1, i2) => i1.SortCompare(i2, col, dir)); + + MainListView.VirtualListSize = CurrentFiles.Count; + + UpdateSelectionUI(); + } + + private void ShowMainListViewPathColumn(bool show) + { + bool visible = (MainPathColumnHeader.Width > 0); + if (show && !visible) + { + MainPathColumnHeader.Width = PreviousPathColumnWidth; + } + else if (!show && visible) + { + PreviousPathColumnWidth = MainPathColumnHeader.Width; + MainPathColumnHeader.Width = 0; + if (SortColumnIndex == 4)//path col + { + SortMainListView(0, SortDirection);//switch sort to name col + } + } + } + + + public void Search(string text) + { + if (!Ready) return; + if (Searching) return; + if (string.IsNullOrEmpty(text)) return; + + SearchTextBox.Text = text; + SearchButton.Image = SearchGlobalButton.Image; + SearchButton.Text = SearchGlobalButton.Text; + SearchGlobalButton.Checked = true; + SearchFilterButton.Checked = false; + + SearchResults = new MainTreeFolder(); + SearchResults.Name = "Search Results: " + text; + SearchResults.Path = SearchResults.Name; + SearchResults.IsSearchResults = true; + SearchResults.SearchTerm = text; + + Navigate(SearchResults); + + SortDirection = SortOrder.None; + MainListView.SetSortIcon(SortColumnIndex, SortDirection); + MainListView.VirtualListSize = 0; + + CurrentFiles.Clear(); + + UpdateStatus("Searching..."); + + var term = text.ToLowerInvariant(); + + //Task.Run(() => + //{ + Searching = true; + + Cursor = Cursors.WaitCursor; + + var resultcount = RootFolder.Search(term, this); + + if (Searching) + { + Searching = false; + UpdateStatus("Search complete. " + resultcount.ToString() + " items found."); + } + else + { + UpdateStatus("Search aborted. " + resultcount.ToString() + " items found."); + } + + Cursor = Cursors.Default; + + //}); + } + + public void Filter(string text) + { + SearchTextBox.Text = text; + SearchButton.Image = SearchFilterButton.Image; + SearchButton.Text = SearchFilterButton.Text; + SearchGlobalButton.Checked = false; + SearchFilterButton.Checked = true; + + //TODO! + MessageBox.Show("Filter TODO!"); + } + + + public void AddSearchResult(MainListItem item) + { + if (SearchResults == null) return; + if (SearchResults.ListItems != CurrentFiles) return; + + if (item != null) + { + item.CacheDetails(this); + CurrentFiles.Add(item); + } + else + { + MainListView.VirtualListSize = CurrentFiles.Count; + } + + //try + //{ + // if (InvokeRequired) + // { + // BeginInvoke(new Action(() => { AddSearchResultInner(item); })); + // } + // else + // { + // AddSearchResultInner(item); + // } + //} + //catch { } + } + + + + + private byte[] GetFileData(MainListItem file) + { + byte[] data = null; + if (file.File != null) + { + //load file from RPF + if (file.File.File == null) return null; //no RPF file? go no further + data = file.File.File.ExtractFile(file.File); + } + else if (!string.IsNullOrEmpty(file.FullPath)) + { + //load file from filesystem + data = File.ReadAllBytes(file.FullPath); + } + return data; + } + + private bool CanViewFile(MainListItem item) + { + if (item == null) return false; + if (item.FileType == null) return false; + switch (item.FileType.DefaultAction) + { + case FileTypeAction.ViewText: + case FileTypeAction.ViewXml: + case FileTypeAction.ViewYtd: + case FileTypeAction.ViewYmt: + case FileTypeAction.ViewYmf: + case FileTypeAction.ViewYmap: + case FileTypeAction.ViewYtyp: + case FileTypeAction.ViewJPso: + case FileTypeAction.ViewModel: + case FileTypeAction.ViewCut: + case FileTypeAction.ViewAwc: + case FileTypeAction.ViewGxt: + case FileTypeAction.ViewRel: + case FileTypeAction.ViewFxc: + case FileTypeAction.ViewYwr: + case FileTypeAction.ViewYvr: + return true; + case FileTypeAction.ViewHex: + default: + break; + } + return false; + } + + + + private void View(MainListItem item) + { +#if !DEBUG + try +#endif + { + byte[] data = null; + string name = ""; + string path = ""; + if (item.File != null) + { + //load file from RPF + if (item.File.File == null) return; //no RPF file? go no further + data = item.File.File.ExtractFile(item.File); + name = item.Name; + path = item.FullPath; + } + else if (!string.IsNullOrEmpty(item.FullPath)) + { + //load file from filesystem + data = File.ReadAllBytes(item.FullPath); + name = new FileInfo(item.FullPath).Name; + path = item.FullPath; + } + + if (data == null) return; + + var ft = item.FileType; + switch (ft.DefaultAction) + { + case FileTypeAction.ViewText: + ViewText(name, path, data); + break; + case FileTypeAction.ViewXml: + ViewXml(name, path, data); + break; + case FileTypeAction.ViewYtd: + ViewYtd(name, path, data, item.File); + break; + case FileTypeAction.ViewYmt: + ViewYmt(name, path, data, item.File); + break; + case FileTypeAction.ViewYmf: + ViewYmf(name, path, data, item.File); + break; + case FileTypeAction.ViewYmap: + ViewYmap(name, path, data, item.File); + break; + case FileTypeAction.ViewYtyp: + ViewYtyp(name, path, data, item.File); + break; + case FileTypeAction.ViewJPso: + ViewJPso(name, path, data, item.File); + break; + case FileTypeAction.ViewCut: + ViewCut(name, path, data, item.File); + break; + case FileTypeAction.ViewModel: + ViewModel(name, path, data, item.File); + break; + case FileTypeAction.ViewAwc: + ViewAwc(name, path, data, item.File); + break; + case FileTypeAction.ViewGxt: + ViewGxt(name, path, data, item.File); + break; + case FileTypeAction.ViewRel: + ViewRel(name, path, data, item.File); + break; + case FileTypeAction.ViewFxc: + ViewFxc(name, path, data, item.File); + break; + case FileTypeAction.ViewYwr: + ViewYwr(name, path, data, item.File); + break; + case FileTypeAction.ViewYvr: + ViewYvr(name, path, data, item.File); + break; + case FileTypeAction.ViewHex: + default: + ViewHex(name, path, data); + break; + } + } +#if !DEBUG + catch (Exception ex) + { + UpdateErrorLog(ex.ToString()); + return; + } +#endif + } + private void ViewHex(MainListItem item) + { + try + { + byte[] data = null; + string name = ""; + string path = ""; + if (item.File != null) + { + //load file from RPF + if (item.File.File == null) return; //no RPF file? go no further + data = item.File.File.ExtractFile(item.File); + name = item.Name; + path = item.FullPath; + } + else if (!string.IsNullOrEmpty(item.FullPath)) + { + //load file from filesystem + data = File.ReadAllBytes(item.FullPath); + name = new FileInfo(item.FullPath).Name; + path = item.FullPath; + } + + if (data == null) return; + + ViewHex(name, path, data); + } + catch (Exception ex) + { + UpdateErrorLog(ex.ToString()); + return; + } + } + private void ViewHex(string name, string path, byte[] data) + { + HexForm f = new HexForm(); + f.Show(); + f.LoadData(name, path, data); + } + private void ViewXml(string name, string path, byte[] data) + { + string xml = Encoding.UTF8.GetString(data); + XmlForm f = new XmlForm(); + f.Show(); + f.LoadXml(name, path, xml); + } + private void ViewText(string name, string path, byte[] data) + { + string txt = Encoding.UTF8.GetString(data); + TextForm f = new TextForm(); + f.Show(); + f.LoadText(name, path, txt); + } + private void ViewYtd(string name, string path, byte[] data, RpfFileEntry e) + { + var ytd = RpfFile.GetFile(e, data); + YtdForm f = new YtdForm(); + f.Show(); + f.LoadYtd(ytd); + } + private void ViewYmt(string name, string path, byte[] data, RpfFileEntry e) + { + var ymt = RpfFile.GetFile(e, data); + MetaForm f = new MetaForm(); + f.Show(); + f.LoadMeta(ymt); + } + private void ViewYmf(string name, string path, byte[] data, RpfFileEntry e) + { + var ymf = RpfFile.GetFile(e, data); + MetaForm f = new MetaForm(); + f.Show(); + f.LoadMeta(ymf); + } + private void ViewYmap(string name, string path, byte[] data, RpfFileEntry e) + { + var ymap = RpfFile.GetFile(e, data); + MetaForm f = new MetaForm(); + f.Show(); + f.LoadMeta(ymap); + } + private void ViewYtyp(string name, string path, byte[] data, RpfFileEntry e) + { + var ytyp = RpfFile.GetFile(e, data); + MetaForm f = new MetaForm(); + f.Show(); + f.LoadMeta(ytyp); + } + private void ViewJPso(string name, string path, byte[] data, RpfFileEntry e) + { + var pso = RpfFile.GetFile(e, data); + MetaForm f = new MetaForm(); + f.Show(); + f.LoadMeta(pso); + } + private void ViewModel(string name, string path, byte[] data, RpfFileEntry e) + { + var nl = e?.NameLower ?? ""; + var fe = new FileInfo(nl).Extension; + ModelForm f = new ModelForm(this); + f.Show(); + switch (fe) + { + case ".ydr": + var ydr = RpfFile.GetFile(e, data); + f.LoadModel(ydr); + break; + case ".ydd": + var ydd = RpfFile.GetFile(e, data); + f.LoadModels(ydd); + break; + case ".yft": + var yft = RpfFile.GetFile(e, data); + f.LoadModel(yft); + break; + case ".ybn": + var ybn = RpfFile.GetFile(e, data); + f.LoadModel(ybn); + break; + case ".ypt": + var ypt = RpfFile.GetFile(e, data); + f.LoadParticles(ypt); + break; + case ".ynv": + var ynv = RpfFile.GetFile(e, data); + f.LoadNavmesh(ynv); + break; + } + } + private void ViewCut(string name, string path, byte[] data, RpfFileEntry e) + { + var cut = RpfFile.GetFile(e, data); + MetaForm f = new MetaForm(); + f.Show(); + f.LoadMeta(cut); + } + private void ViewAwc(string name, string path, byte[] data, RpfFileEntry e) + { + var awc = RpfFile.GetFile(e, data); + AwcForm f = new AwcForm(); + f.Show(); + f.LoadAwc(awc); + } + private void ViewGxt(string name, string path, byte[] data, RpfFileEntry e) + { + var gxt = RpfFile.GetFile(e, data); + GxtForm f = new GxtForm(); + f.Show(); + f.LoadGxt2(gxt); + } + private void ViewRel(string name, string path, byte[] data, RpfFileEntry e) + { + var rel = RpfFile.GetFile(e, data); + RelForm f = new RelForm(); + f.Show(); + f.LoadRel(rel); + } + private void ViewFxc(string name, string path, byte[] data, RpfFileEntry e) + { + var fxc = RpfFile.GetFile(e, data); + FxcForm f = new FxcForm(); + f.Show(); + f.LoadFxc(fxc); + } + private void ViewYwr(string name, string path, byte[] data, RpfFileEntry e) + { + var ywr = RpfFile.GetFile(e, data); + YwrForm f = new YwrForm(); + f.Show(); + f.LoadYwr(ywr); + } + private void ViewYvr(string name, string path, byte[] data, RpfFileEntry e) + { + var yvr = RpfFile.GetFile(e, data); + YvrForm f = new YvrForm(); + f.Show(); + f.LoadYvr(yvr); + } + + + + private void ShowTreeContextMenu(TreeNode n, Point p) + { + var f = n?.Tag as MainTreeFolder; + + bool filesys = ((f.RpfFolder == null) && (f.RpfFile == null)); + bool expanded = ((n != null) && (n.IsExpanded)); + bool collapsed = ((n != null) && (!n.IsExpanded)); + + if ((f.RpfFile != null) && (f.RpfFile.Parent == null)) + { + filesys = true; //allow viewing root RPF's in explorer + } + + TreeContextWinExplorerMenu.Enabled = filesys; + TreeContextExpandMenu.Enabled = collapsed; + TreeContextCollapseMenu.Enabled = expanded; + + + TreeContextMenu.Show(MainTreeView, p); + + } + + private void ShowListContextMenu(MainListItem item) + { + + bool isitem = false; + bool isfile = false; + bool isfolder = false; + bool isfilesys = false; + bool canview = false; + bool canexportxml = false; + bool editmode = false;//todo: set this for edit mode + bool canimport = editmode; + bool canedit = false; + bool issearch = CurrentFolder?.IsSearchResults ?? false; + + if (item != null) + { + isfolder = (item.Folder != null); + isfilesys = (item.File == null) && (item.Folder == null); + canview = CanViewFile(item); + isitem = true; + isfile = !isfolder; + canedit = editmode && !canimport; + } + + + ListContextViewMenu.Enabled = canview; + ListContextViewHexMenu.Enabled = isfile; + + ListContextExportXmlMenu.Enabled = canexportxml; + ListContextExtractRawMenu.Enabled = isfile; + + ListContextImportRawMenu.Visible = canimport; + ListContextImportXmlMenu.Visible = canimport; + ListContextImportSeparator.Visible = canimport; + + ListContextCopyMenu.Enabled = isfile; + ListContextCopyPathMenu.Enabled = isitem; + + ListContextOpenFileLocationMenu.Visible = issearch; + ListContextOpenFileLocationSeparator.Visible = issearch; + + ListContextRenameMenu.Visible = canedit; + ListContextReplaceMenu.Visible = canedit; + ListContextDeleteMenu.Visible = canedit; + ListContextEditSeparator.Visible = canedit; + + ListContextMenu.Show(Cursor.Position); + + } + + + + private void ViewSelected() + { + for (int i = 0; i < MainListView.SelectedIndices.Count; i++) + { + var idx = MainListView.SelectedIndices[i]; + if ((idx < 0) || (idx >= CurrentFiles.Count)) continue; + var file = CurrentFiles[idx]; + if (file.Folder == null) + { + View(file); + } + } + } + private void ViewSelectedHex() + { + for (int i = 0; i < MainListView.SelectedIndices.Count; i++) + { + var idx = MainListView.SelectedIndices[i]; + if ((idx < 0) || (idx >= CurrentFiles.Count)) continue; + var file = CurrentFiles[idx]; + if (file.Folder == null) + { + ViewHex(file); + } + } + } + private void ExportXml() + { + MessageBox.Show("Export XML TODO!"); + for (int i = 0; i < MainListView.SelectedIndices.Count; i++) + { + var idx = MainListView.SelectedIndices[i]; + if ((idx < 0) || (idx >= CurrentFiles.Count)) continue; + var file = CurrentFiles[idx]; + if (file.Folder == null) + { + //todo: meta convert to XML and export... + } + } + } + private void ExtractRaw() + { + if (MainListView.SelectedIndices.Count == 1) + { + var idx = MainListView.SelectedIndices[0]; + if ((idx < 0) || (idx >= CurrentFiles.Count)) return; + var file = CurrentFiles[idx]; + if (file.Folder == null) + { + byte[] data = GetFileData(file); + if (data == null) + { + MessageBox.Show("Unable to extract file: " + file.Path); + return; + } + + SaveFileDialog.FileName = file.Name; + if (SaveFileDialog.ShowDialog() == DialogResult.OK) + { + string path = SaveFileDialog.FileName; + try + { + File.WriteAllBytes(path, data); + } + catch (Exception ex) + { + MessageBox.Show("Error saving file " + path + ":\n" + ex.ToString()); + } + } + } + } + else + { + if (FolderBrowserDialog.ShowDialog() != DialogResult.OK) return; + string folderpath = FolderBrowserDialog.SelectedPath; + if (!folderpath.EndsWith("\\")) folderpath += "\\"; + + StringBuilder errors = new StringBuilder(); + + for (int i = 0; i < MainListView.SelectedIndices.Count; i++) + { + var idx = MainListView.SelectedIndices[i]; + if ((idx < 0) || (idx >= CurrentFiles.Count)) continue; + var file = CurrentFiles[idx]; + if (file.Folder == null) + { + var path = folderpath + file.Name; + var data = GetFileData(file); + if (data == null) + { + errors.AppendLine("Unable to extract file: " + file.Path); + continue; + } + try + { + File.WriteAllBytes(path, data); + } + catch (Exception ex) + { + errors.AppendLine("Error saving file " + path + ":\n" + ex.ToString()); + } + } + } + + string errstr = errors.ToString(); + if (!string.IsNullOrEmpty(errstr)) + { + MessageBox.Show("Errors were encountered:\n" + errstr); + } + } + } + private void ExtractAll() + { + if (CurrentFiles == null) return; + if (FolderBrowserDialog.ShowDialog() != DialogResult.OK) return; + string folderpath = FolderBrowserDialog.SelectedPath; + if (!folderpath.EndsWith("\\")) folderpath += "\\"; + + StringBuilder errors = new StringBuilder(); + + foreach (var file in CurrentFiles) + { + if (file.Folder == null) + { + var path = folderpath + file.Name; + var data = GetFileData(file); + if (data == null) + { + errors.AppendLine("Unable to extract file: " + file.Path); + continue; + } + try + { + File.WriteAllBytes(path, data); + } + catch (Exception ex) + { + errors.AppendLine("Error saving file " + path + ":\n" + ex.ToString()); + } + } + } + + string errstr = errors.ToString(); + if (!string.IsNullOrEmpty(errstr)) + { + MessageBox.Show("Errors were encountered:\n" + errstr); + } + } + private void ImportXml() + { + if (!EditMode) return; + MessageBox.Show("Edit mode functions not yet implemented..."); + } + private void ImportRaw() + { + if (!EditMode) return; + MessageBox.Show("Edit mode functions not yet implemented..."); + } + private void CopySelected() + { + //only really for edit mode... + MessageBox.Show("CopySelected TODO!"); + } + private void CopyPath() + { + if (MainListView.SelectedIndices.Count == 0) + { + Clipboard.SetText(CurrentFolder?.FullPath ?? GetRootPath()); + } + else if (MainListView.SelectedIndices.Count == 1) + { + var idx = MainListView.SelectedIndices[0]; + if ((idx < 0) || (idx >= CurrentFiles.Count)) return; + var f = CurrentFiles[idx]; + if (f.FullPath != null) + { + Clipboard.SetText(f.FullPath); + } + } + else + { + StringBuilder sb = new StringBuilder(); + foreach (int idx in MainListView.SelectedIndices) + { + if ((idx < 0) || (idx >= CurrentFiles.Count)) return; + var f = CurrentFiles[idx]; + if (f.FullPath != null) + { + sb.AppendLine(f.FullPath); + } + } + Clipboard.SetText(sb.ToString()); + } + } + private void CopyPath(string path) + { + Clipboard.SetText(path); + } + private void CopyFileList() + { + StringBuilder sb = new StringBuilder(); + if (CurrentFiles != null) + { + foreach (var file in CurrentFiles) + { + sb.AppendLine(file.Name); + } + } + Clipboard.SetText(sb.ToString()); + } + private void RenameSelected() + { + if (!EditMode) return; + if (MainListView.SelectedItems.Count != 1) return; + MessageBox.Show("Edit mode functions not yet implemented..."); + } + private void ReplaceSelected() + { + if (!EditMode) return; + if (MainListView.SelectedItems.Count != 1) return; + MessageBox.Show("Edit mode functions not yet implemented..."); + } + private void DeleteSelected() + { + if (!EditMode) return; + MessageBox.Show("Edit mode functions not yet implemented..."); + } + private void SelectAll() + { + MainListView.SelectAllItems(); + UpdateSelectionUI(); + } + private void ShowInExplorer(string path) + { + try + { + Process.Start("explorer", "/select, \"" + path + "\""); + } + catch (Exception ex) + { + UpdateErrorLog(ex.ToString()); + } + } + private void OpenFileLocation() + { + var ind = -1; + if (MainListView.SelectedIndices.Count == 1) + { + ind = MainListView.SelectedIndices[0]; + } + if ((CurrentFiles != null) && (CurrentFiles.Count > ind)) + { + var file = CurrentFiles[ind]; + var path = file.Path.Replace('/', '\\'); + var bsind = path.LastIndexOf('\\'); + if (bsind > 0) + { + path = path.Substring(0, bsind); + } + Navigate(path); + } + } + + + private void SetView(View v) + { + + MainListView.View = v; + + foreach (ToolStripMenuItem menu in ViewMenu.DropDownItems) + { + menu.Checked = false; + } + + switch (v) + { + case System.Windows.Forms.View.LargeIcon: + ViewLargeIconsMenu.Checked = true; + break; + case System.Windows.Forms.View.SmallIcon: + ViewSmallIconsMenu.Checked = true; + break; + case System.Windows.Forms.View.List: + ViewListMenu.Checked = true; + break; + case System.Windows.Forms.View.Details: + ViewDetailsMenu.Checked = true; + break; + } + + } + + + private void ExploreForm_Load(object sender, EventArgs e) + { + Init(); + } + + private void MainTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + var prev = CurrentFolder; + CurrentFolder = e.Node?.Tag as MainTreeFolder; + LocationTextBox.Text = CurrentFolder?.Path ?? ""; + if (!string.IsNullOrEmpty(CurrentFolder?.SearchTerm)) + { + SearchTextBox.Text = CurrentFolder.SearchTerm; + } + RefreshMainListView(); + NavigateComplete(prev); + } + + private void MainTreeView_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + + // Point where the mouse is clicked. + Point p = new Point(e.X, e.Y); + + // Get the node that the user has clicked. + TreeNode node = MainTreeView.GetNodeAt(p); + if (node != null) + { + + // Select the node the user has clicked. + // The node appears selected until the menu is displayed on the screen. + //var oldNode = MainTreeView.SelectedNode; + MainTreeView.SelectedNode = node; + + ShowTreeContextMenu(node, p); + + // Highlight the selected node. + //MainTreeView.SelectedNode = oldNode; + } + } + } + + private void MainListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) + { + var lvi = new ListViewItem(); + if ((CurrentFiles != null) && (e.ItemIndex < CurrentFiles.Count)) + { + var file = CurrentFiles[e.ItemIndex]; + var fld = file.Folder; + lvi.Tag = file; + lvi.Text = file.Name; + lvi.ToolTipText = file.Path; + lvi.ImageIndex = file.ImageIndex; + lvi.SubItems.Add(file.FileTypeText); //type column + lvi.SubItems.Add(file.FileSizeText); //size column + lvi.SubItems.Add(file.Attributes); //attributes column + lvi.SubItems.Add(file.Path); //path column + } + e.Item = lvi; + } + + private void MainListView_ColumnClick(object sender, ColumnClickEventArgs e) + { + var newdir = SortDirection; + var idx = e.Column; + if (idx == SortColumnIndex) + { + switch (SortDirection) + { + case SortOrder.None: newdir = SortOrder.Ascending; break; + case SortOrder.Ascending: newdir = SortOrder.Descending; break; + case SortOrder.Descending: newdir = SortOrder.Ascending; break; + } + } + + SortMainListView(idx, newdir); + } + + private void MainListView_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + MainListItem item = null; + if ((MainListView.FocusedItem != null) && (MainListView.FocusedItem.Bounds.Contains(e.Location))) + { + item = MainListView.FocusedItem.Tag as MainListItem; + } + ShowListContextMenu(item); + } + + UpdateSelectionUI(); //need to use this instead of SelectedIndexChanged because of shift-click bug :/ + } + + private void MainListView_KeyDown(object sender, KeyEventArgs e) + { + var ctrl = (e.Control && !e.Shift); + var ctrlshft = (e.Control && e.Shift); + var shft = (e.Shift && !e.Control); + + switch (e.KeyCode) + { + case Keys.P: + if (ctrl) ViewSelected(); + break; + case Keys.H: + if (ctrl) ViewSelectedHex(); + break; + case Keys.S: + if (ctrl) ExportXml(); + break; + case Keys.E: + if (ctrlshft) ExtractAll(); + else if (ctrl) ExtractRaw(); + break; + case Keys.Insert: + if (MainListView.SelectedIndices.Count == 1) + { + if (shft) ReplaceSelected(); + } + else + { + if (shft) ImportXml(); + else if (!ctrl) ImportRaw(); + } + break; + case Keys.C: + if (ctrlshft) CopyPath(); + else if (ctrl) CopySelected(); + break; + case Keys.F2: + RenameSelected(); + break; + case Keys.Delete: + if (shft) DeleteSelected(); + break; + case Keys.A: + if (ctrl) SelectAll(); + break; + } + } + + private void MainListView_KeyUp(object sender, KeyEventArgs e) + { + UpdateSelectionUI(); //need to use this instead of SelectedIndexChanged because of shift-click bug :/ + } + + private void MainListView_ItemActivate(object sender, EventArgs e) + { + if (MainListView.SelectedIndices.Count == 1) + { + var idx = MainListView.SelectedIndices[0]; + if ((idx >= 0) && (idx < CurrentFiles.Count)) + { + var file = CurrentFiles[idx]; + if (file.Folder != null) + { + Navigate(file.Folder); + } + else + { + //a file was activated. open it... (or, perform "default action"?) + View(file); + } + } + } + else + { + //how to activate multiple items? open files? + } + } + + private void BackButton_ButtonClick(object sender, EventArgs e) + { + GoBack(); + } + + private void BackListButton_Click(object sender, EventArgs e) + { + var step = (sender as ToolStripItem)?.Tag as MainTreeFolder; + if (step == null) return; + GoBack(step); + } + + private void ForwardButton_ButtonClick(object sender, EventArgs e) + { + GoForward(); + } + + private void ForwardListButton_Click(object sender, EventArgs e) + { + var step = (sender as ToolStripItem)?.Tag as MainTreeFolder; + if (step == null) return; + GoForward(step); + } + + private void UpButton_ButtonClick(object sender, EventArgs e) + { + GoUp(); + } + + private void UpListButton_Click(object sender, EventArgs e) + { + var step = (sender as ToolStripItem)?.Tag as MainTreeFolder; + if (step == null) return; + GoUp(step); + } + + private void LocationTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == 13) + { + Navigate(LocationTextBox.Text); + e.Handled = true; + } + } + + private void LocationTextBox_Enter(object sender, EventArgs e) + { + BeginInvoke(new Action(() => LocationTextBox.SelectAll())); + } + + private void GoButton_Click(object sender, EventArgs e) + { + Navigate(LocationTextBox.Text); + } + + private void RefreshButton_Click(object sender, EventArgs e) + { + Task.Run(() => + { + UpdateStatus("Scanning..."); + + RefreshMainTreeView(); + + UpdateStatus("Scan complete."); + }); + } + + private void SearchTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == 13) + { + SearchButton_ButtonClick(sender, e); + e.Handled = true; + } + } + + private void SearchTextBox_Enter(object sender, EventArgs e) + { + BeginInvoke(new Action(() => SearchTextBox.SelectAll())); + } + + private void SearchButton_ButtonClick(object sender, EventArgs e) + { + if (SearchGlobalButton.Checked) + { + Search(SearchTextBox.Text); + } + else + { + Filter(SearchTextBox.Text); + } + } + + private void SearchGlobalButton_Click(object sender, EventArgs e) + { + Search(SearchTextBox.Text); + } + + private void SearchFilterButton_Click(object sender, EventArgs e) + { + Filter(SearchTextBox.Text); + } + + private void TreeContextCopyPathMenu_Click(object sender, EventArgs e) + { + var f = MainTreeView.SelectedNode?.Tag as MainTreeFolder; + if (f != null) + { + CopyPath(f.FullPath); + } + } + + private void TreeContextWinExplorerMenu_Click(object sender, EventArgs e) + { + var folder = MainTreeView.SelectedNode?.Tag as MainTreeFolder; + var path = folder?.FullPath ?? GetRootPath(); + ShowInExplorer(path); + } + + private void TreeContextExpandMenu_Click(object sender, EventArgs e) + { + if (MainTreeView.SelectedNode != null) + { + MainTreeView.SelectedNode.Expand(); + } + } + + private void TreeContextCollapseMenu_Click(object sender, EventArgs e) + { + if (MainTreeView.SelectedNode != null) + { + MainTreeView.SelectedNode.Collapse(); + } + } + + private void TreeContextCollapseAllMenu_Click(object sender, EventArgs e) + { + var seln = MainTreeView.SelectedNode; + foreach (TreeNode root in MainTreeView.Nodes) + { + foreach (TreeNode n in root.Nodes) + { + n.Collapse(false); //collapse the first level nodes (not the roots) + } + } + if (MainTreeView.SelectedNode != seln) + { + TreeViewEventArgs tve = new TreeViewEventArgs(MainTreeView.SelectedNode); + MainTreeView_AfterSelect(MainTreeView, tve); //for some reason, this event doesn't get raised when the selected node changes here + } + } + + private void ListContextViewMenu_Click(object sender, EventArgs e) + { + ViewSelected(); + } + + private void ListContextViewHexMenu_Click(object sender, EventArgs e) + { + ViewSelectedHex(); + } + + private void ListContextExportXmlMenu_Click(object sender, EventArgs e) + { + ExportXml(); + } + + private void ListContextExtractRawMenu_Click(object sender, EventArgs e) + { + ExtractRaw(); + } + + private void ListContextExtractAllMenu_Click(object sender, EventArgs e) + { + ExtractAll(); + } + + private void ListContextImportXmlMenu_Click(object sender, EventArgs e) + { + ImportXml(); + } + + private void ListContextImportRawMenu_Click(object sender, EventArgs e) + { + ImportRaw(); + } + + private void ListContextCopyMenu_Click(object sender, EventArgs e) + { + CopySelected(); + } + + private void ListContextCopyPathMenu_Click(object sender, EventArgs e) + { + CopyPath(); + } + + private void ListContextCopyFileListMenu_Click(object sender, EventArgs e) + { + CopyFileList(); + } + + private void ListContextOpenFileLocationMenu_Click(object sender, EventArgs e) + { + OpenFileLocation(); + } + + private void ListContextRenameMenu_Click(object sender, EventArgs e) + { + RenameSelected(); + } + + private void ListContextReplaceMenu_Click(object sender, EventArgs e) + { + ReplaceSelected(); + } + + private void ListContextDeleteMenu_Click(object sender, EventArgs e) + { + DeleteSelected(); + } + + private void ListContextSelectAllMenu_Click(object sender, EventArgs e) + { + SelectAll(); + } + + private void FileExitMenu_Click(object sender, EventArgs e) + { + Close(); + } + + private void EditViewMenu_Click(object sender, EventArgs e) + { + ViewSelected(); + } + + private void EditViewHexMenu_Click(object sender, EventArgs e) + { + ViewSelectedHex(); + } + + private void EditExportXmlMenu_Click(object sender, EventArgs e) + { + ExportXml(); + } + + private void EditExtractRawMenu_Click(object sender, EventArgs e) + { + ExtractRaw(); + } + + private void EditExtractAllMenu_Click(object sender, EventArgs e) + { + ExtractAll(); + } + + private void EditImportXmlMenu_Click(object sender, EventArgs e) + { + ImportXml(); + } + + private void EditImportRawMenu_Click(object sender, EventArgs e) + { + ImportRaw(); + } + + private void EditCopyMenu_Click(object sender, EventArgs e) + { + CopySelected(); + } + + private void EditCopyPathMenu_Click(object sender, EventArgs e) + { + CopyPath(); + } + + private void EditCopyFileListMenu_Click(object sender, EventArgs e) + { + CopyFileList(); + } + + private void EditRenameMenu_Click(object sender, EventArgs e) + { + RenameSelected(); + } + + private void EditReplaceMenu_Click(object sender, EventArgs e) + { + ReplaceSelected(); + } + + private void EditDeleteMenu_Click(object sender, EventArgs e) + { + DeleteSelected(); + } + + private void EditSelectAllMenu_Click(object sender, EventArgs e) + { + SelectAll(); + } + + private void ViewLargeIconsMenu_Click(object sender, EventArgs e) + { + SetView(System.Windows.Forms.View.LargeIcon); + } + + private void ViewSmallIconsMenu_Click(object sender, EventArgs e) + { + SetView(System.Windows.Forms.View.SmallIcon); + } + + private void ViewListMenu_Click(object sender, EventArgs e) + { + SetView(System.Windows.Forms.View.List); + } + + private void ViewDetailsMenu_Click(object sender, EventArgs e) + { + SetView(System.Windows.Forms.View.Details); + } + + private void ToolsOptionsMenu_Click(object sender, EventArgs e) + { + MessageBox.Show("Options TODO!"); + } + + private void ToolsRpfBrowserMenu_Click(object sender, EventArgs e) + { + BrowseForm f = new BrowseForm(); + f.Show(this); + } + } + + + + public class MainTreeFolder + { + public string Name { get; set; } + public string Path { get; set; } + public string FullPath { get; set; } + public RpfFile RpfFile { get; set; } + public RpfDirectoryEntry RpfFolder { get; set; } + public List Files { get; set; } + public MainTreeFolder Parent { get; set; } + public List Children { get; set; } + public List ListItems { get; set; } + public bool IsSearchResults { get; set; } + public string SearchTerm { get; set; } + + public void AddFile(string file) + { + if (Files == null) Files = new List(); + Files.Add(file); + } + public void AddChild(MainTreeFolder child) + { + if (Children == null) Children = new List(); + Children.Add(child); + child.Parent = this; + } + public void AddChildToHierarchy(MainTreeFolder child) + { + var relpath = child.Path.Replace(Path + "\\", ""); + var idx = relpath.IndexOf('\\'); + var lidx = 0; + var parent = this; + while (idx > 0) + { + var pname = relpath.Substring(lidx, idx - lidx); + if (parent.Children == null) break; + foreach (var tc in parent.Children) + { + if (tc.Name == pname) + { + parent = tc; + break; + } + } + lidx = idx + 1; + if (lidx >= relpath.Length) break; + idx = relpath.IndexOf('\\', lidx); + } + parent.AddChild(child); + } + + public List GetListItems() + { + if (ListItems == null) + { + ListItems = new List(); + var rootpath = ExploreForm.GetRootPath(); + + if (Children != null) + { + foreach (var child in Children) + { + ListItems.Add(new MainListItem(child)); + } + } + if (Files != null) + { + foreach (var file in Files) + { + ListItems.Add(new MainListItem(file, rootpath, this)); + } + } + if ((RpfFolder != null) && (RpfFolder.Files != null)) + { + foreach (var file in RpfFolder.Files) + { + if (file.NameLower.EndsWith(".rpf")) continue; //RPF files are already added.. + ListItems.Add(new MainListItem(file, rootpath, this)); + } + } + } + return ListItems; + } + public int GetItemCount() + { + int ic = 0; + if (Children != null) ic += Children.Count; + if (Files != null) ic += Files.Count; + if ((RpfFolder != null) && (RpfFolder.Files != null)) + { + foreach (var file in RpfFolder.Files) + { + if (file.NameLower.EndsWith(".rpf")) continue; //RPF files are already added.. + ic++; + } + } + return ic; + } + + public string GetToolText() + { + if (string.IsNullOrEmpty(Path)) return Name; + return Path; + } + + public int Search(string term, ExploreForm form) + { + int resultcount = 0; + //if (!form.Searching) return resultcount; + + form.UpdateStatus("Searching " + Path + "..."); + + if (Name.ToLowerInvariant().Contains(term)) + { + form.AddSearchResult(new MainListItem(this)); + resultcount++; + } + + var rootpath = ExploreForm.GetRootPath(); + + if (Files != null) + { + foreach (var file in Files) + { + //if (!form.Searching) return resultcount; + var fi = new FileInfo(file); + if (fi.Name.ToLowerInvariant().Contains(term)) + { + form.AddSearchResult(new MainListItem(file, rootpath, this)); + resultcount++; + } + } + } + if ((RpfFolder != null) && (RpfFolder.Files != null)) + { + foreach (var file in RpfFolder.Files) + { + //if (!form.Searching) return resultcount; + if (file.NameLower.EndsWith(".rpf")) continue; //don't search rpf files.. + if (file.NameLower.Contains(term)) + { + form.AddSearchResult(new MainListItem(file, rootpath, this)); + resultcount++; + } + } + } + + if (Children != null) + { + foreach (var child in Children) + { + //if (!form.Searching) return resultcount; + resultcount += child.Search(term, form); + } + } + + form.AddSearchResult(null); + + return resultcount; + } + + public override string ToString() + { + return Name; + } + } + + public class MainListItem + { + public string Name { get; set; } + public MainTreeFolder Parent { get; set; } + public MainTreeFolder Folder { get; set; } + public RpfFileEntry File { get; set; } + public string Path { get; set; } + public string FullPath { get; set; } + + public FileTypeInfo FileType { get; set; } + public string FileTypeText { get; set; } + public long FileSize { get; set; } + public string FileSizeText { get; set; } + public string Attributes { get; set; } + public int ImageIndex { get; set; } + + + public MainListItem(MainTreeFolder f) + { + Parent = f?.Parent; + Folder = f; + Name = f.Name; + Path = f.Path; + FullPath = f.FullPath; + } + public MainListItem(string file, string rootpath, MainTreeFolder parent) + { + Parent = parent; + Name = new FileInfo(file).Name; + Path = file.Replace(rootpath, ""); + FullPath = file; + } + public MainListItem(RpfFileEntry file, string rootpath, MainTreeFolder parent) + { + Parent = parent; + File = file; + Name = file.Name; + Path = file.Path; + FullPath = rootpath + file.Path; + } + + public override string ToString() + { + return Name; + } + + public void CacheDetails(ExploreForm form) + { + var fld = Folder; + FileType = form.GetFileType(Name); + FileTypeText = FileType.Name; + FileSizeText = ""; + Attributes = ""; + ImageIndex = FileType.ImageIndex; + if (File != null) + { + FileSize = File.GetFileSize(); + FileSizeText = TextUtil.GetBytesReadable(FileSize); + if (File is RpfResourceFileEntry) + { + var resf = File as RpfResourceFileEntry; + Attributes += "Resource [V." + resf.Version.ToString() + "]"; + } + if (File.IsEncrypted) + { + if (Attributes.Length > 0) Attributes += ", "; + Attributes += "Encrypted"; + } + } + else if (fld != null) + { + if (fld.RpfFile != null) + { + FileSize = fld.RpfFile.FileSize; + FileSizeText = TextUtil.GetBytesReadable(FileSize); + } + else + { + FileTypeText = "Folder"; + ImageIndex = 1; //FOLDER imageIndex + var ic = fld.GetItemCount(); + FileSize = ic; + FileSizeText = ic.ToString() + " item" + ((ic != 1) ? "s" : ""); + } + } + else + { + var fi = new FileInfo(FullPath); + if (fi.Exists) + { + FileSize = fi.Length; + FileSizeText = TextUtil.GetBytesReadable(fi.Length); + } + } + + } + + public int SortCompare(MainListItem i, int col, SortOrder dir) + { + var desc = (dir == SortOrder.Descending); + if (Folder != null) + { + if (i.Folder == null) return desc ? 1 : -1; + } + else if (i.Folder != null) + { + return desc ? -1 : 1; + } + + var i1 = this; + var i2 = i; + if (desc) + { + i1 = i; + i2 = this; + } + + switch (col) + { + default: + case 0: //Name column + return i1.Name.CompareTo(i2.Name); + case 1: //Type column + var ftc = i1.FileTypeText.CompareTo(i2.FileTypeText); + if (ftc == 0) return i1.Name.CompareTo(i2.Name); //same type, sort by name... + return ftc; + case 2: //Size column + return i1.FileSize.CompareTo(i2.FileSize); + case 3: //Attributes column + var ac = i1.Attributes.CompareTo(i2.Attributes); + if (ac == 0) return i1.Name.CompareTo(i2.Name); //same attributes, sort by name... + return ac; + case 4: //path column + return i1.Path.CompareTo(i2.Path); + } + + //return i1.Name.CompareTo(i2.Name); + } + + } + + + public class FileTypeInfo + { + public string Name { get; set; } + public string Extension { get; set; } + public int ImageIndex { get; set; } + public FileTypeAction DefaultAction { get; set; } + + public FileTypeInfo(string extension, string name, int imageindex, FileTypeAction defaultAction) + { + Name = name; + Extension = extension; + ImageIndex = imageindex; + DefaultAction = defaultAction; + } + } + + public enum FileTypeAction + { + ViewHex = 0, + ViewText = 1, + ViewXml = 2, + ViewYtd = 3, + ViewYmt = 4, + ViewYmf = 5, + ViewYmap = 6, + ViewYtyp = 7, + ViewJPso = 8, + ViewModel = 9, + ViewCut = 10, + ViewAwc = 11, + ViewGxt = 12, + ViewRel = 13, + ViewFxc = 14, + ViewYwr = 15, + ViewYvr = 16, + } + +} diff --git a/ExploreForm.resx b/ExploreForm.resx new file mode 100644 index 0000000..2bcc009 --- /dev/null +++ b/ExploreForm.resx @@ -0,0 +1,855 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAQFJREFUOE+dkz0LglAUhv0H/ZLA3+De1FrQ4NJkY9Du3FRLEAZuRVNQS2FLRDQE + UWu0BBX4Mbie7nvxmslNrQMPXI/nfTgXUUlXGIaUgctQo1F5YVDTNCmmaeZLsgQgV5IUeK7/QSFJEUFS + EsXelSUQiPeYjWLvQtMwDNJ1XRoGXwWsMTxfH9Sxt5zT5U6+FxQTsIfGYn+hUt2itrWhZt9h5xGXFBVM + K+acerNDPAgJNklv8U2wgsBenuJBbAJB4OcI2EFluBCUW2MuwSa4jrM7xoE0XCDCte6SlOqAIBFM1kf+ + NWRhIAQu1kQYEjR/AYLG7enxu7Jz/t8mK0j+CyvKC4EcOC+MIvJ7AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAGlJREFUOE/ljlsKgEAIRV1Sa3BxbncKxN9CUKbCdIboqwsHxMdB8IjIntCYebHV + OLqIiCFEVEsygVJKzoK1bReGJHdBVCsusbOe7APH57prZz1PH0S9IUHElMDrqPeHDyq+E8xgZ28DcADi + +uZiNACH5wAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAKZJREFUOE/Nk0sOwyAMRDlSz8CFOEQqtsldOBitYrFNNa1NXMQnCxaxNIplzzxE + ophplVI6OopE9GBrvWC01lblvR9DegBoCNGAV3z/6RLkCkBDOHZWDyCSPbwcO+segBDCd1lqCMBbFfO2 + btmIHjPaqQ3gcJTFsjzziegxww6QKkDC/HmySZuxQ48ryozjEwDlFZxzOYxeoHhqcfxXAilNSo1/wJgP + rxwb6AQLOW8AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAKtJREFUOE/NkNENwjAMRDMSM2QFfpkn3wzQLfLflQqiyq/JmVzkthZFIKRaOtU6 + 3z0pDSLyk0Ip5RTq1K9YNU9vb6eGJgS1dB5U2OmtpNlWfY05rAHqxRi7UkpbCEKX66glC6BnAS6ERRQI + 4I7bbbp3uRAstmwh82N2ARYCAH7WAoK9eouyFSHI8BkdAuWcNeCVoQ0AQwhMBrwy5AIwDfI9AHMswJ7+ + B/hcRZ4ta4FRmq6ouAAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAJVJREFUOE+1kNEJwzAMRDNSZvBCHsLFv8068VJpf/yr+oSckuQCVUMMD8Tp/MAe + ROQSNPRAQw809PAd7NRax8bSkB3IRqtxAQpWlOk5SZmLghmZ7VRyEGCBQs5Zyyk95LW8FczIbKcSJtDL + XRBC2NAFXXKLYPOEGON6GXMXoIPuQbD/xBPOP/FfaOiBhh5o6IGGvyPDB6ug8Uv1Fi1pAAAAAElFTkSu + QmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAJ5JREFUOE/VkcEJwzAMRTNSZ/AKuWYenztAIZtkJbcp+OrkK5L5qIbEhxwqeBjZ + +s9gD1w55xlo21caLkqfxMLTcxFI5Ek7D40dtW/U8DC+BJPEGEsIoYL+R+LDXsKCpgRDFuAwVpy906fS + lGDIbjMB77UELBGBwQKDBV4kGR2Uh2SB3nBJIH+OhsHAun7PBb4sDFph8EeCM+4TXCeXDdS/V/ydKVLV + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB + DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7 + k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAFBJREFUOE9joBh8+/btPz4MVYYbgBQ5OTmBMUwTMh+qDDegigHYNBKL4S6A0chs + YmjauYAQhqkbTi5A1ojMJ0QTNIAQRvECNgxNb4MWMDAAAPsOTf9dAGOQAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAJ5JREFUOE/VkcEJwzAMRTNSZ/AKuWYenztAIZtkJbcp+OrkK5L5qIbEhxwqeBjZ + +s9gD1w55xlo21caLkqfxMLTcxFI5Ek7D40dtW/U8DC+BJPEGEsIoYL+R+LDXsKCpgRDFuAwVpy906fS + lGDIbjMB77UELBGBwQKDBV4kGR2Uh2SB3nBJIH+OhsHAun7PBb4sDFph8EeCM+4TXCeXDdS/V/ydKVLV + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAVdJREFUOE+lk7FKw1AUhn0BwQdwcHJwEpzcsjkJmZ06+AABfYDqA1h3h+AiHQrS + xUkoOjiIEFwERSgOtoqDdcl6/b+bc9OmJHbwhx+Sc/7z33NyT5acc/9iiTzP18S2mIgrFq6AuJiKA2Mr + JKKfz7F7PDv11PtQrJjoPZ58jL4fTo7d2+01mqzU6CGl8Hx92fPu6ADBpeU4tTPK7l0v2nD93W2HkWKb + vhjMG0A7hZGGT93UXWytemKkWGylBRTwI+AeDBATo5s508TKqlCiVWcSnulCmtTk9agzgTeH+xRPP1oT + FhgMTFYPCTpfr8+LRmicP+XrzhZgRDfcezCzG5heH2gqtruOxYzTibMHk/F7dcm4mlAIMeJkiSLyiMUU + HbmrvR1yfsk8Qouh2NosdnwGiiXk6IKaUhOc/yoOUC5iNEZ86XeLdaZA5AW2TdsIafhr2Qkdlme/FMP+ + sdnP7QgAAAAASUVORK5CYII= + + + + 132, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADNSURBVDhPtZPBDYMwEARdSmpxJamDAvhTQ3iHEvL2i1JM + Hoan43EOCR8osYKy0kro9nZlnw+jsSzLNYTwmOc5bkkNTdr2SOIlNY7Oudg0TbTWFqSGRg+9YntDzL5t + 251Rs+s6QnwRQirCkeGIEjJmM/fiaLppuA9x8s9MvrWOB69hOPrO38wQD16OXwg15pV4i4Ct+RP/F6BD + +ltfaJo54PQQTz8jSEcZa7ZwZbFIgLVMBV+zjYerDCTkt59pC+7FcFJjnvJKamjSJjDmBbRcUoRy09fK + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADISURBVDhPrZPBDcMgEAQpJbVQSeqgAP/dSFxC3rxcCskD + eBKGnCWDkW3FWWml6G53xZ0vqkWM8e69f4YQ0prU6Ilsi9y8ZeFsrU3GmKS1rkiNHhq0YvtCzG4Yho2x + 5TiOhLgqhFQaPUOPEjIXM3PxtFY0Pab0cu9Cfrd9PHgVy+nNDPdC8ODl+VWj5V4I3ipgEe5xHfL/gB4P + R7i8xMufEeSnzGeucGF1SICzzAV35hq7pwwk5Lc/0xrMxXKysGx5ITV6IhMo9QHkNlKlha2WkwAAAABJ + RU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB/SURBVDhPtZFRCsAgDEM9m4fzGjtl/d2INBBm3SxsgUBX + kzfQ8qvM7ID9MycUe+8nnIaw3FobTkG0XGsd3oZE5RRkVaYJ8fgsHGo4mrcA/JOWCHkFsHwH6JnHZzHI + y1QAd7DHZzHIWQHYEYI5lD5RBIA086gVYFsoqX39tUq5AMi8L6aOTq28AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABOSURBVDhPYxhm4OvXr/O/ffv2HxsGyUGV4QcwQ9ra2v47 + OTmBMYhNW0NAErgwUYaABGGKCGGshlDFAFyYKC+gA5CCgdWMDRPUPFQBAwMAwxIvpmCwEUkAAAAASUVO + RK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAD9SURBVDhPrZM9joQwDIVzhDnKnIGTbEHPHGErenrOQk81 + Df0cgCIFfyXDN/FDiQa0QlpLTyG234vtBPdvNo7jfZ5nv2E9wjAMr2mafi09NZHLslyzLEsAmTXP87Vp + GvZP7/3NqMHOyEACQlVVHxGjBiOpbdu1KIokGRDjZCqQj/3WzsPozi3L8oNTCXEyAqDv+93PykyM7hyb + OEgy37QlAVUSCxs9tKCADeqLDGjzT4Gu676IErtUgaDbuTwDCUhYccAhyS2wicsjWZXIJ9R1vYsbPdjm + ePJI4uQjAWAz8UYNxvNEhJNVrq7ziMzzN2pq/DDMhNNPcE6+bs69AUIIBqGH+5QgAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADVSURBVDhPpVIxDoMwDORJfQN7pI5hz1pmytSJ7/EFhrYZ + MqSVgDXlIhslaoga9aQTsn1nOyFVDsuynNd1HTe6gCPyJDnGJrpN0+T6vnd1Xe9EjDzqJP0GJkAkhIjM + TOSpSXoTrMmTu+7qHvene9m3/7aX1udRh44sMXBWnsZmJmKuQUeWGFiPRaGZKaXMN/hrg3meTygopbyo + 6A7IbIdh2KekmPwLR+amaaI4+Q6OzDiGMcafNWD8EnNmrbVFnaRppBr8bGaETYrNDG4CFpsZMJaZq+oD + NQar60zqQI0AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAANNJREFUOE+lUjEOgzAM5El9A3skRthZy0yZOvE9vpCh7UCGtAtr6otslIgENepJ + J2TfnZ0A1Rm2bWuIC9EFRN2wJQ8y3bXWbpomV9f1TtToQ2frEdgAk1IqCgvR5yHpk5CwyOZxvLnn4+Xe + 9uOfw3XwfejwcSQGCfs2CQtRiwYfR2LgeGIKw8K2bc8H/HUCal4g9H3vTUXvgMN2nud9S4rJr5ALd10X + 1cn/IBfGNYwx/q4B4z+Rimx4XVcLna1ppAb8HBaEQ4rDAhnCLAsLeEhBuKq+87Osda2nLc8AAAAASUVO + RK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAKJJREFUOE/VjLENAjEQBL8ESqEE5NxdfAFU4VYcUocjWnDu4DOnhwdZJyQfFoaI + lVY67e7NJiI/2QxXrEetVVZsAY5938U5NzUbthbgknMW7735iOnYsB0AqBXXlJL5jOnYsDUBqA1uMcbh + mYyuz6aAU/M9hKDP3GR0ffYegNrwXEpRADdZr5+aAlB7UAB3j1V/Anh1j1UD4Fub4YrN8HPL9gAVE1vf + J6IiRgAAAABJRU5ErkJggg== + + + + 253, 17 + + + 353, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADo + HwAAAk1TRnQBSQFMAgEBGAEAAZABAAGQAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + AwABQAMAAXADAAEBAQABCAYAARwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA + AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 + AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA + AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm + AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM + AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA + ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz + AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ + AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM + AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA + AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA + AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ + AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/ + AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA + AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm + ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ + Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz + AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA + AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM + AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM + ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM + Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA + AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM + AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ + AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz + AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm + AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw + AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD//8A/wD/AP8AFwAG9BgA + A/QJAAH/AwAQ9AEAAfQB8AH0Am0B9AHwAfQNAAH/A/QGAAH0AW0B8AH0BgAB/wP0AgAB9AQUAfQEFAH0 + BBQC9AHwARQBbQITAW0BFAHwAfQLAAH/AfQB7AEUAfQGAAH0ARQBEwHvAfQB/wMAAf8B9AHsARQB9AIA + AfQBFAL0ARQB9AEUAvQBFAH0ARQC9AEUA/QBbQGSAvQBkgFtAvQKAAH/AfQB7AIUAfQCAAH/AfQCAAH0 + AxQB7AL0AQAB/wH0AewCFAH0AgAB9AQUAfQEFAH0BBQC9AFtAeoB9AKSAfQBEwFtAfQJAAH/AfQB7AMU + AfQBAAH/A/QBAAH0AxQB7QL0Af8B9AHsAxQB9AIAAfQBFAL0ARQB9AEUAvQBFAH0ARQC9AEUAvQBbQHq + AfQCkgH0ARMBbQH0BgAE9AHsBBQB9AH/AvQBFAP0ARQBEwEHBPQB7AQUAfQCAAH0BBQB9AQUAfQEFAP0 + AW0BkgL0AZIBbQb0AgAB9AgUAvQB8wEUAvQB/wH0AW0B8gL0CBQE9AQUAfQEFAH0BBQC9AHwARQBbQIT + AW0BFAHvAfQCbQH0AfAB9AEAAfQKFAH0AfMG9AEAAfQKFAL0BBQB9AQUAfQEFAH0Af8B9AHwAfQCbQH0 + Ae8BFAFtAhMBbQEUAfAC9AoUAvQCFAH0BAAB9AoUAvQEFAH0BBQB9AQUAfQCAAb0AW0BkgL0AZIBbQP0 + ChQB9AHzA/QEAAH0ChQC9AEUAvQBFAH0BBQB9AEUAvQBFAH0BgAB9AFtAeoB9AKSAfQBEwFtAvQIFAL0 + AfMBFAL0Af8EAAH0CBQE9AEUAvQBFAH0BBQB9AEUAvQBFAH0BgAB9AFtAeoB9AKSAfQBEwFtBfQB7AQU + AfQB/wL0ARQC9AQABPQB7AQUAfQCAAH0BBQB9AEUAvQBFAH0BBQB9AYAAvQBbQGSAvQBkgFtAvQDAAH/ + AfQB7AMUAfQBAAH/A/QIAAH/AfQB7AMUAfQCAAb0BBQG9AYAAfQB8AEUAW0CEwFtARQB8AH0BAAB/wH0 + AewCFAH0AgAB/wH0CgAB/wH0AewCFAH0BwAG9AsAAf8B9AHwAfQCbQH0AfAB9AYAAf8B9AHsARQB9A8A + Af8B9AHsARQB9BoABvQIAAH/A/QQAAH/A/QSABD0CgAC9BQAEfQOFAH0CQAB9AHwAfQFAAv0BAAB9A4U + AvQOFAH0AQAC9AH/BAAB/wHzARMB9AUAAfQJFAH0BAAB9A4UAvQCFAr0AhQB9AEAAvQB8wL0Av8B9AFt + ARQB9AUAAfQJFAH0BAAB9AIUCvQCFAL0AhQE9AUUAfQCFAH0AQAB/wH0AW0B7AH3AfIB9AGSAhQB9AUA + AfQCFAX0AhQD9AIAAfQCFAX0Ae8BkgP0AhQC9AIUBPQBFAP0ARQB9AIUBPQB8AMUAW0DFAH0BQAB9AIU + BfQCFAH0ARQB9AIAAfQCFAGSA/QB7wIUAW0BvAHvAhQC9AIUBPQFFAH0AhQB9AMUAfQBkgYUAfMC9AMA + AfQCFAX0AhQB9AEUBPQDFAFtAbwB7wEUAe8B8QFtBBQC9AIUCvQCFAb0AW0FFAETAewBBwL0AQAB9AIU + BfQCFAH0ARQB9AEUAvQCFAG8AW0CFAHvA/QB9wG8AhQC9AIUAfQB7wMUAe8E9AIUAvQCFAL0Ae8IFAHs + AfQBAAH0AhQF9AIUAfQBFAH0ARQC9AIUAvQBkgHvAfQB7wFtAe8C9AIUAvQCFAH0ARQD9AEUBPQCFAb0 + AW0FFAHsAe8B8wL0AQAB9AkUAfQBFAH0ARQC9AIUBfQBbQEUAW0C9AIUAvQCFAH0ARQD9AEUBPQCFAH0 + AxQB9AHvBhQC9AH/AwAB9AkUAfQBFAH0ARQC9AIUBfQB7wFtAe8C9AIUAvQCFAH0Ae8DFAHvBPQCFAX0 + AeoB7AHvAfIB7wIUAfQFAAv0ARQB9AEUAvQCFAr0AhQC9AIUCvQCFAH0AgAF9AH/AfQB7QEUAfQHAAH0 + CRQB9AEUAvQOFAL0DhQB9AIAAf8B9AH/AwAB/wH0AewB9AcAC/QBFAL0DhQC9A4UAfQJAAH/AvQJAAH0 + CRQh9AoAAvQJAAv0BgAB/wP0FgAB/w/0FQAB9AHzAZIBbQHyAfQB/wUAC/QEAAH0AbwBEwttARQB9AEA + DvQEAAH/AfQBvAFtAewB6gFtAe8B9AH/AwAB9AG8ARMHFAETAbwB9AMAAfQBEwG8C/QBFAH0AQAB9AwU + AfQEAAH0AewBbQHxAQcBbQHyAuwB9AMAAfQBEwYUAbwB9AG8ARMB9AMAAfQBFAP0ARQB9AEUAfQEFAH0 + ARQB9AEAAfQBFAH0ARQG9AEUAfQBFAH0BAAB9AEUAfIB9AEHAW0C9AEUAvQCAAH0BxQD9AEUAfIDAAH0 + ARQBvAH0AbwBFAj0ARQB9AEAAfQDFAb0AxQB9AIAAf8C9AEUAvQBBwHqAvQBFAH0AfAB9AEAC/QBFAH0 + AwAB9AUUCPQBFAH0AQAB9AEUAfQBFAb0ARQB9AEUAfQBAAT0ARQB8gGSAewBkgFtAQcBFAH0ARQB8AH0 + AgAB9AIUBvQBFAH0AwAB9AUUAfQBFAH0AhQD9AEUAfQBAAH0AxQG9AMUAfQBAAH0AesBEwH0ARQBbQEH + AvQB8QFtARQB8QEUAW0B9AIAAfQCFAb0ARQB9AMAAfQFFAj0ARQB9AEAAfQBFAH0ARQG9AEUAfQBFAH0 + AQAB9AHsARIBvAEHAW0B7wL0Ae8BbQEHAbwCFAH0AgAB9AIUBvQBFAH0AwAB9AUUCPQBFAH0AQAB9AMU + BvQDFAH0AQAB9AHvAeoBFAH3AfABkgFtAeoB7QHyAQcB6gIUAfQCAAH0AhQG9AEUAfQDAAH0BRQB9AFt + AfQEFAH0ARQB9AEAAfQBFAH0ARQG9AEUAfQBFAH0AQAB/wHzAW0DFAHvAfEB8gHwAfcB7AFtARQBEwH0 + AgAB9AIUBvQBFAH0AwAB9AUUCPQBFAH0AQAB9AMUBvQDFAH0AgAB9AEHARMBFAFtAQcBbQHsAu0B7AFt + ARQBkgH0AgAB9AEUARMG9AEUBfQOFAH0AQAB9AEUAfQBFAb0ARQB9AEUAfQCAAH/AfQBbQEUAbwB9AHt + AW0C7AFtARIBbQH0Af8CAAH0ARQBEwHyBfQEFAL0BRQB7wi8AfQBAAH0AxQG9AMUAfQDAAH0AbwB7AH0 + Af8B9AG8AZIC7AHvAfQB/wMAAfQBbQsUAvQBEwMUARMK9AEAAfQBFAH0ARQG9AEUAfQBFAH0BAAD9AIA + BfQB/wQAAfQB8wFtCRQBkgL0AQcBEwEUARMBvAH0CgAB9AwUAfQEAAL0DgAM9AH/AQAF9AsADvQBAAH/ + CvQB/wYAAf8G9AH/HAAE9AYAAfQB7AEUAuwFFAHtBfQBAAH/A/QCbQP0Af8FABD0BAAB/wH0AfACbQHw + AfQB/wQAAfQBFALvARQBbQH0AbwB9AHvARQB9AMUAfQB/wH0Am0B7wIUAe8CbQf0DhQB9AMAAvQBkgET + Am0BEwGSAvQDAAH0ARQB9wHzAbwB9AFtARQB7wH3ARQB9AMUA/QBbQYUAW0B9AFtAxQC9AEUDPQBFAH0 + AQAB/wH0AfABbQHsAfICkgHyAewBbQHwAfQB/wEAAfQB7AUUAuwBFAHsAvQCFAP0Ae8BFAGSAvQBkgEU + Ae8B9AHvAxQC9AEUBfQGFAH0ARQB9AEAAfQBkgETAQcC9AKSAvQBBwETAZIB9AEAAf8M9AIUAvQBbQIU + AfQCkgH0AhQBbQL0AhQC9AEUAfQDFAH0ARQE9AEUAfQBFAH0AQAB9AEUAfID9AKSA/QB8gEUAfQFAAH0 + AhQG9AIUAvQBbQIUAfQCkgH0AhQBbQL0AhQC9AEUBfQGFAH0ARQB9AEAAfQBFAT0ApIE9AEUAfQFAAH0 + AhQG9AIUA/QB7wEUAZIC9AGSARQB7wP0AhQC9AEUDPQBFAH0AQAB9AEUA/QB9wLsAfcD9AEUAfQFAAH0 + AhQG9AIUA/QBbQYUAW0D9AIUAvQBFAX0BhQB9AEUAfQBAAH0ARQB9AHxAewB9wL0AfcB7AHxAfQBFAH0 + BQAB9AIUBvQCFAH0Af8B9AJtAe8CFAHvAm0D9AIUAvQBFAH0AxQB9AEUBPQBFAH0ARQB9AEAAfQBFAH3 + AewB8QT0AfEB7AH3ARQB9AUAAfQCFAT0AxQB7AH0AQAB/wP0Am0G9AIUAvQBFAX0BhQB9AEUAfQBAAH0 + ARQBkgj0AZIBFAH0BQAB9AIUBPQCFAHsAfQB/wIAAf8C9AK8BPQDFAHsAvQBFAz0ARQB9AEAAfQBkgET + AQcG9AEHARMBkgH0BQAB9AcUAewB9AH/BQAB9AIUBPQCFAHsAfQB/wH0DhQB9AEAAf8B9AHwAW0B7AHy + AvQB8gHsAW0B8AH0Af8FAAH0BhQB7AH0Af8GAAH0BxQB7AH0Af8BAAH0DhQB9AMAAvQBkgETAgcBEwGS + AvQHAAj0Af8HAAH0BhQB7AH0Af8CAAH0DhQB9AQAAf8B9AHwAm0B8AH0Af8YAAj0Af8DABD0BgAE9CcA + Af8I9AH/BQAJ9AkADPQEAAz0AgAB/wH0ARQB9AFtAhQBbQH0ARQE9AIAAfQHFAH0CQAB9AoUAfQEAAH0 + ChQB9AIAAfQBFAHsAfQEFAH0AewBFAHvARQB9AIAAfQBFAHvAfQB8QFtAewBFAj0AgAB9AoUAfQEAAH0 + ChQB9AIAAfQBFAHsAfQEFAH0AewBFAHvARQB9AIAAfQBFAFtAewB6gEHAfQBFAH0BhQB9AIAAfQCFAb0 + AhQB9AQAAfQCFAb0AhQB9AIAAf8B9AEUAfQB7AL0AewB9AEUAfQCFAH0AgAB9AEUAfIB7AHxAvQBFAH0 + BhQB9AIAAfQCFAb0AhQB9AQAAfQCFAH0BBQB9AIUAfQDAAH/AvQB7QIUAe0D9AIUAfQCAAH0ARQD9AHs + AbwBFAX0AhQB9AIAAfQCFAb0AhQB9AQAAfQCFAb0AhQB9AQAAfQB7wf0AhQB9AIAAfQBFAP0AbwB8gEU + BfQCFAH0AgAB9AIUBvQCFAH0BAAB9AIUAfQEFAH0AhQB9AQAAfQCFAb0AhQB9AIAAfQHFAX0AhQB9AIA + AfQCFAb0AhQB9AQAAfQCFAb0AhQB9AQAAfQCFAb0AhQB9AIADfQCFAH0AgAB9AIUBvQCFAH0BAAB9AIU + AfQEFAH0AhQB9AQAAfQCFAb0AhQB9AYAAfQCFAb0AhQB9AIAAfQCFAT0AxQB7AH0BAAB9AIUBvQCFAH0 + BAAB9AIUBPQDFAHsAfQGAAH0AhQG9AIUAfQCAAH0AhQE9AIUAewB9AH/BAAB9AIUAfQCFAH0AxQB7AH0 + BAAB9AIUBPQCFAHsAfQB/wYAAfQCFAT0AxQB7AH0AgAB9AcUAewB9AH/BQAB9AIUBPQCFAHsAfQB/wQA + AfQHFAHsAfQB/wcAAfQCFAT0AhQB7AH0Af8CAAH0BhQB7AH0Af8GAAH0BxQB7AH0Af8FAAH0BhQB7AH0 + Af8IAAH0BxQB7AH0Af8DAAj0Af8HAAH0BhQB7AH0Af8GAAj0Af8JAAH0BhQB7AH0Af8UAAj0Af8ZAAj0 + Af8lAAH/AfQBGwEaAZkBUgHzAf8cAAH/AfQC/wYAC1IBdAGZARsEAAV5BlIBeQEbAgAB9AlJAhUB9AgA + Af8BkwEaAf8GAAFSA5oGegFSAXoBeQGZBAABeQGZA3kDUgRYAXkBAAEHAREBeAH/AfMB8gHxAfACvAIH + Ae8BFQgAAf8BkwEHBf8CAAFSAaABmgd6AVIBegGzAXQEAAF5ApkCeQNSA1gBswFSAQAB7QHvAVAJSQH3 + AUkDAAL/AfYD/wGTARoB/wH2ARoC/wIAAVIBoAGaB3oBUgF6AboBdAQAAXkCmgGZAXkDUgF5AlgBugFS + AQABBwERAVABmAFyAlAETwFJAaYBigHzAgAB/wGTAUUB9AL/AZMBGgH/AUUBbwL/AgABdAKgAZoGegF0 + AXoB8wF0BAABeQOaAZkBUgJ0A3kB8wFSAQAB6wHvAVABmAJ4BJcBTwFJAbIB0wGKAgAC/wFFARoC/wGZ + ARsB/wF0AfYB/wMAAXkDoAGaBXoBeQF6AfMBdAQAAXkEmgFSAnQDeQHzAVIBAAEHAREBcgGYA3gDlwFP + AUkBsgHTAYoDAAT/ARoBbwFuARsD/wMAAXkEoAGaA3oBmgF5AXoB8wF0BAABegGgA5oBdAJ5AXoCeQHz + AVIBAAHrAe8BcgGYBXgBlwFQAUkBJwECAfMDAAP/AZkBdAJvAUsBGgT/AQABeQWgBJoBeQKaAXQEAAGa + A6ABmgF0AnkBmgJ6AXkBUgEAAQcBEQFyAQgCmAR4AVABSQJWAQIDAAH0AXQBbwFLAW8BAQFvAZMBAQFu + Am8B9gEAAXkGoAOaAXkBmgF5ARoEAAGaBKADeQOaAXkBGgEAAesB7wFyAQgDmAN4AXIBSQJWAQIBAAP/ + AhoBkwJFAZMBdAFvARoB9AL/AQABeQmgAXoBeQH0BQABmgSgAXkBmQF5AaACmgF0AgABBwERAXIBCASY + AngBcgFJASoBMAH0AQAB/wH0ARsC/wH0AZMBRQFvAZMC/wH0ARoB/wEAAXkKoAF5BgABmgLDAqABeQKZ + A6ABeQIAAW0B7wFyAQgGmAGXAUkBNwE4ATABAAH0AUUBGgP/AvYB9AP/ARsBRQGTAQABeQqgAXkGAAGa + A8MBoAF5ApkCwwGgAXkCAAEHAREBlwEIBpgBlwFJATcBOAEwAQAB/wHzAv8BbwEbAf8B8wL/AW8BGgL/ + AfQBAAGaAcMJoAGaBgABmgLDAaABmgF5AZkBGgPDAXkCAAHqAQcBlwEIBpgBlwFQAioB9AMAAf8BGgFL + Av8BRQEbAf8BSwFvAf8DAAGaA8MGoAKaBgAFmgGZBcMBmQIAAfEBQwGXBwgBmAFQAbUB7QUAAfYD/wGT + AfMD/wQAC5oBGwYAA5oCegV5AZkBGwIAAf8BBwWXBXIB9AMAAUIBTQE+BwABPgMAASgDAAFAAwABcAMA + AQEBAAEBBQABgAEDFgAD/4EAAv8BwAP/AR8B9wIAAYABfwH8AT8BDwHDAwABPwH4AT8BAwGDAwABPwHw + ATMBAQEDAwABPwHgASEBAAEDAwABPwMAAQMDAAEDBwABAQIAARAHAAHwAwABwAMAAfADAAH8AwAB8AMA + AfwDAAHwAQMCAAH8AQAB4AEhAf4BAwIAAfwBAAHwATMB/wEDAfgBHwH8AQEB+AE/Af8BgwP/AQMB/AE/ + Af8BwwL/AgAB/wHPAv8EAAH/AY8BgAEPBAABjwEPAYABDwQAAYABDwGAAQ8EAAGAAQ8BgAEDBQABDwGA + AQMFAAEDAYAHAAGABwABgAcAAYAGAAEDAYAGAAEPAYAFAAHAAQ8B4AUAAccBDwHgBQAB/wGPAfgFAAH/ + Ac8B+AEAAfwBPwL/AgAC/wH4AQ8BgAEPAgABgAEBAeABBwEAAQcCAAGAAQEB4AEHAQABBwIAAYABAQHg + AQMBAAEHAgABgAEBAYABAQEAAQcCAAGAAQECAAHAAQcCAAGAAQECAAHAAQcCAAGAAQECAAHAAQcCAAGA + AQECAAHAAQcCAAGAAQECAAHAAQcCAAGAAQEBgAEAAcADAAGAAQEBgAEAAcADAAGAAQEBwAEBAcADAAGA + AQEB4wEDAcABAAEBAf8BgAEBAecB/wHgAQABgwH/AYABAQEAAQ8BwAE/Av8B/AE/AgABgAEfAgAB8AEP + BgAB4AEHBgABgAEBBgABgAEBBgABgAEBAfAFAAGAAQEB8AUAAYABAQHwBQABgAEBAfAFAAGAAQEB8AEA + AYADAAGAAQEB8AEAAcADAAGAAQEB8AEBAfADAAGAAQEB8AEDAfABAQIAAeABBwHwAQcB8AEDAgAB8AEP + Av8B8AEHAgAB/AE/BP8BgAEfAQABfwHAAQMBwAEDAQABAwEAAX8BwAEDAcABAwEAAQMCAAHAAQMBwAED + AQABAwIAAcABAwHAAQMBAAEDAgABwAEDAcABAwGAAQMCAAHAAQMBwAEDAcABAwIAAcABAwHAAQMBwAED + AgABwAEDAcABAwHAAQMCAAHAAQMBwAEDAcABAwHwAQABwAEDAcABAwHAAQMB8AEAAcABAwHAAQMBwAED + AfABAAHAAQcBwAEDAcABBwHwAQABwAEPAcABBwHAAQ8B8AEBAcABHwHAAQ8BwAEfAfABAwL/AcABHwL/ + AfABBwT/AcABPwL/AfwBPwEAAQMBwAEBAYABAwH8AT8BAAEDAcABAQEAAQMB/AEDAQABAwHAAQEBAAED + AYABAwEAAQMBwAEBAQABAQGAAQMBAAEDAcABAQEAAQEBgAEHAQABAwHAAQEBAAEBAcABBwEAAQMBwAEB + AQABAQHAAQEBAAEDAcABAQEAAQEBwAEBAQABAwHAAQEBAAEBAQABAQEAAQcBwAEDAQABAQEAAQEBAAEP + AcABAwEAAQEBAAEBAQABDwHAAQMBAAEBAQABAQEAAQ8BwAEDAQABAQHAAQcBAAEPAcABAwEAAQMB4AEP + AQABDwHAAQMBAAEHCw== + + + + 638, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAQFJREFUOE+dkz0LglAUhv0H/ZLA3+De1FrQ4NJkY9Du3FRLEAZuRVNQS2FLRDQE + UWu0BBX4Mbie7nvxmslNrQMPXI/nfTgXUUlXGIaUgctQo1F5YVDTNCmmaeZLsgQgV5IUeK7/QSFJEUFS + EsXelSUQiPeYjWLvQtMwDNJ1XRoGXwWsMTxfH9Sxt5zT5U6+FxQTsIfGYn+hUt2itrWhZt9h5xGXFBVM + K+acerNDPAgJNklv8U2wgsBenuJBbAJB4OcI2EFluBCUW2MuwSa4jrM7xoE0XCDCte6SlOqAIBFM1kf+ + NWRhIAQu1kQYEjR/AYLG7enxu7Jz/t8mK0j+CyvKC4EcOC+MIvJ7AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAGlJREFUOE/ljlsKgEAIRV1Sa3BxbncKxN9CUKbCdIboqwsHxMdB8IjIntCYebHV + OLqIiCFEVEsygVJKzoK1bReGJHdBVCsusbOe7APH57prZz1PH0S9IUHElMDrqPeHDyq+E8xgZ28DcADi + +uZiNACH5wAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAKZJREFUOE/Nk0sOwyAMRDlSz8CFOEQqtsldOBitYrFNNa1NXMQnCxaxNIplzzxE + ophplVI6OopE9GBrvWC01lblvR9DegBoCNGAV3z/6RLkCkBDOHZWDyCSPbwcO+segBDCd1lqCMBbFfO2 + btmIHjPaqQ3gcJTFsjzziegxww6QKkDC/HmySZuxQ48ryozjEwDlFZxzOYxeoHhqcfxXAilNSo1/wJgP + rxwb6AQLOW8AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAKtJREFUOE/NkNENwjAMRDMSM2QFfpkn3wzQLfLflQqiyq/JmVzkthZFIKRaOtU6 + 3z0pDSLyk0Ip5RTq1K9YNU9vb6eGJgS1dB5U2OmtpNlWfY05rAHqxRi7UkpbCEKX66glC6BnAS6ERRQI + 4I7bbbp3uRAstmwh82N2ARYCAH7WAoK9eouyFSHI8BkdAuWcNeCVoQ0AQwhMBrwy5AIwDfI9AHMswJ7+ + B/hcRZ4ta4FRmq6ouAAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAJVJREFUOE+1kNEJwzAMRDNSZvBCHsLFv8068VJpf/yr+oSckuQCVUMMD8Tp/MAe + ROQSNPRAQw809PAd7NRax8bSkB3IRqtxAQpWlOk5SZmLghmZ7VRyEGCBQs5Zyyk95LW8FczIbKcSJtDL + XRBC2NAFXXKLYPOEGON6GXMXoIPuQbD/xBPOP/FfaOiBhh5o6IGGvyPDB6ug8Uv1Fi1pAAAAAElFTkSu + QmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAJ5JREFUOE/VkcEJwzAMRTNSZ/AKuWYenztAIZtkJbcp+OrkK5L5qIbEhxwqeBjZ + +s9gD1w55xlo21caLkqfxMLTcxFI5Ek7D40dtW/U8DC+BJPEGEsIoYL+R+LDXsKCpgRDFuAwVpy906fS + lGDIbjMB77UELBGBwQKDBV4kGR2Uh2SB3nBJIH+OhsHAun7PBb4sDFph8EeCM+4TXCeXDdS/V/ydKVLV + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB + DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7 + k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAFBJREFUOE9joBh8+/btPz4MVYYbgBQ5OTmBMUwTMh+qDDegigHYNBKL4S6A0chs + YmjauYAQhqkbTi5A1ojMJ0QTNIAQRvECNgxNb4MWMDAAAPsOTf9dAGOQAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAJ5JREFUOE/VkcEJwzAMRTNSZ/AKuWYenztAIZtkJbcp+OrkK5L5qIbEhxwqeBjZ + +s9gD1w55xlo21caLkqfxMLTcxFI5Ek7D40dtW/U8DC+BJPEGEsIoYL+R+LDXsKCpgRDFuAwVpy906fS + lGDIbjMB77UELBGBwQKDBV4kGR2Uh2SB3nBJIH+OhsHAun7PBb4sDFph8EeCM+4TXCeXDdS/V/ydKVLV + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1 + MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAFjSURBVDhPpVOxSsNQFM0PCP2A + Dp0cOgmd3Lo5CU4OTh0E14B+QPQDrLtDcBEHRRx0KgQdFKQQXARRENFGxeHpkvV5zs195kUSHXrg0Mc9 + 956c5N0GRJ7nLTAGLWjAUIRfQD3SHsclJ4RPFyO732sLs/S6FAGcO2B6s7tj92Zn7P3pEfVIZWlIxttb + IpIni/P28y1jEiYLeT7fWBWNfagd62gBNjGBMyAvN9fZaD4e7sSQNZqgloItHS3AAoXbg7hiwqfxlXj2 + UnV0rIomE5ImX++vfHpf2+tBd1Ci+gY0RT3WtnrocG2Cw3733/hzoOGH8wf9b3C2siAfUEdKuOGG2Kl/ + C3ozQx0twGijteXKMBcGjXLX+B2whwk8458lC9x2OdbdNc5M+UiNrzQZX8mSiegbNC4KwBqYsJ+vZCbP + iQgme5Ed19ilcwOgD/lf4ObiHDnnUPnnsAP6BmBCBtbaKWiDbxUsAY8G1hgMAAAAAElFTkSuQmCC + + + + 489, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAIhJREFUOE+9jlEKgCAQRD1KR+gI4Vm8u58WLfpZCbNU22oW0cJD1JnHGm1SSkOB + DpH6xBgXDe99IKIesfLksLX2gnNOl8hVWTCG6URRclxTIgUs2f4C6vWVpYRF+R31XaAFNckjAUtoptN7 + k4Dhgryj/qMgn8wrgQT1dgHi12FBjVtBC4h/OcasZcFBjvFV4nkAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAALNJREFUOE9jIAS+fftmAMTvgfg/NgxVhh0AFYA1t7W1/XdycsLAKAbATETHIM3N + zS3/P7z/iIKxGoBuAwgja4aJ4TUAppgQpp4BIAKGyTYAxCEWYzPgfH5+PoZCXPjokaMYBjQsX74cQyEu + 3NfXj2GAwZUrVzAU4sLJScmoBkBj4H1kZCSGYlz41s3bYBrZgPm4kis2vH7dejCNbEDCvn37MBQSwsgG + CIA45GCG//8pwf8ZANa5gGyReLItAAAAAElFTkSuQmCC + + + + 782, 17 + + + 17, 56 + + + 152, 56 + + + 126 + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/ExtractKeysForm.Designer.cs b/ExtractKeysForm.Designer.cs new file mode 100644 index 0000000..df85296 --- /dev/null +++ b/ExtractKeysForm.Designer.cs @@ -0,0 +1,160 @@ +namespace CodeWalker +{ + partial class ExtractKeysForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExtractKeysForm)); + this.BeginButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.FolderBrowseButton = new System.Windows.Forms.Button(); + this.FolderTextBox = new System.Windows.Forms.TextBox(); + this.StatusLabel = new System.Windows.Forms.Label(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.label2 = new System.Windows.Forms.Label(); + this.ExeBrowseButton = new System.Windows.Forms.Button(); + this.ExeTextBox = new System.Windows.Forms.TextBox(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.SuspendLayout(); + // + // BeginButton + // + this.BeginButton.Location = new System.Drawing.Point(98, 89); + this.BeginButton.Name = "BeginButton"; + this.BeginButton.Size = new System.Drawing.Size(75, 23); + this.BeginButton.TabIndex = 60; + this.BeginButton.Text = "Begin"; + this.BeginButton.UseVisualStyleBackColor = true; + this.BeginButton.Click += new System.EventHandler(this.BeginButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(20, 28); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(68, 13); + this.label1.TabIndex = 59; + this.label1.Text = "GTAV folder:"; + // + // FolderBrowseButton + // + this.FolderBrowseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.FolderBrowseButton.Location = new System.Drawing.Point(449, 23); + this.FolderBrowseButton.Name = "FolderBrowseButton"; + this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.FolderBrowseButton.TabIndex = 58; + this.FolderBrowseButton.Text = "..."; + this.FolderBrowseButton.UseVisualStyleBackColor = true; + this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click); + // + // FolderTextBox + // + this.FolderTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FolderTextBox.Location = new System.Drawing.Point(98, 25); + this.FolderTextBox.Name = "FolderTextBox"; + this.FolderTextBox.Size = new System.Drawing.Size(345, 20); + this.FolderTextBox.TabIndex = 57; + this.FolderTextBox.TextChanged += new System.EventHandler(this.FolderTextBox_TextChanged); + // + // StatusLabel + // + this.StatusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.StatusLabel.AutoEllipsis = true; + this.StatusLabel.Location = new System.Drawing.Point(20, 139); + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(474, 125); + this.StatusLabel.TabIndex = 61; + this.StatusLabel.Text = "Keys not loaded - Browse for the main GTAV folder and click Begin..."; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(20, 54); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(59, 13); + this.label2.TabIndex = 64; + this.label2.Text = "GTAV exe:"; + // + // ExeBrowseButton + // + this.ExeBrowseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ExeBrowseButton.Location = new System.Drawing.Point(449, 49); + this.ExeBrowseButton.Name = "ExeBrowseButton"; + this.ExeBrowseButton.Size = new System.Drawing.Size(27, 23); + this.ExeBrowseButton.TabIndex = 63; + this.ExeBrowseButton.Text = "..."; + this.ExeBrowseButton.UseVisualStyleBackColor = true; + this.ExeBrowseButton.Click += new System.EventHandler(this.ExeBrowseButton_Click); + // + // ExeTextBox + // + this.ExeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ExeTextBox.Location = new System.Drawing.Point(98, 51); + this.ExeTextBox.Name = "ExeTextBox"; + this.ExeTextBox.Size = new System.Drawing.Size(345, 20); + this.ExeTextBox.TabIndex = 62; + // + // ExtractKeysForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(518, 273); + this.Controls.Add(this.label2); + this.Controls.Add(this.ExeBrowseButton); + this.Controls.Add(this.ExeTextBox); + this.Controls.Add(this.StatusLabel); + this.Controls.Add(this.BeginButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.FolderBrowseButton); + this.Controls.Add(this.FolderTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "ExtractKeysForm"; + this.Text = "ExtractKeysForm"; + this.Load += new System.EventHandler(this.ExtractKeysForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button BeginButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button FolderBrowseButton; + private System.Windows.Forms.TextBox FolderTextBox; + private System.Windows.Forms.Label StatusLabel; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button ExeBrowseButton; + private System.Windows.Forms.TextBox ExeTextBox; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + } +} \ No newline at end of file diff --git a/ExtractKeysForm.cs b/ExtractKeysForm.cs new file mode 100644 index 0000000..ee97408 --- /dev/null +++ b/ExtractKeysForm.cs @@ -0,0 +1,145 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class ExtractKeysForm : Form + { + private volatile bool KeysLoaded = false; + private volatile bool InProgress = false; + private volatile bool AbortOperation = false; + + public ExtractKeysForm() + { + InitializeComponent(); + } + + private void ExtractKeysForm_Load(object sender, EventArgs e) + { + FolderTextBox.Text = Settings.Default.GTAFolder; + + try + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); + KeysLoaded = true; + UpdateStatus("Keys loaded. Nothing to do here!"); + } + catch + { + //default label text has this case + //UpdateStatus("Keys not found! Please scan a GTA 5 exe..."); + } + } + + private void FolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.GTAFolder = FolderTextBox.Text; + ExeTextBox.Text = FolderTextBox.Text + "\\" + "GTA5.exe"; + } + + private void FolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = Settings.Default.GTAFolder; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + FolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void ExeBrowseButton_Click(object sender, EventArgs e) + { + if (!string.IsNullOrEmpty(FolderTextBox.Text) && !string.IsNullOrEmpty(ExeTextBox.Text)) + { + OpenFileDialog.InitialDirectory = FolderTextBox.Text; + OpenFileDialog.FileName = ExeTextBox.Text; + } + DialogResult res = OpenFileDialog.ShowDialog(); + if (res == DialogResult.OK) + { + ExeTextBox.Text = OpenFileDialog.FileName; + } + } + + + private void UpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { UpdateStatus(text); })); + } + else + { + StatusLabel.Text = text; + } + } + catch { } + } + + private void BeginButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + if (KeysLoaded) + { + if (MessageBox.Show("Keys are already loaded. Do you wish to do the extraction anyway?", "Keys already loaded", MessageBoxButtons.OKCancel) != DialogResult.OK) + { + return; + } + } + + + InProgress = true; + AbortOperation = false; + + string exepath = ExeTextBox.Text; + + Task.Run(() => + { + try + { + + if (AbortOperation) + { + UpdateStatus("Key extraction aborted."); + return; + } + + FileInfo dmpfi = new FileInfo(exepath); + + UpdateStatus(string.Format("Scanning {0} for keys...", dmpfi.Name)); + + + byte[] exedat = File.ReadAllBytes(exepath); + GTA5Keys.GenerateV2(exedat, UpdateStatus); + + + UpdateStatus("Saving found keys..."); + + //GTA5Keys.SaveToPath(); + + UpdateStatus("Keys extracted successfully."); + KeysLoaded = true; + InProgress = false; + } + catch (Exception ex) + { + UpdateStatus("Error - " + ex.ToString()); + + InProgress = false; + } + }); + } + } +} diff --git a/ExtractKeysForm.resx b/ExtractKeysForm.resx new file mode 100644 index 0000000..e71684f --- /dev/null +++ b/ExtractKeysForm.resx @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 326, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/ExtractRawForm.Designer.cs b/ExtractRawForm.Designer.cs new file mode 100644 index 0000000..2c14b15 --- /dev/null +++ b/ExtractRawForm.Designer.cs @@ -0,0 +1,229 @@ +namespace CodeWalker +{ + partial class ExtractRawForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExtractRawForm)); + this.AbortButton = new System.Windows.Forms.Button(); + this.label4 = new System.Windows.Forms.Label(); + this.OutputFolderBrowseButton = new System.Windows.Forms.Button(); + this.OutputFolderTextBox = new System.Windows.Forms.TextBox(); + this.ExtractStatusLabel = new System.Windows.Forms.Label(); + this.ExtractButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.FolderBrowseButton = new System.Windows.Forms.Button(); + this.FolderTextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.FileMatchTextBox = new System.Windows.Forms.TextBox(); + this.MatchEndsWithRadio = new System.Windows.Forms.RadioButton(); + this.MatchContainsRadio = new System.Windows.Forms.RadioButton(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.CompressCheckBox = new System.Windows.Forms.CheckBox(); + this.SuspendLayout(); + // + // AbortButton + // + this.AbortButton.Location = new System.Drawing.Point(186, 99); + this.AbortButton.Name = "AbortButton"; + this.AbortButton.Size = new System.Drawing.Size(75, 23); + this.AbortButton.TabIndex = 72; + this.AbortButton.Text = "Abort"; + this.AbortButton.UseVisualStyleBackColor = true; + this.AbortButton.Click += new System.EventHandler(this.AbortButton_Click); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(13, 41); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(71, 13); + this.label4.TabIndex = 71; + this.label4.Text = "Output folder:"; + // + // OutputFolderBrowseButton + // + this.OutputFolderBrowseButton.Location = new System.Drawing.Point(348, 36); + this.OutputFolderBrowseButton.Name = "OutputFolderBrowseButton"; + this.OutputFolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.OutputFolderBrowseButton.TabIndex = 70; + this.OutputFolderBrowseButton.Text = "..."; + this.OutputFolderBrowseButton.UseVisualStyleBackColor = true; + this.OutputFolderBrowseButton.Click += new System.EventHandler(this.OutputFolderBrowseButton_Click); + // + // OutputFolderTextBox + // + this.OutputFolderTextBox.Location = new System.Drawing.Point(91, 38); + this.OutputFolderTextBox.Name = "OutputFolderTextBox"; + this.OutputFolderTextBox.Size = new System.Drawing.Size(251, 20); + this.OutputFolderTextBox.TabIndex = 69; + this.OutputFolderTextBox.TextChanged += new System.EventHandler(this.OutputFolderTextBox_TextChanged); + // + // ExtractStatusLabel + // + this.ExtractStatusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ExtractStatusLabel.AutoEllipsis = true; + this.ExtractStatusLabel.Location = new System.Drawing.Point(13, 136); + this.ExtractStatusLabel.Name = "ExtractStatusLabel"; + this.ExtractStatusLabel.Size = new System.Drawing.Size(501, 37); + this.ExtractStatusLabel.TabIndex = 68; + this.ExtractStatusLabel.Text = "Initialising..."; + // + // ExtractButton + // + this.ExtractButton.Location = new System.Drawing.Point(91, 99); + this.ExtractButton.Name = "ExtractButton"; + this.ExtractButton.Size = new System.Drawing.Size(75, 23); + this.ExtractButton.TabIndex = 67; + this.ExtractButton.Text = "Extract"; + this.ExtractButton.UseVisualStyleBackColor = true; + this.ExtractButton.Click += new System.EventHandler(this.ExtractButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(13, 15); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(68, 13); + this.label1.TabIndex = 66; + this.label1.Text = "GTAV folder:"; + // + // FolderBrowseButton + // + this.FolderBrowseButton.Location = new System.Drawing.Point(348, 10); + this.FolderBrowseButton.Name = "FolderBrowseButton"; + this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.FolderBrowseButton.TabIndex = 65; + this.FolderBrowseButton.Text = "..."; + this.FolderBrowseButton.UseVisualStyleBackColor = true; + this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click); + // + // FolderTextBox + // + this.FolderTextBox.Location = new System.Drawing.Point(91, 12); + this.FolderTextBox.Name = "FolderTextBox"; + this.FolderTextBox.Size = new System.Drawing.Size(251, 20); + this.FolderTextBox.TabIndex = 64; + this.FolderTextBox.TextChanged += new System.EventHandler(this.FolderTextBox_TextChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(13, 67); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(58, 13); + this.label2.TabIndex = 74; + this.label2.Text = "File match:"; + // + // FileMatchTextBox + // + this.FileMatchTextBox.Location = new System.Drawing.Point(91, 64); + this.FileMatchTextBox.Name = "FileMatchTextBox"; + this.FileMatchTextBox.Size = new System.Drawing.Size(198, 20); + this.FileMatchTextBox.TabIndex = 73; + this.FileMatchTextBox.Text = ".ymt"; + // + // MatchEndsWithRadio + // + this.MatchEndsWithRadio.AutoSize = true; + this.MatchEndsWithRadio.Checked = true; + this.MatchEndsWithRadio.Location = new System.Drawing.Point(295, 65); + this.MatchEndsWithRadio.Name = "MatchEndsWithRadio"; + this.MatchEndsWithRadio.Size = new System.Drawing.Size(71, 17); + this.MatchEndsWithRadio.TabIndex = 75; + this.MatchEndsWithRadio.TabStop = true; + this.MatchEndsWithRadio.Text = "Ends with"; + this.MatchEndsWithRadio.UseVisualStyleBackColor = true; + // + // MatchContainsRadio + // + this.MatchContainsRadio.AutoSize = true; + this.MatchContainsRadio.Location = new System.Drawing.Point(372, 65); + this.MatchContainsRadio.Name = "MatchContainsRadio"; + this.MatchContainsRadio.Size = new System.Drawing.Size(66, 17); + this.MatchContainsRadio.TabIndex = 76; + this.MatchContainsRadio.Text = "Contains"; + this.MatchContainsRadio.UseVisualStyleBackColor = true; + // + // CompressCheckBox + // + this.CompressCheckBox.AutoSize = true; + this.CompressCheckBox.Location = new System.Drawing.Point(348, 103); + this.CompressCheckBox.Name = "CompressCheckBox"; + this.CompressCheckBox.Size = new System.Drawing.Size(93, 17); + this.CompressCheckBox.TabIndex = 77; + this.CompressCheckBox.Text = "Compress files"; + this.CompressCheckBox.UseVisualStyleBackColor = true; + // + // ExtractRawForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(528, 274); + this.Controls.Add(this.CompressCheckBox); + this.Controls.Add(this.MatchContainsRadio); + this.Controls.Add(this.MatchEndsWithRadio); + this.Controls.Add(this.label2); + this.Controls.Add(this.FileMatchTextBox); + this.Controls.Add(this.AbortButton); + this.Controls.Add(this.label4); + this.Controls.Add(this.OutputFolderBrowseButton); + this.Controls.Add(this.OutputFolderTextBox); + this.Controls.Add(this.ExtractStatusLabel); + this.Controls.Add(this.ExtractButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.FolderBrowseButton); + this.Controls.Add(this.FolderTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "ExtractRawForm"; + this.Text = "Extract Raw Files - CodeWalker by dexyfex"; + this.Load += new System.EventHandler(this.ExtractRawForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button AbortButton; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button OutputFolderBrowseButton; + private System.Windows.Forms.TextBox OutputFolderTextBox; + private System.Windows.Forms.Label ExtractStatusLabel; + private System.Windows.Forms.Button ExtractButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button FolderBrowseButton; + private System.Windows.Forms.TextBox FolderTextBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox FileMatchTextBox; + private System.Windows.Forms.RadioButton MatchEndsWithRadio; + private System.Windows.Forms.RadioButton MatchContainsRadio; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.CheckBox CompressCheckBox; + } +} \ No newline at end of file diff --git a/ExtractRawForm.cs b/ExtractRawForm.cs new file mode 100644 index 0000000..b199371 --- /dev/null +++ b/ExtractRawForm.cs @@ -0,0 +1,227 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class ExtractRawForm : Form + { + private volatile bool KeysLoaded = false; + private volatile bool InProgress = false; + private volatile bool AbortOperation = false; + + public ExtractRawForm() + { + InitializeComponent(); + } + + private void ExtractRawForm_Load(object sender, EventArgs e) + { + FolderTextBox.Text = Settings.Default.GTAFolder; + OutputFolderTextBox.Text = Settings.Default.ExtractedRawFilesFolder; + + try + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); + KeysLoaded = true; + UpdateExtractStatus("Ready to extract."); + } + catch + { + UpdateExtractStatus("Keys not found! This shouldn't happen."); + } + } + + + private void UpdateExtractStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { UpdateExtractStatus(text); })); + } + else + { + ExtractStatusLabel.Text = text; + } + } + catch { } + } + + private void FolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.GTAFolder = FolderTextBox.Text; + } + + private void OutputFolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.ExtractedRawFilesFolder = OutputFolderTextBox.Text; + } + + private void FolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = Settings.Default.GTAFolder; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + FolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void OutputFolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = OutputFolderTextBox.Text; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + OutputFolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void ExtractButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + + if (!KeysLoaded) + { + MessageBox.Show("Please scan a GTA 5 exe dump for keys first, or include key files in this app's folder!"); + return; + } + if (!Directory.Exists(FolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + FolderTextBox.Text); + return; + } + if (!Directory.Exists(OutputFolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + OutputFolderTextBox.Text); + return; + } + if(string.IsNullOrEmpty(FileMatchTextBox.Text) || (FileMatchTextBox.Text.Length < 3)) + { + MessageBox.Show("Please enter at least 3 characters to match."); + return; + } + + InProgress = true; + AbortOperation = false; + + string searchpath = FolderTextBox.Text; + string outputpath = OutputFolderTextBox.Text; + string replpath = searchpath + "\\"; + string matchstr = FileMatchTextBox.Text; + bool endswith = MatchEndsWithRadio.Checked; + bool compress = CompressCheckBox.Checked; + + Task.Run(() => + { + + UpdateExtractStatus("Keys loaded."); + + + + RpfManager rpfman = new RpfManager(); + rpfman.Init(searchpath, UpdateExtractStatus, UpdateExtractStatus); + + + UpdateExtractStatus("Beginning file extraction..."); + StringBuilder errsb = new StringBuilder(); + foreach (RpfFile rpf in rpfman.AllRpfs) + { + foreach (RpfEntry entry in rpf.AllEntries) + { + if (AbortOperation) + { + UpdateExtractStatus("Operation aborted"); + InProgress = false; + return; + } + try + { + bool extract = false; + if (endswith) + { + extract = entry.NameLower.EndsWith(matchstr); + } + else + { + extract = entry.NameLower.Contains(matchstr); + } + var fentry = entry as RpfFileEntry; + if (fentry == null) + { + extract = false; + } + if (extract) + { + UpdateExtractStatus(entry.Path); + + byte[] data = entry.File.ExtractFile(fentry); + + if (compress) + { + data = ResourceBuilder.Compress(data); + } + + RpfResourceFileEntry rrfe = fentry as RpfResourceFileEntry; + if (rrfe != null) //add resource header if this is a resource file. + { + data = ResourceBuilder.AddResourceHeader(rrfe, data); + } + + + if (data != null) + { + var finf = new FileInfo(entry.Name); + string bpath = outputpath + "\\" + entry.Name.Substring(0, entry.Name.Length - finf.Extension.Length); + string fpath = bpath + finf.Extension; + int c = 1; + while (File.Exists(fpath)) + { + fpath = bpath + "_" + c.ToString() + finf.Extension; + c++; + } + + File.WriteAllBytes(fpath, data); + + + } + else + { + throw new Exception("Couldn't extract data."); + } + } + } + catch (Exception ex) + { + string err = entry.Name + ": " + ex.Message; + UpdateExtractStatus(err); + errsb.AppendLine(err); + } + + } + } + + File.WriteAllText(outputpath + "\\_errors.txt", errsb.ToString()); + + UpdateExtractStatus("Complete."); + InProgress = false; + }); + } + + private void AbortButton_Click(object sender, EventArgs e) + { + AbortOperation = true; + } + } +} diff --git a/ExtractRawForm.resx b/ExtractRawForm.resx new file mode 100644 index 0000000..bd12579 --- /dev/null +++ b/ExtractRawForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/ExtractScriptsForm.Designer.cs b/ExtractScriptsForm.Designer.cs new file mode 100644 index 0000000..9d8accd --- /dev/null +++ b/ExtractScriptsForm.Designer.cs @@ -0,0 +1,244 @@ +namespace CodeWalker +{ + partial class ExtractScriptsForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExtractScriptsForm)); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.OutputFolderBrowseButton = new System.Windows.Forms.Button(); + this.OutputFolderTextBox = new System.Windows.Forms.TextBox(); + this.FindKeysButton = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.DumpBrowseButton = new System.Windows.Forms.Button(); + this.DumpTextBox = new System.Windows.Forms.TextBox(); + this.ExtractStatusLabel = new System.Windows.Forms.Label(); + this.DumpStatusLabel = new System.Windows.Forms.Label(); + this.ExtractScriptsButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.FolderBrowseButton = new System.Windows.Forms.Button(); + this.FolderTextBox = new System.Windows.Forms.TextBox(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.SuspendLayout(); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(12, 10); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(113, 13); + this.label6.TabIndex = 56; + this.label6.Text = "Extract all YSC scripts:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(12, 170); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(87, 13); + this.label5.TabIndex = 55; + this.label5.Text = "Decryption Keys:"; + this.label5.Visible = false; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(20, 55); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(71, 13); + this.label4.TabIndex = 54; + this.label4.Text = "Output folder:"; + // + // OutputFolderBrowseButton + // + this.OutputFolderBrowseButton.Location = new System.Drawing.Point(355, 50); + this.OutputFolderBrowseButton.Name = "OutputFolderBrowseButton"; + this.OutputFolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.OutputFolderBrowseButton.TabIndex = 53; + this.OutputFolderBrowseButton.Text = "..."; + this.OutputFolderBrowseButton.UseVisualStyleBackColor = true; + this.OutputFolderBrowseButton.Click += new System.EventHandler(this.OutputFolderBrowseButton_Click); + // + // OutputFolderTextBox + // + this.OutputFolderTextBox.Location = new System.Drawing.Point(98, 52); + this.OutputFolderTextBox.Name = "OutputFolderTextBox"; + this.OutputFolderTextBox.Size = new System.Drawing.Size(251, 20); + this.OutputFolderTextBox.TabIndex = 52; + this.OutputFolderTextBox.TextChanged += new System.EventHandler(this.OutputFolderTextBox_TextChanged); + // + // FindKeysButton + // + this.FindKeysButton.Location = new System.Drawing.Point(388, 185); + this.FindKeysButton.Name = "FindKeysButton"; + this.FindKeysButton.Size = new System.Drawing.Size(75, 23); + this.FindKeysButton.TabIndex = 51; + this.FindKeysButton.Text = "Find keys"; + this.FindKeysButton.UseVisualStyleBackColor = true; + this.FindKeysButton.Visible = false; + this.FindKeysButton.Click += new System.EventHandler(this.FindKeysButton_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(20, 190); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(68, 13); + this.label3.TabIndex = 50; + this.label3.Text = "GTAV dump:"; + this.label3.Visible = false; + // + // DumpBrowseButton + // + this.DumpBrowseButton.Location = new System.Drawing.Point(355, 185); + this.DumpBrowseButton.Name = "DumpBrowseButton"; + this.DumpBrowseButton.Size = new System.Drawing.Size(27, 23); + this.DumpBrowseButton.TabIndex = 49; + this.DumpBrowseButton.Text = "..."; + this.DumpBrowseButton.UseVisualStyleBackColor = true; + this.DumpBrowseButton.Visible = false; + this.DumpBrowseButton.Click += new System.EventHandler(this.DumpBrowseButton_Click); + // + // DumpTextBox + // + this.DumpTextBox.Location = new System.Drawing.Point(98, 187); + this.DumpTextBox.Name = "DumpTextBox"; + this.DumpTextBox.Size = new System.Drawing.Size(251, 20); + this.DumpTextBox.TabIndex = 48; + this.DumpTextBox.Text = "gta5_dump.exe"; + this.DumpTextBox.Visible = false; + this.DumpTextBox.TextChanged += new System.EventHandler(this.DumpTextBox_TextChanged); + // + // ExtractStatusLabel + // + this.ExtractStatusLabel.AutoEllipsis = true; + this.ExtractStatusLabel.Location = new System.Drawing.Point(45, 80); + this.ExtractStatusLabel.Name = "ExtractStatusLabel"; + this.ExtractStatusLabel.Size = new System.Drawing.Size(455, 41); + this.ExtractStatusLabel.TabIndex = 47; + this.ExtractStatusLabel.Text = "Initialising..."; + // + // DumpStatusLabel + // + this.DumpStatusLabel.AutoEllipsis = true; + this.DumpStatusLabel.Location = new System.Drawing.Point(45, 215); + this.DumpStatusLabel.Name = "DumpStatusLabel"; + this.DumpStatusLabel.Size = new System.Drawing.Size(455, 37); + this.DumpStatusLabel.TabIndex = 46; + this.DumpStatusLabel.Text = "Keys not found!"; + this.DumpStatusLabel.Visible = false; + // + // ExtractScriptsButton + // + this.ExtractScriptsButton.Location = new System.Drawing.Point(388, 50); + this.ExtractScriptsButton.Name = "ExtractScriptsButton"; + this.ExtractScriptsButton.Size = new System.Drawing.Size(75, 23); + this.ExtractScriptsButton.TabIndex = 45; + this.ExtractScriptsButton.Text = "Extract"; + this.ExtractScriptsButton.UseVisualStyleBackColor = true; + this.ExtractScriptsButton.Click += new System.EventHandler(this.ExtractScriptsButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(20, 29); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(68, 13); + this.label1.TabIndex = 44; + this.label1.Text = "GTAV folder:"; + // + // FolderBrowseButton + // + this.FolderBrowseButton.Location = new System.Drawing.Point(355, 24); + this.FolderBrowseButton.Name = "FolderBrowseButton"; + this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.FolderBrowseButton.TabIndex = 43; + this.FolderBrowseButton.Text = "..."; + this.FolderBrowseButton.UseVisualStyleBackColor = true; + this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click); + // + // FolderTextBox + // + this.FolderTextBox.Location = new System.Drawing.Point(98, 26); + this.FolderTextBox.Name = "FolderTextBox"; + this.FolderTextBox.Size = new System.Drawing.Size(251, 20); + this.FolderTextBox.TabIndex = 42; + this.FolderTextBox.TextChanged += new System.EventHandler(this.FolderTextBox_TextChanged); + // + // ExtractScriptsForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(512, 143); + this.Controls.Add(this.label6); + this.Controls.Add(this.label5); + this.Controls.Add(this.label4); + this.Controls.Add(this.OutputFolderBrowseButton); + this.Controls.Add(this.OutputFolderTextBox); + this.Controls.Add(this.FindKeysButton); + this.Controls.Add(this.label3); + this.Controls.Add(this.DumpBrowseButton); + this.Controls.Add(this.DumpTextBox); + this.Controls.Add(this.ExtractStatusLabel); + this.Controls.Add(this.DumpStatusLabel); + this.Controls.Add(this.ExtractScriptsButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.FolderBrowseButton); + this.Controls.Add(this.FolderTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "ExtractScriptsForm"; + this.Text = "Script Extractor - CodeWalker by dexyfex"; + this.Load += new System.EventHandler(this.ExtractForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button OutputFolderBrowseButton; + private System.Windows.Forms.TextBox OutputFolderTextBox; + private System.Windows.Forms.Button FindKeysButton; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button DumpBrowseButton; + private System.Windows.Forms.TextBox DumpTextBox; + private System.Windows.Forms.Label ExtractStatusLabel; + private System.Windows.Forms.Label DumpStatusLabel; + private System.Windows.Forms.Button ExtractScriptsButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button FolderBrowseButton; + private System.Windows.Forms.TextBox FolderTextBox; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + } +} \ No newline at end of file diff --git a/ExtractScriptsForm.cs b/ExtractScriptsForm.cs new file mode 100644 index 0000000..69abc39 --- /dev/null +++ b/ExtractScriptsForm.cs @@ -0,0 +1,235 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class ExtractScriptsForm : Form + { + private volatile bool KeysLoaded = false; + private volatile bool InProgress = false; + private volatile bool AbortOperation = false; + + + public ExtractScriptsForm() + { + InitializeComponent(); + } + + private void ExtractForm_Load(object sender, EventArgs e) + { + DumpTextBox.Text = Settings.Default.GTAExeDumpFile; + FolderTextBox.Text = Settings.Default.GTAFolder; + OutputFolderTextBox.Text = Settings.Default.CompiledScriptFolder; + + try + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); + KeysLoaded = true; + UpdateDumpStatus("Ready."); + UpdateExtractStatus("Ready to extract."); + } + catch + { + UpdateDumpStatus("Keys not found! This shouldn't happen."); + } + } + + private void DumpTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.GTAExeDumpFile = DumpTextBox.Text; + } + + private void FolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.GTAFolder = FolderTextBox.Text; + } + + private void OutputFolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.CompiledScriptFolder = OutputFolderTextBox.Text; + } + + private void FolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = Settings.Default.GTAFolder; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + FolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void OutputFolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = OutputFolderTextBox.Text; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + OutputFolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void DumpBrowseButton_Click(object sender, EventArgs e) + { + + DialogResult res = OpenFileDialog.ShowDialog(); + if (res == DialogResult.OK) + { + DumpTextBox.Text = OpenFileDialog.FileName; + } + + } + + private void FindKeysButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + if (KeysLoaded) + { + if (MessageBox.Show("Keys are already loaded. Do you wish to scan the exe dump anyway?", "Keys already loaded", MessageBoxButtons.OKCancel) != DialogResult.OK) + { + return; + } + } + + + InProgress = true; + AbortOperation = false; + + string dmppath = DumpTextBox.Text; + + Task.Run(() => + { + try + { + + if (AbortOperation) + { + UpdateDumpStatus("Dump scan aborted."); + return; + } + + FileInfo dmpfi = new FileInfo(dmppath); + + UpdateDumpStatus(string.Format("Scanning {0} for keys...", dmpfi.Name)); + + + byte[] exedat = File.ReadAllBytes(dmppath); + GTA5Keys.Generate(exedat, UpdateDumpStatus); + + + UpdateDumpStatus("Saving found keys..."); + + GTA5Keys.SaveToPath(); + + UpdateDumpStatus("Keys loaded."); + UpdateExtractStatus("Keys loaded, ready to extract."); + KeysLoaded = true; + InProgress = false; + } + catch (Exception ex) + { + UpdateDumpStatus("Error - " + ex.ToString()); + + InProgress = false; + } + }); + } + + private void ExtractScriptsButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + + if (!KeysLoaded) + { + MessageBox.Show("Please scan a GTA 5 exe dump for keys first, or include key files in this app's folder!"); + return; + } + if (!Directory.Exists(FolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + FolderTextBox.Text); + return; + } + if (!Directory.Exists(OutputFolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + OutputFolderTextBox.Text); + return; + } + if (Directory.GetFiles(OutputFolderTextBox.Text, "*.ysc", SearchOption.AllDirectories).Length > 0) + { + if (MessageBox.Show("Output folder already contains .ysc files. Are you sure you want to continue?", "Output folder already contains .ysc files", MessageBoxButtons.OKCancel) != DialogResult.OK) + { + return; + } + } + + InProgress = true; + AbortOperation = false; + + string searchpath = FolderTextBox.Text; + string outputpath = OutputFolderTextBox.Text; + string replpath = searchpath + "\\"; + + Task.Run(() => + { + + UpdateExtractStatus("Keys loaded."); + + string[] allfiles = Directory.GetFiles(searchpath, "*.rpf", SearchOption.AllDirectories); + foreach (string rpfpath in allfiles) + { + RpfFile rf = new RpfFile(rpfpath, rpfpath.Replace(replpath, "")); + UpdateExtractStatus("Searching " + rf.Name + "..."); + rf.ExtractScripts(outputpath, UpdateExtractStatus); + } + + UpdateExtractStatus("Complete."); + InProgress = false; + }); + } + + + + private void UpdateDumpStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { UpdateDumpStatus(text); })); + } + else + { + DumpStatusLabel.Text = text; + } + } + catch { } + } + + private void UpdateExtractStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { UpdateExtractStatus(text); })); + } + else + { + ExtractStatusLabel.Text = text; + } + } + catch { } + } + + } +} diff --git a/ExtractScriptsForm.resx b/ExtractScriptsForm.resx new file mode 100644 index 0000000..fdb418c --- /dev/null +++ b/ExtractScriptsForm.resx @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 26, 17 + + + 191, 17 + + + + + AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA + AABAAAAAAQAYAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv8/u3v+Pn6//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AP7+/vX3/rzA3OHl9fz9/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7//+zv+3Z6qcLI5Pr7/wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAP7+/+br+15in6+33vf5/wAAAAAAAAAAAAAAAP7+//7+/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//v8//v8//3+/wAAAAAAAAAAAAAAAAAAAP7+/+Ho+1dana20 + 4/b4/wAAAAAAAPz9//P2/+Tp/ezw/vz9/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///X4 + /9Pa+tPa+/H1//z9/wAAAAAAAAAAAAAAAP7+/93k+SsscaSr3PX3/wAAAP7+//L1/7W98AcWgrvC8Pj6 + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/+bs/xohiAEJdrvF9+7y//z9/wAAAAAAAAAA + AP7+/9rh+CEkapmh0/T3/wAAAPj6/9HZ/AEHcgEEb9LZ+/r7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAP7//+/z/3F+zAAAXwQLcZai3fb4/wAAAAAAAAAAAP3+/97l/E9Tmaau4fT3/wAAAO/0/1dd + sAAAV7a/8/H1//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPr8/+jv/46Y3QUUf6Ot + 5PX4/wAAAAAAAAAAAP3+/9zj+3Z6wLe/7fX4/wAAAPD0/212xnaAzerw//z9/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv8/+/z/+Dm+/D0//z9/wAAAAAAAP7+//j6/9Pd+UhLjb/H + 9/D0//3+//n7/+nt/+jt//n7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AP7///7+//7+//7+/wAAAAAAAPr8/+7z/83W+ImU2A0UdFNarr/K9env//X4//z9//3+//7//wAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///j6/+Pq/255 + xhckjE5XsVVftUlTqwAKeTA9nr3H8+7z//v8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+//b4/9Tc+Sc0mRonj8rV/crX/ZSb48rX/brG8wwWgQAEdJei + 4efu//n7//7+//z9//z9//z9//z9//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//f5/+3y/+nv/+ft + /8vV+io2mImU2M7c/7vG9yIvlQAOfCg4mM3Y/s/c/4aR1AQRfGtzwtni/ebt/9vi/tri/tXd+9Tc+O3x + /vz9/wAAAAAAAAAAAAAAAAAAAAAAAPn6/87V+FVftkRPrFlnvSEqjQoUfmJvwWFvvg0TfQQIcxEchwAD + cy89n19rvVVitQwZgwAAaiMrkT9NqTVBoiw3mhQihig1mNLX+fv8/wAAAAAAAAAAAAAAAAAAAAAAAPb5 + /52l4EFLqoCK03yF0VBctGhyw52o5GVrvQAAaneBzsHM+jA3mhYgiTtIpJOf3ouW2AAAbmh0wbbA8bS+ + 7qiz5pCb16+56e/z//3+/wAAAAAAAAAAAAAAAAAAAAAAAPv8//H1/+vw/+zx/+nv/7/J9YqP3MbP/8LM + +hwqkFZftaCp5EhRrcTQ+9jj/8rW/UJMqn6J0ebt//X3//f5//b4//X3//f5//z9/wAAAAAAAAAAAAAA + AAAAAAAAAP7+//z9//3+/wAAAAAAAP3+/+7z/6at64iP3aWs7XN8zRIfhyUykp2o5MHM+oKM0xonjY6X + 2+jv//v8/wAAAP7+//n7//b5//r7//7//wAAAAAAAAAAAAAAAP7+//f5/+rw/9Pa9fL0/v7//wAAAAAA + APv8//H1/+Tr/7i/91liu0NPq0VQrS06m0NNqDdCoYqU1+nv//v8/wAAAAAAAPn7/9zi/qSt59ri/fL1 + //v8//7//wAAAPz9//D0/8rT+h0sjkVQrPD0/wAAAAAAAAAAAAAAAAAAAPz9/+7z/8LL9Jqk4aGq6LW/ + 8c3W9+Xs/vH1//v8/wAAAAAAAAAAAPf5/6at5gAAbxIfh6u16+Po/fr7/wAAAPb5/6ev5gAIeAAPernC + 8fX4/wAAAAAAAP3+//v8//z9/wAAAP3+//j6//P3//P2//b4//r8//7+//7+//v8//r8//3+/wAAAPv8 + /+Xr/nuIzwAAbBseg5Sb2fb5/wAAAPf5/8DF8pWe3d/n/vT3//39/wAAAPv8/+zx/87V9+3x/v3+/wAA + AP3+//j6//X4//v8/wAAAAAAAPn7/+Dm/snR9fD0//39//z8/fv8/+3y/8LK9aGq4dfd9/n7/wAAAPz9 + //b5//X4//v8/wAAAAAAAP7+/+7z/4aP1gEPet7k/f39/wAAAPf5/83U+ZCZ2u3x/v7+/wAAAPP3/215 + wgAJd7fB8/L1//7+/wAAAP3+//j6//f5//r8//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAPj6/87W/AAA + X2duue3y//7+/wAAAPD0/05asBQfidzj/P39/wAAAPX4/6Su6AAAXBccgtff/vv8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPP3/3F8xhYli9Xe/fn6/wAAAAAAAO3y/1pltQAJd9be + /fv8/wAAAPz9/+rw/36I0Bknjs/W+vv8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAPf5/8HI7tnf+/X4//7+/wAAAAAAAO/0/3R7xgAAb9ng/Pz9/wAAAAAAAPn7/+Ln/dLY+fP2//3+ + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//r7//v8//7+/wAAAAAAAAAA + APb4/7/F84eP0e/0//7+/wAAAAAAAP7+//z9//v8//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz9//b5//X4//v8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////w////4 + P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA + AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA + AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v// + /////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/ExtractShadersForm.Designer.cs b/ExtractShadersForm.Designer.cs new file mode 100644 index 0000000..02e997f --- /dev/null +++ b/ExtractShadersForm.Designer.cs @@ -0,0 +1,221 @@ +namespace CodeWalker +{ + partial class ExtractShadersForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExtractShadersForm)); + this.AbortButton = new System.Windows.Forms.Button(); + this.label4 = new System.Windows.Forms.Label(); + this.OutputFolderBrowseButton = new System.Windows.Forms.Button(); + this.OutputFolderTextBox = new System.Windows.Forms.TextBox(); + this.ExtractStatusLabel = new System.Windows.Forms.Label(); + this.ExtractButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.FolderBrowseButton = new System.Windows.Forms.Button(); + this.FolderTextBox = new System.Windows.Forms.TextBox(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.label2 = new System.Windows.Forms.Label(); + this.AsmCheckBox = new System.Windows.Forms.CheckBox(); + this.CsoCheckBox = new System.Windows.Forms.CheckBox(); + this.MetaCheckBox = new System.Windows.Forms.CheckBox(); + this.SuspendLayout(); + // + // AbortButton + // + this.AbortButton.Location = new System.Drawing.Point(188, 99); + this.AbortButton.Name = "AbortButton"; + this.AbortButton.Size = new System.Drawing.Size(75, 23); + this.AbortButton.TabIndex = 72; + this.AbortButton.Text = "Abort"; + this.AbortButton.UseVisualStyleBackColor = true; + this.AbortButton.Click += new System.EventHandler(this.AbortButton_Click); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(15, 41); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(71, 13); + this.label4.TabIndex = 71; + this.label4.Text = "Output folder:"; + // + // OutputFolderBrowseButton + // + this.OutputFolderBrowseButton.Location = new System.Drawing.Point(350, 36); + this.OutputFolderBrowseButton.Name = "OutputFolderBrowseButton"; + this.OutputFolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.OutputFolderBrowseButton.TabIndex = 70; + this.OutputFolderBrowseButton.Text = "..."; + this.OutputFolderBrowseButton.UseVisualStyleBackColor = true; + this.OutputFolderBrowseButton.Click += new System.EventHandler(this.OutputFolderBrowseButton_Click); + // + // OutputFolderTextBox + // + this.OutputFolderTextBox.Location = new System.Drawing.Point(93, 38); + this.OutputFolderTextBox.Name = "OutputFolderTextBox"; + this.OutputFolderTextBox.Size = new System.Drawing.Size(251, 20); + this.OutputFolderTextBox.TabIndex = 69; + this.OutputFolderTextBox.TextChanged += new System.EventHandler(this.OutputFolderTextBox_TextChanged); + // + // ExtractStatusLabel + // + this.ExtractStatusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ExtractStatusLabel.AutoEllipsis = true; + this.ExtractStatusLabel.Location = new System.Drawing.Point(15, 136); + this.ExtractStatusLabel.Name = "ExtractStatusLabel"; + this.ExtractStatusLabel.Size = new System.Drawing.Size(507, 37); + this.ExtractStatusLabel.TabIndex = 68; + this.ExtractStatusLabel.Text = "Initialising..."; + // + // ExtractButton + // + this.ExtractButton.Location = new System.Drawing.Point(93, 99); + this.ExtractButton.Name = "ExtractButton"; + this.ExtractButton.Size = new System.Drawing.Size(75, 23); + this.ExtractButton.TabIndex = 67; + this.ExtractButton.Text = "Extract"; + this.ExtractButton.UseVisualStyleBackColor = true; + this.ExtractButton.Click += new System.EventHandler(this.ExtractButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(15, 15); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(68, 13); + this.label1.TabIndex = 66; + this.label1.Text = "GTAV folder:"; + // + // FolderBrowseButton + // + this.FolderBrowseButton.Location = new System.Drawing.Point(350, 10); + this.FolderBrowseButton.Name = "FolderBrowseButton"; + this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.FolderBrowseButton.TabIndex = 65; + this.FolderBrowseButton.Text = "..."; + this.FolderBrowseButton.UseVisualStyleBackColor = true; + this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click); + // + // FolderTextBox + // + this.FolderTextBox.Location = new System.Drawing.Point(93, 12); + this.FolderTextBox.Name = "FolderTextBox"; + this.FolderTextBox.Size = new System.Drawing.Size(251, 20); + this.FolderTextBox.TabIndex = 64; + this.FolderTextBox.TextChanged += new System.EventHandler(this.FolderTextBox_TextChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(15, 71); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(42, 13); + this.label2.TabIndex = 75; + this.label2.Text = "Output:"; + // + // AsmCheckBox + // + this.AsmCheckBox.AutoSize = true; + this.AsmCheckBox.Checked = true; + this.AsmCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.AsmCheckBox.Location = new System.Drawing.Point(142, 70); + this.AsmCheckBox.Name = "AsmCheckBox"; + this.AsmCheckBox.Size = new System.Drawing.Size(63, 17); + this.AsmCheckBox.TabIndex = 74; + this.AsmCheckBox.Text = "hlsl asm"; + this.AsmCheckBox.UseVisualStyleBackColor = true; + // + // CsoCheckBox + // + this.CsoCheckBox.AutoSize = true; + this.CsoCheckBox.Location = new System.Drawing.Point(93, 70); + this.CsoCheckBox.Name = "CsoCheckBox"; + this.CsoCheckBox.Size = new System.Drawing.Size(43, 17); + this.CsoCheckBox.TabIndex = 73; + this.CsoCheckBox.Text = "cso"; + this.CsoCheckBox.UseVisualStyleBackColor = true; + // + // MetaCheckBox + // + this.MetaCheckBox.AutoSize = true; + this.MetaCheckBox.Checked = true; + this.MetaCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.MetaCheckBox.Location = new System.Drawing.Point(211, 70); + this.MetaCheckBox.Name = "MetaCheckBox"; + this.MetaCheckBox.Size = new System.Drawing.Size(49, 17); + this.MetaCheckBox.TabIndex = 76; + this.MetaCheckBox.Text = "meta"; + this.MetaCheckBox.UseVisualStyleBackColor = true; + // + // ExtractShadersForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(534, 224); + this.Controls.Add(this.MetaCheckBox); + this.Controls.Add(this.label2); + this.Controls.Add(this.AsmCheckBox); + this.Controls.Add(this.CsoCheckBox); + this.Controls.Add(this.AbortButton); + this.Controls.Add(this.label4); + this.Controls.Add(this.OutputFolderBrowseButton); + this.Controls.Add(this.OutputFolderTextBox); + this.Controls.Add(this.ExtractStatusLabel); + this.Controls.Add(this.ExtractButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.FolderBrowseButton); + this.Controls.Add(this.FolderTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "ExtractShadersForm"; + this.Text = "Extract Shaders - CodeWalker by dexyfex"; + this.Load += new System.EventHandler(this.ExtractShadersForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button AbortButton; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button OutputFolderBrowseButton; + private System.Windows.Forms.TextBox OutputFolderTextBox; + private System.Windows.Forms.Label ExtractStatusLabel; + private System.Windows.Forms.Button ExtractButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button FolderBrowseButton; + private System.Windows.Forms.TextBox FolderTextBox; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.CheckBox AsmCheckBox; + private System.Windows.Forms.CheckBox CsoCheckBox; + private System.Windows.Forms.CheckBox MetaCheckBox; + } +} \ No newline at end of file diff --git a/ExtractShadersForm.cs b/ExtractShadersForm.cs new file mode 100644 index 0000000..3669a17 --- /dev/null +++ b/ExtractShadersForm.cs @@ -0,0 +1,225 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class ExtractShadersForm : Form + { + private volatile bool KeysLoaded = false; + private volatile bool InProgress = false; + private volatile bool AbortOperation = false; + + public ExtractShadersForm() + { + InitializeComponent(); + } + + private void ExtractShadersForm_Load(object sender, EventArgs e) + { + FolderTextBox.Text = Settings.Default.GTAFolder; + OutputFolderTextBox.Text = Settings.Default.ExtractedShadersFolder; + + try + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); + KeysLoaded = true; + UpdateExtractStatus("Ready to extract."); + } + catch + { + UpdateExtractStatus("Keys not found! This shouldn't happen."); + } + } + + private void FolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.GTAFolder = FolderTextBox.Text; + } + + private void OutputFolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.ExtractedShadersFolder = OutputFolderTextBox.Text; + } + + private void FolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = Settings.Default.GTAFolder; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + FolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void OutputFolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = OutputFolderTextBox.Text; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + OutputFolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void ExtractButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + + if (!KeysLoaded) + { + MessageBox.Show("Please scan a GTA 5 exe dump for keys first, or include key files in this app's folder!"); + return; + } + if (!Directory.Exists(FolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + FolderTextBox.Text); + return; + } + if (!Directory.Exists(OutputFolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + OutputFolderTextBox.Text); + return; + } + //if (Directory.GetFiles(OutputFolderTextBox.Text, "*.ysc", SearchOption.AllDirectories).Length > 0) + //{ + // if (MessageBox.Show("Output folder already contains .ysc files. Are you sure you want to continue?", "Output folder already contains .ysc files", MessageBoxButtons.OKCancel) != DialogResult.OK) + // { + // return; + // } + //} + + InProgress = true; + AbortOperation = false; + + string searchpath = FolderTextBox.Text; + string outputpath = OutputFolderTextBox.Text; + string replpath = searchpath + "\\"; + + bool cso = CsoCheckBox.Checked; + bool asm = AsmCheckBox.Checked; + bool meta = MetaCheckBox.Checked; + + Task.Run(() => + { + + UpdateExtractStatus("Keys loaded."); + + + + RpfManager rpfman = new RpfManager(); + rpfman.Init(searchpath, UpdateExtractStatus, UpdateExtractStatus); + + + UpdateExtractStatus("Beginning shader extraction..."); + StringBuilder errsb = new StringBuilder(); + foreach (RpfFile rpf in rpfman.AllRpfs) + { + foreach (RpfEntry entry in rpf.AllEntries) + { + if (AbortOperation) + { + UpdateExtractStatus("Operation aborted"); + InProgress = false; + return; + } + try + { + if (entry.NameLower.EndsWith(".fxc")) + { + UpdateExtractStatus(entry.Path); + FxcFile fxc = rpfman.GetFile(entry); + if (fxc == null) throw new Exception("Couldn't load file."); + + string basepath = outputpath + "\\" + rpf.Name.Replace(".rpf", ""); + + + if (!Directory.Exists(basepath)) + { + Directory.CreateDirectory(basepath); + } + + string pleft = entry.Path.Substring(0, entry.Path.Length - (entry.Name.Length + 1)); + string ppart = pleft.Substring(pleft.LastIndexOf('\\')); + string opath = basepath + ppart; + + if (!Directory.Exists(opath)) + { + Directory.CreateDirectory(opath); + } + + string obase = opath + "\\" + entry.Name; + + foreach (var shader in fxc.Shaders) + { + string filebase = obase + "_" + shader.Name; + if (cso) + { + string csofile = filebase + ".cso"; + File.WriteAllBytes(csofile, shader.ByteCode); + } + if (asm) + { + string asmfile = filebase + ".hlsl"; + File.WriteAllText(asmfile, shader.Disassembly); + } + } + + if (meta) + { + string metafile = obase + ".meta.txt"; + string metastr = fxc.GetMetaString(); + File.WriteAllText(metafile, metastr); + } + + } + } + catch (Exception ex) + { + string err = entry.Name + ": " + ex.Message; + UpdateExtractStatus(err); + errsb.AppendLine(err); + } + + } + } + + File.WriteAllText(outputpath + "\\_errors.txt", errsb.ToString()); + + UpdateExtractStatus("Complete."); + InProgress = false; + }); + } + + private void AbortButton_Click(object sender, EventArgs e) + { + AbortOperation = true; + } + + private void UpdateExtractStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { UpdateExtractStatus(text); })); + } + else + { + ExtractStatusLabel.Text = text; + } + } + catch { } + } + + } +} diff --git a/ExtractShadersForm.resx b/ExtractShadersForm.resx new file mode 100644 index 0000000..bd12579 --- /dev/null +++ b/ExtractShadersForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/ExtractTexForm.Designer.cs b/ExtractTexForm.Designer.cs new file mode 100644 index 0000000..1599947 --- /dev/null +++ b/ExtractTexForm.Designer.cs @@ -0,0 +1,236 @@ +namespace CodeWalker +{ + partial class ExtractTexForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExtractTexForm)); + this.label4 = new System.Windows.Forms.Label(); + this.OutputFolderBrowseButton = new System.Windows.Forms.Button(); + this.OutputFolderTextBox = new System.Windows.Forms.TextBox(); + this.ExtractStatusLabel = new System.Windows.Forms.Label(); + this.ExtractButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.FolderBrowseButton = new System.Windows.Forms.Button(); + this.FolderTextBox = new System.Windows.Forms.TextBox(); + this.AbortButton = new System.Windows.Forms.Button(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.YtdChecBox = new System.Windows.Forms.CheckBox(); + this.YdrCheckBox = new System.Windows.Forms.CheckBox(); + this.YddCheckBox = new System.Windows.Forms.CheckBox(); + this.YftCheckBox = new System.Windows.Forms.CheckBox(); + this.label2 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(12, 35); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(71, 13); + this.label4.TabIndex = 62; + this.label4.Text = "Output folder:"; + // + // OutputFolderBrowseButton + // + this.OutputFolderBrowseButton.Location = new System.Drawing.Point(347, 30); + this.OutputFolderBrowseButton.Name = "OutputFolderBrowseButton"; + this.OutputFolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.OutputFolderBrowseButton.TabIndex = 61; + this.OutputFolderBrowseButton.Text = "..."; + this.OutputFolderBrowseButton.UseVisualStyleBackColor = true; + this.OutputFolderBrowseButton.Click += new System.EventHandler(this.OutputFolderBrowseButton_Click); + // + // OutputFolderTextBox + // + this.OutputFolderTextBox.Location = new System.Drawing.Point(90, 32); + this.OutputFolderTextBox.Name = "OutputFolderTextBox"; + this.OutputFolderTextBox.Size = new System.Drawing.Size(251, 20); + this.OutputFolderTextBox.TabIndex = 60; + this.OutputFolderTextBox.TextChanged += new System.EventHandler(this.OutputFolderTextBox_TextChanged); + // + // ExtractStatusLabel + // + this.ExtractStatusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ExtractStatusLabel.AutoEllipsis = true; + this.ExtractStatusLabel.Location = new System.Drawing.Point(12, 130); + this.ExtractStatusLabel.Name = "ExtractStatusLabel"; + this.ExtractStatusLabel.Size = new System.Drawing.Size(501, 65); + this.ExtractStatusLabel.TabIndex = 59; + this.ExtractStatusLabel.Text = "Initialising..."; + // + // ExtractButton + // + this.ExtractButton.Location = new System.Drawing.Point(90, 93); + this.ExtractButton.Name = "ExtractButton"; + this.ExtractButton.Size = new System.Drawing.Size(75, 23); + this.ExtractButton.TabIndex = 58; + this.ExtractButton.Text = "Extract"; + this.ExtractButton.UseVisualStyleBackColor = true; + this.ExtractButton.Click += new System.EventHandler(this.ExtractButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(68, 13); + this.label1.TabIndex = 57; + this.label1.Text = "GTAV folder:"; + // + // FolderBrowseButton + // + this.FolderBrowseButton.Location = new System.Drawing.Point(347, 4); + this.FolderBrowseButton.Name = "FolderBrowseButton"; + this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.FolderBrowseButton.TabIndex = 56; + this.FolderBrowseButton.Text = "..."; + this.FolderBrowseButton.UseVisualStyleBackColor = true; + this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click); + // + // FolderTextBox + // + this.FolderTextBox.Location = new System.Drawing.Point(90, 6); + this.FolderTextBox.Name = "FolderTextBox"; + this.FolderTextBox.Size = new System.Drawing.Size(251, 20); + this.FolderTextBox.TabIndex = 55; + this.FolderTextBox.TextChanged += new System.EventHandler(this.FolderTextBox_TextChanged); + // + // AbortButton + // + this.AbortButton.Location = new System.Drawing.Point(185, 93); + this.AbortButton.Name = "AbortButton"; + this.AbortButton.Size = new System.Drawing.Size(75, 23); + this.AbortButton.TabIndex = 63; + this.AbortButton.Text = "Abort"; + this.AbortButton.UseVisualStyleBackColor = true; + this.AbortButton.Click += new System.EventHandler(this.AbortButton_Click); + // + // YtdChecBox + // + this.YtdChecBox.AutoSize = true; + this.YtdChecBox.Location = new System.Drawing.Point(90, 64); + this.YtdChecBox.Name = "YtdChecBox"; + this.YtdChecBox.Size = new System.Drawing.Size(40, 17); + this.YtdChecBox.TabIndex = 64; + this.YtdChecBox.Text = "ytd"; + this.YtdChecBox.UseVisualStyleBackColor = true; + // + // YdrCheckBox + // + this.YdrCheckBox.AutoSize = true; + this.YdrCheckBox.Checked = true; + this.YdrCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.YdrCheckBox.Location = new System.Drawing.Point(136, 64); + this.YdrCheckBox.Name = "YdrCheckBox"; + this.YdrCheckBox.Size = new System.Drawing.Size(40, 17); + this.YdrCheckBox.TabIndex = 65; + this.YdrCheckBox.Text = "ydr"; + this.YdrCheckBox.UseVisualStyleBackColor = true; + // + // YddCheckBox + // + this.YddCheckBox.AutoSize = true; + this.YddCheckBox.Checked = true; + this.YddCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.YddCheckBox.Location = new System.Drawing.Point(182, 64); + this.YddCheckBox.Name = "YddCheckBox"; + this.YddCheckBox.Size = new System.Drawing.Size(43, 17); + this.YddCheckBox.TabIndex = 66; + this.YddCheckBox.Text = "ydd"; + this.YddCheckBox.UseVisualStyleBackColor = true; + // + // YftCheckBox + // + this.YftCheckBox.AutoSize = true; + this.YftCheckBox.Checked = true; + this.YftCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.YftCheckBox.Location = new System.Drawing.Point(231, 64); + this.YftCheckBox.Name = "YftCheckBox"; + this.YftCheckBox.Size = new System.Drawing.Size(37, 17); + this.YftCheckBox.TabIndex = 67; + this.YftCheckBox.Text = "yft"; + this.YftCheckBox.UseVisualStyleBackColor = true; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 65); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(54, 13); + this.label2.TabIndex = 68; + this.label2.Text = "From files:"; + // + // ExtractTexForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(525, 236); + this.Controls.Add(this.label2); + this.Controls.Add(this.YftCheckBox); + this.Controls.Add(this.YddCheckBox); + this.Controls.Add(this.YdrCheckBox); + this.Controls.Add(this.YtdChecBox); + this.Controls.Add(this.AbortButton); + this.Controls.Add(this.label4); + this.Controls.Add(this.OutputFolderBrowseButton); + this.Controls.Add(this.OutputFolderTextBox); + this.Controls.Add(this.ExtractStatusLabel); + this.Controls.Add(this.ExtractButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.FolderBrowseButton); + this.Controls.Add(this.FolderTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "ExtractTexForm"; + this.Text = "Extract Textures - CodeWalker by dexyfex"; + this.Load += new System.EventHandler(this.ExtractTexForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button OutputFolderBrowseButton; + private System.Windows.Forms.TextBox OutputFolderTextBox; + private System.Windows.Forms.Label ExtractStatusLabel; + private System.Windows.Forms.Button ExtractButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button FolderBrowseButton; + private System.Windows.Forms.TextBox FolderTextBox; + private System.Windows.Forms.Button AbortButton; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.CheckBox YtdChecBox; + private System.Windows.Forms.CheckBox YdrCheckBox; + private System.Windows.Forms.CheckBox YddCheckBox; + private System.Windows.Forms.CheckBox YftCheckBox; + private System.Windows.Forms.Label label2; + } +} \ No newline at end of file diff --git a/ExtractTexForm.cs b/ExtractTexForm.cs new file mode 100644 index 0000000..42df42c --- /dev/null +++ b/ExtractTexForm.cs @@ -0,0 +1,276 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using CodeWalker.Utils; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class ExtractTexForm : Form + { + private volatile bool KeysLoaded = false; + private volatile bool InProgress = false; + private volatile bool AbortOperation = false; + + public ExtractTexForm() + { + InitializeComponent(); + } + + private void ExtractTexForm_Load(object sender, EventArgs e) + { + FolderTextBox.Text = Settings.Default.GTAFolder; + OutputFolderTextBox.Text = Settings.Default.ExtractedTexturesFolder; + + try + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); + KeysLoaded = true; + UpdateExtractStatus("Ready to extract."); + } + catch + { + UpdateExtractStatus("Keys not found! This shouldn't happen."); + } + } + + private void FolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.GTAFolder = FolderTextBox.Text; + } + + private void OutputFolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.ExtractedTexturesFolder = OutputFolderTextBox.Text; + } + + private void FolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = Settings.Default.GTAFolder; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + FolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void OutputFolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = OutputFolderTextBox.Text; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + OutputFolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + + private void UpdateExtractStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { UpdateExtractStatus(text); })); + } + else + { + ExtractStatusLabel.Text = text; + } + } + catch { } + } + + private void ExtractButton_Click(object sender, EventArgs e) + { + if (InProgress) return; + + if (!KeysLoaded) + { + MessageBox.Show("Please scan a GTA 5 exe dump for keys first, or include key files in this app's folder!"); + return; + } + if (!Directory.Exists(FolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + FolderTextBox.Text); + return; + } + if (!Directory.Exists(OutputFolderTextBox.Text)) + { + MessageBox.Show("Folder doesn't exist: " + OutputFolderTextBox.Text); + return; + } + //if (Directory.GetFiles(OutputFolderTextBox.Text, "*.ysc", SearchOption.AllDirectories).Length > 0) + //{ + // if (MessageBox.Show("Output folder already contains .ysc files. Are you sure you want to continue?", "Output folder already contains .ysc files", MessageBoxButtons.OKCancel) != DialogResult.OK) + // { + // return; + // } + //} + + InProgress = true; + AbortOperation = false; + + string searchpath = FolderTextBox.Text; + string outputpath = OutputFolderTextBox.Text; + string replpath = searchpath + "\\"; + bool bytd = YtdChecBox.Checked; + bool bydr = YdrCheckBox.Checked; + bool bydd = YddCheckBox.Checked; + bool byft = YftCheckBox.Checked; + + Task.Run(() => + { + + UpdateExtractStatus("Keys loaded."); + + + + RpfManager rpfman = new RpfManager(); + rpfman.Init(searchpath, UpdateExtractStatus, UpdateExtractStatus); + + + UpdateExtractStatus("Beginning texture extraction..."); + StringBuilder errsb = new StringBuilder(); + foreach (RpfFile rpf in rpfman.AllRpfs) + { + foreach (RpfEntry entry in rpf.AllEntries) + { + if (AbortOperation) + { + UpdateExtractStatus("Operation aborted"); + InProgress = false; + return; + } + try + { + if (bytd && entry.NameLower.EndsWith(".ytd")) + { + UpdateExtractStatus(entry.Path); + YtdFile ytd = rpfman.GetFile(entry); + if (ytd == null) throw new Exception("Couldn't load file."); + if (ytd.TextureDict == null) throw new Exception("Couldn't load texture dictionary."); + if (ytd.TextureDict.Textures == null) throw new Exception("Couldn't load texture dictionary texture array."); + if (ytd.TextureDict.Textures.data_items == null) throw new Exception("Texture dictionary had no entries..."); + foreach (var tex in ytd.TextureDict.Textures.data_items) + { + SaveTexture(tex, entry, outputpath); + } + } + else if (bydr && entry.NameLower.EndsWith(".ydr")) + { + UpdateExtractStatus(entry.Path); + YdrFile ydr = rpfman.GetFile(entry); + if (ydr == null) throw new Exception("Couldn't load file."); + if (ydr.Drawable == null) throw new Exception("Couldn't load drawable."); + if (ydr.Drawable.ShaderGroup != null) + { + var ydrtd = ydr.Drawable.ShaderGroup.TextureDictionary; + if ((ydrtd != null) && (ydrtd.Textures != null) && (ydrtd.Textures.data_items != null)) + { + foreach (var tex in ydrtd.Textures.data_items) + { + SaveTexture(tex, entry, outputpath); + } + } + } + } + else if (bydd && entry.NameLower.EndsWith(".ydd")) + { + UpdateExtractStatus(entry.Path); + YddFile ydd = rpfman.GetFile(entry); + if (ydd == null) throw new Exception("Couldn't load file."); + //if (ydd.DrawableDict == null) throw new Exception("Couldn't load drawable dictionary."); + //if (ydd.DrawableDict.Drawables == null) throw new Exception("Drawable dictionary had no items..."); + //if (ydd.DrawableDict.Drawables.data_items == null) throw new Exception("Drawable dictionary had no items..."); + if ((ydd.Dict==null)||(ydd.Dict.Count==0)) throw new Exception("Drawable dictionary had no items..."); + foreach (var drawable in ydd.Dict.Values) + { + if (drawable.ShaderGroup != null) + { + var ydrtd = drawable.ShaderGroup.TextureDictionary; + if ((ydrtd != null) && (ydrtd.Textures != null) && (ydrtd.Textures.data_items != null)) + { + foreach (var tex in ydrtd.Textures.data_items) + { + SaveTexture(tex, entry, outputpath); + } + } + } + } + } + else if (byft && entry.NameLower.EndsWith(".yft")) + { + UpdateExtractStatus(entry.Path); + YftFile yft = rpfman.GetFile(entry); + if (yft == null) throw new Exception("Couldn't load file."); + if (yft.Fragment == null) throw new Exception("Couldn't load fragment."); + if (yft.Fragment.Drawable != null) + { + if (yft.Fragment.Drawable.ShaderGroup != null) + { + var ydrtd = yft.Fragment.Drawable.ShaderGroup.TextureDictionary; + if ((ydrtd != null) && (ydrtd.Textures != null) && (ydrtd.Textures.data_items != null)) + { + foreach (var tex in ydrtd.Textures.data_items) + { + SaveTexture(tex, entry, outputpath); + } + } + } + } + } + } + catch (Exception ex) + { + string err = entry.Name + ": " + ex.Message; + UpdateExtractStatus(err); + errsb.AppendLine(err); + } + + } + } + + File.WriteAllText(outputpath + "\\_errors.txt", errsb.ToString()); + + UpdateExtractStatus("Complete."); + InProgress = false; + }); + } + + private void SaveTexture(Texture tex, RpfEntry entry, string folder) + { + + //DirectXTex + + byte[] dds = DDSIO.GetDDSFile(tex); + + string bpath = folder + "\\" + entry.Name + "_" + tex.Name; + string fpath = bpath + ".dds"; + int c = 1; + while (File.Exists(fpath)) + { + fpath = bpath + "_Copy" + c.ToString() + ".dds"; + c++; + } + + File.WriteAllBytes(fpath, dds); + + } + + + private void AbortButton_Click(object sender, EventArgs e) + { + AbortOperation = true; + } + + } +} diff --git a/ExtractTexForm.resx b/ExtractTexForm.resx new file mode 100644 index 0000000..bd12579 --- /dev/null +++ b/ExtractTexForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/AwcForm.Designer.cs b/Forms/AwcForm.Designer.cs new file mode 100644 index 0000000..cfee778 --- /dev/null +++ b/Forms/AwcForm.Designer.cs @@ -0,0 +1,254 @@ +namespace CodeWalker.Forms +{ + partial class AwcForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AwcForm)); + this.MainTabControl = new System.Windows.Forms.TabControl(); + this.PlayerTabPage = new System.Windows.Forms.TabPage(); + this.PrevButton = new System.Windows.Forms.Button(); + this.NextButton = new System.Windows.Forms.Button(); + this.VolumeButton = new System.Windows.Forms.Button(); + this.PlayButton = new System.Windows.Forms.Button(); + this.PlayListView = new System.Windows.Forms.ListView(); + this.PlaylistNameHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.PlaylistTypeHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.PlaylistLengthHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.VolumeTrackBar = new System.Windows.Forms.TrackBar(); + this.PositionTrackBar = new System.Windows.Forms.TrackBar(); + this.DetailsTabPage = new System.Windows.Forms.TabPage(); + this.DetailsPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.label1 = new System.Windows.Forms.Label(); + this.MainTabControl.SuspendLayout(); + this.PlayerTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.VolumeTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PositionTrackBar)).BeginInit(); + this.DetailsTabPage.SuspendLayout(); + this.SuspendLayout(); + // + // MainTabControl + // + this.MainTabControl.Controls.Add(this.PlayerTabPage); + this.MainTabControl.Controls.Add(this.DetailsTabPage); + this.MainTabControl.Dock = System.Windows.Forms.DockStyle.Fill; + this.MainTabControl.Location = new System.Drawing.Point(0, 0); + this.MainTabControl.Name = "MainTabControl"; + this.MainTabControl.SelectedIndex = 0; + this.MainTabControl.Size = new System.Drawing.Size(576, 358); + this.MainTabControl.TabIndex = 0; + // + // PlayerTabPage + // + this.PlayerTabPage.Controls.Add(this.label1); + this.PlayerTabPage.Controls.Add(this.PrevButton); + this.PlayerTabPage.Controls.Add(this.NextButton); + this.PlayerTabPage.Controls.Add(this.VolumeButton); + this.PlayerTabPage.Controls.Add(this.PlayButton); + this.PlayerTabPage.Controls.Add(this.PlayListView); + this.PlayerTabPage.Controls.Add(this.VolumeTrackBar); + this.PlayerTabPage.Controls.Add(this.PositionTrackBar); + this.PlayerTabPage.Location = new System.Drawing.Point(4, 22); + this.PlayerTabPage.Name = "PlayerTabPage"; + this.PlayerTabPage.Padding = new System.Windows.Forms.Padding(3); + this.PlayerTabPage.Size = new System.Drawing.Size(568, 332); + this.PlayerTabPage.TabIndex = 0; + this.PlayerTabPage.Text = "Player"; + this.PlayerTabPage.UseVisualStyleBackColor = true; + // + // PrevButton + // + this.PrevButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.PrevButton.Location = new System.Drawing.Point(137, 301); + this.PrevButton.Name = "PrevButton"; + this.PrevButton.Size = new System.Drawing.Size(31, 23); + this.PrevButton.TabIndex = 2; + this.PrevButton.Text = "<<"; + this.PrevButton.UseVisualStyleBackColor = true; + this.PrevButton.Click += new System.EventHandler(this.PrevButton_Click); + // + // NextButton + // + this.NextButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.NextButton.Location = new System.Drawing.Point(255, 301); + this.NextButton.Name = "NextButton"; + this.NextButton.Size = new System.Drawing.Size(31, 23); + this.NextButton.TabIndex = 4; + this.NextButton.Text = ">>"; + this.NextButton.UseVisualStyleBackColor = true; + this.NextButton.Click += new System.EventHandler(this.NextButton_Click); + // + // VolumeButton + // + this.VolumeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.VolumeButton.Location = new System.Drawing.Point(426, 301); + this.VolumeButton.Name = "VolumeButton"; + this.VolumeButton.Size = new System.Drawing.Size(33, 23); + this.VolumeButton.TabIndex = 5; + this.VolumeButton.Text = "Vol"; + this.VolumeButton.UseVisualStyleBackColor = true; + this.VolumeButton.Click += new System.EventHandler(this.VolumeButton_Click); + // + // PlayButton + // + this.PlayButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.PlayButton.Location = new System.Drawing.Point(174, 301); + this.PlayButton.Name = "PlayButton"; + this.PlayButton.Size = new System.Drawing.Size(75, 23); + this.PlayButton.TabIndex = 3; + this.PlayButton.Text = "Play/Pause"; + this.PlayButton.UseVisualStyleBackColor = true; + this.PlayButton.Click += new System.EventHandler(this.PlayButton_Click); + // + // PlayListView + // + this.PlayListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.PlayListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.PlaylistNameHeader, + this.PlaylistTypeHeader, + this.PlaylistLengthHeader}); + this.PlayListView.FullRowSelect = true; + this.PlayListView.HideSelection = false; + this.PlayListView.Location = new System.Drawing.Point(6, 6); + this.PlayListView.Name = "PlayListView"; + this.PlayListView.Size = new System.Drawing.Size(556, 216); + this.PlayListView.TabIndex = 0; + this.PlayListView.UseCompatibleStateImageBehavior = false; + this.PlayListView.View = System.Windows.Forms.View.Details; + // + // PlaylistNameHeader + // + this.PlaylistNameHeader.Text = "Name"; + this.PlaylistNameHeader.Width = 303; + // + // PlaylistTypeHeader + // + this.PlaylistTypeHeader.Text = "Type"; + this.PlaylistTypeHeader.Width = 110; + // + // PlaylistLengthHeader + // + this.PlaylistLengthHeader.Text = "Length"; + this.PlaylistLengthHeader.Width = 110; + // + // VolumeTrackBar + // + this.VolumeTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.VolumeTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.VolumeTrackBar.LargeChange = 10; + this.VolumeTrackBar.Location = new System.Drawing.Point(455, 301); + this.VolumeTrackBar.Maximum = 100; + this.VolumeTrackBar.Name = "VolumeTrackBar"; + this.VolumeTrackBar.Size = new System.Drawing.Size(105, 45); + this.VolumeTrackBar.TabIndex = 6; + this.VolumeTrackBar.TickStyle = System.Windows.Forms.TickStyle.None; + this.VolumeTrackBar.Value = 50; + this.VolumeTrackBar.Scroll += new System.EventHandler(this.VolumeTrackBar_Scroll); + // + // PositionTrackBar + // + this.PositionTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.PositionTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.PositionTrackBar.LargeChange = 50; + this.PositionTrackBar.Location = new System.Drawing.Point(6, 263); + this.PositionTrackBar.Maximum = 1000; + this.PositionTrackBar.Name = "PositionTrackBar"; + this.PositionTrackBar.Size = new System.Drawing.Size(554, 45); + this.PositionTrackBar.TabIndex = 1; + this.PositionTrackBar.TickStyle = System.Windows.Forms.TickStyle.None; + this.PositionTrackBar.Scroll += new System.EventHandler(this.PositionTrackBar_Scroll); + // + // DetailsTabPage + // + this.DetailsTabPage.Controls.Add(this.DetailsPropertyGrid); + this.DetailsTabPage.Location = new System.Drawing.Point(4, 22); + this.DetailsTabPage.Name = "DetailsTabPage"; + this.DetailsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.DetailsTabPage.Size = new System.Drawing.Size(568, 332); + this.DetailsTabPage.TabIndex = 1; + this.DetailsTabPage.Text = "Details"; + this.DetailsTabPage.UseVisualStyleBackColor = true; + // + // DetailsPropertyGrid + // + this.DetailsPropertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.DetailsPropertyGrid.HelpVisible = false; + this.DetailsPropertyGrid.Location = new System.Drawing.Point(3, 3); + this.DetailsPropertyGrid.Name = "DetailsPropertyGrid"; + this.DetailsPropertyGrid.Size = new System.Drawing.Size(562, 326); + this.DetailsPropertyGrid.TabIndex = 0; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(44, 238); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(248, 13); + this.label1.TabIndex = 7; + this.label1.Text = "NOTE: Work in progress... Audio does not play yet!"; + // + // AwcForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(576, 358); + this.Controls.Add(this.MainTabControl); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "AwcForm"; + this.Text = "AWC Player - CodeWalker by dexyfex"; + this.MainTabControl.ResumeLayout(false); + this.PlayerTabPage.ResumeLayout(false); + this.PlayerTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.VolumeTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PositionTrackBar)).EndInit(); + this.DetailsTabPage.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TabControl MainTabControl; + private System.Windows.Forms.TabPage PlayerTabPage; + private System.Windows.Forms.TabPage DetailsTabPage; + private WinForms.PropertyGridFix DetailsPropertyGrid; + private System.Windows.Forms.ListView PlayListView; + private System.Windows.Forms.ColumnHeader PlaylistNameHeader; + private System.Windows.Forms.ColumnHeader PlaylistTypeHeader; + private System.Windows.Forms.ColumnHeader PlaylistLengthHeader; + private System.Windows.Forms.Button PrevButton; + private System.Windows.Forms.Button NextButton; + private System.Windows.Forms.Button VolumeButton; + private System.Windows.Forms.Button PlayButton; + private System.Windows.Forms.TrackBar VolumeTrackBar; + private System.Windows.Forms.TrackBar PositionTrackBar; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/Forms/AwcForm.cs b/Forms/AwcForm.cs new file mode 100644 index 0000000..3b754bf --- /dev/null +++ b/Forms/AwcForm.cs @@ -0,0 +1,196 @@ +using CodeWalker.GameFiles; +using SharpDX.Multimedia; +using SharpDX.XAudio2; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class AwcForm : Form + { + public AwcFile Awc { get; set; } + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + private bool Playing = false; + + + public AwcForm() + { + InitializeComponent(); + } + + + + private void UpdateFormTitle() + { + Text = fileName + " - AWC Player - CodeWalker by dexyfex"; + } + + + public void LoadAwc(AwcFile awc) + { + Awc = awc; + DetailsPropertyGrid.SelectedObject = awc; + + //MainTabControl.SelectedTab = DetailsTabPage;//remove this + + fileName = awc?.Name; + if (string.IsNullOrEmpty(fileName)) + { + fileName = awc?.FileEntry?.Name; + } + + + PlayListView.Items.Clear(); + if (awc.Audios != null) + { + foreach (var audio in awc.Audios) + { + var item = PlayListView.Items.Add(audio.Name); + item.SubItems.Add(audio.Type); + item.SubItems.Add(audio.LengthStr); + item.Tag = audio; + } + } + + UpdateFormTitle(); + } + + + private void Play() + { + if (PlayListView.SelectedItems.Count != 1) return; + + var item = PlayListView.SelectedItems[0]; + var audio = item.Tag as AwcAudio; + + if (audio == null) return; + + + + //see https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/XAudio2/PlaySound/Program.cs + //see https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/XAudio2/AudioPlayerApp/AudioPlayer.cs + + //var mstrm = new MemoryStream(audio.Data); + //var sstrm = new SoundStream(mstrm); + //SourceVoice sv=new SourceVoice() + var mstrm = audio.GetWavStream(); + + ////var mdata = ((MemoryStream)mstrm).GetBuffer(); + ////File.WriteAllBytes("C:\\test2.wav", mdata); + ////return; + + //var sstrm = new SoundStream(mstrm); + //var waveFormat = sstrm.Format; + //var buffer = new AudioBuffer + //{ + // Stream = sstrm.ToDataStream(), + // AudioBytes = (int)sstrm.Length, + // Flags = BufferFlags.EndOfStream + //}; + //sstrm.Close(); + + + //var xaudio2 = new XAudio2();//cache this... + //var masteringVoice = new MasteringVoice(xaudio2);//cache this... + //var sourceVoice = new SourceVoice(xaudio2, waveFormat, true); + ////sourceVoice.BufferEnd += (context) => Console.WriteLine(" => event received: end of buffer"); + //sourceVoice.SubmitSourceBuffer(buffer, sstrm.DecodedPacketsInfo); + //sourceVoice.Start(); + //while (sourceVoice.State.BuffersQueued > 0) // && !IsKeyPressed(ConsoleKey.Escape)) + //{ + // Thread.Sleep(10); + //} + //sourceVoice.DestroyVoice(); + //sourceVoice.Dispose(); + //buffer.Stream.Dispose(); + + //masteringVoice.Dispose();//on form exit? + //xaudio2.Dispose();//on form exit? + + + + Playing = true; + } + + private void Pause() + { + + Playing = false; + } + + private void Prev() + { + } + + private void Next() + { + } + + + + private void PositionTrackBar_Scroll(object sender, EventArgs e) + { + + } + + private void PlayButton_Click(object sender, EventArgs e) + { + if (Playing) Pause(); + else Play(); + } + + private void PrevButton_Click(object sender, EventArgs e) + { + Prev(); + } + + private void NextButton_Click(object sender, EventArgs e) + { + Next(); + } + + private void VolumeButton_Click(object sender, EventArgs e) + { + + } + + private void VolumeTrackBar_Scroll(object sender, EventArgs e) + { + + } + } + + + + + + + public class AudioPlayer + { + + } + + + +} diff --git a/Forms/AwcForm.resx b/Forms/AwcForm.resx new file mode 100644 index 0000000..1431f6b --- /dev/null +++ b/Forms/AwcForm.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/FxcForm.Designer.cs b/Forms/FxcForm.Designer.cs new file mode 100644 index 0000000..225b6cb --- /dev/null +++ b/Forms/FxcForm.Designer.cs @@ -0,0 +1,379 @@ +namespace CodeWalker.Forms +{ + partial class FxcForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FxcForm)); + this.MainTabControl = new System.Windows.Forms.TabControl(); + this.ShadersTabPage = new System.Windows.Forms.TabPage(); + this.DetailsTabPage = new System.Windows.Forms.TabPage(); + this.DetailsPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.ShaderPanel = new System.Windows.Forms.Panel(); + this.ShadersListView = new System.Windows.Forms.ListView(); + this.ShadersNameColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.ShaderTextBox = new FastColoredTextBoxNS.FastColoredTextBox(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.TechniquesTabPage = new System.Windows.Forms.TabPage(); + this.splitContainer2 = new System.Windows.Forms.SplitContainer(); + this.TechniquesListView = new System.Windows.Forms.ListView(); + this.TechniquesNameColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.TechniquePanel = new System.Windows.Forms.Panel(); + this.TechniqueTextBox = new FastColoredTextBoxNS.FastColoredTextBox(); + this.MainTabControl.SuspendLayout(); + this.ShadersTabPage.SuspendLayout(); + this.DetailsTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.ShaderPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ShaderTextBox)).BeginInit(); + this.statusStrip1.SuspendLayout(); + this.TechniquesTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); + this.splitContainer2.Panel1.SuspendLayout(); + this.splitContainer2.Panel2.SuspendLayout(); + this.splitContainer2.SuspendLayout(); + this.TechniquePanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.TechniqueTextBox)).BeginInit(); + this.SuspendLayout(); + // + // MainTabControl + // + this.MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTabControl.Controls.Add(this.ShadersTabPage); + this.MainTabControl.Controls.Add(this.TechniquesTabPage); + this.MainTabControl.Controls.Add(this.DetailsTabPage); + this.MainTabControl.Location = new System.Drawing.Point(2, 3); + this.MainTabControl.Name = "MainTabControl"; + this.MainTabControl.SelectedIndex = 0; + this.MainTabControl.Size = new System.Drawing.Size(784, 480); + this.MainTabControl.TabIndex = 0; + // + // ShadersTabPage + // + this.ShadersTabPage.Controls.Add(this.splitContainer1); + this.ShadersTabPage.Location = new System.Drawing.Point(4, 22); + this.ShadersTabPage.Name = "ShadersTabPage"; + this.ShadersTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ShadersTabPage.Size = new System.Drawing.Size(776, 454); + this.ShadersTabPage.TabIndex = 0; + this.ShadersTabPage.Text = "Shaders"; + this.ShadersTabPage.UseVisualStyleBackColor = true; + // + // DetailsTabPage + // + this.DetailsTabPage.Controls.Add(this.DetailsPropertyGrid); + this.DetailsTabPage.Location = new System.Drawing.Point(4, 22); + this.DetailsTabPage.Name = "DetailsTabPage"; + this.DetailsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.DetailsTabPage.Size = new System.Drawing.Size(776, 454); + this.DetailsTabPage.TabIndex = 1; + this.DetailsTabPage.Text = "Details"; + this.DetailsTabPage.UseVisualStyleBackColor = true; + // + // DetailsPropertyGrid + // + this.DetailsPropertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.DetailsPropertyGrid.HelpVisible = false; + this.DetailsPropertyGrid.Location = new System.Drawing.Point(3, 3); + this.DetailsPropertyGrid.Name = "DetailsPropertyGrid"; + this.DetailsPropertyGrid.Size = new System.Drawing.Size(770, 448); + this.DetailsPropertyGrid.TabIndex = 1; + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer1.Location = new System.Drawing.Point(3, 3); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.ShadersListView); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.ShaderPanel); + this.splitContainer1.Size = new System.Drawing.Size(770, 448); + this.splitContainer1.SplitterDistance = 235; + this.splitContainer1.TabIndex = 0; + // + // ShaderPanel + // + this.ShaderPanel.Controls.Add(this.ShaderTextBox); + this.ShaderPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.ShaderPanel.Enabled = false; + this.ShaderPanel.Location = new System.Drawing.Point(0, 0); + this.ShaderPanel.Name = "ShaderPanel"; + this.ShaderPanel.Size = new System.Drawing.Size(531, 448); + this.ShaderPanel.TabIndex = 0; + // + // ShadersListView + // + this.ShadersListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.ShadersNameColumn}); + this.ShadersListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.ShadersListView.FullRowSelect = true; + this.ShadersListView.HideSelection = false; + this.ShadersListView.Location = new System.Drawing.Point(0, 0); + this.ShadersListView.MultiSelect = false; + this.ShadersListView.Name = "ShadersListView"; + this.ShadersListView.Size = new System.Drawing.Size(235, 448); + this.ShadersListView.TabIndex = 0; + this.ShadersListView.UseCompatibleStateImageBehavior = false; + this.ShadersListView.View = System.Windows.Forms.View.Details; + this.ShadersListView.SelectedIndexChanged += new System.EventHandler(this.ShadersListView_SelectedIndexChanged); + // + // ShadersNameColumn + // + this.ShadersNameColumn.Text = "Name"; + this.ShadersNameColumn.Width = 208; + // + // ShaderTextBox + // + this.ShaderTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ShaderTextBox.AutoCompleteBracketsList = new char[] { + '(', + ')', + '{', + '}', + '[', + ']', + '\"', + '\"', + '\'', + '\''}; + this.ShaderTextBox.AutoIndentChars = false; + this.ShaderTextBox.AutoIndentCharsPatterns = ""; + this.ShaderTextBox.AutoIndentExistingLines = false; + this.ShaderTextBox.AutoScrollMinSize = new System.Drawing.Size(27, 14); + this.ShaderTextBox.BackBrush = null; + this.ShaderTextBox.CharHeight = 14; + this.ShaderTextBox.CharWidth = 8; + this.ShaderTextBox.CommentPrefix = null; + this.ShaderTextBox.Cursor = System.Windows.Forms.Cursors.IBeam; + this.ShaderTextBox.DelayedEventsInterval = 10; + this.ShaderTextBox.DisabledColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180))))); + this.ShaderTextBox.IsReplaceMode = false; + this.ShaderTextBox.Language = FastColoredTextBoxNS.Language.CSharp; + this.ShaderTextBox.LeftBracket = '<'; + this.ShaderTextBox.LeftBracket2 = '('; + this.ShaderTextBox.Location = new System.Drawing.Point(3, 0); + this.ShaderTextBox.Name = "ShaderTextBox"; + this.ShaderTextBox.Paddings = new System.Windows.Forms.Padding(0); + this.ShaderTextBox.RightBracket = '>'; + this.ShaderTextBox.RightBracket2 = ')'; + this.ShaderTextBox.SelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255))))); + this.ShaderTextBox.ServiceColors = ((FastColoredTextBoxNS.ServiceColors)(resources.GetObject("ShaderTextBox.ServiceColors"))); + this.ShaderTextBox.Size = new System.Drawing.Size(523, 448); + this.ShaderTextBox.TabIndex = 1; + this.ShaderTextBox.Zoom = 100; + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel}); + this.statusStrip1.Location = new System.Drawing.Point(0, 486); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Size = new System.Drawing.Size(788, 22); + this.statusStrip1.TabIndex = 1; + this.statusStrip1.Text = "statusStrip1"; + // + // StatusLabel + // + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(773, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.Text = "Ready"; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // TechniquesTabPage + // + this.TechniquesTabPage.Controls.Add(this.splitContainer2); + this.TechniquesTabPage.Location = new System.Drawing.Point(4, 22); + this.TechniquesTabPage.Name = "TechniquesTabPage"; + this.TechniquesTabPage.Size = new System.Drawing.Size(776, 454); + this.TechniquesTabPage.TabIndex = 2; + this.TechniquesTabPage.Text = "Techniques"; + this.TechniquesTabPage.UseVisualStyleBackColor = true; + // + // splitContainer2 + // + this.splitContainer2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer2.Location = new System.Drawing.Point(3, 3); + this.splitContainer2.Name = "splitContainer2"; + // + // splitContainer2.Panel1 + // + this.splitContainer2.Panel1.Controls.Add(this.TechniquesListView); + // + // splitContainer2.Panel2 + // + this.splitContainer2.Panel2.Controls.Add(this.TechniquePanel); + this.splitContainer2.Size = new System.Drawing.Size(770, 448); + this.splitContainer2.SplitterDistance = 235; + this.splitContainer2.TabIndex = 1; + // + // TechniquesListView + // + this.TechniquesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.TechniquesNameColumn}); + this.TechniquesListView.Dock = System.Windows.Forms.DockStyle.Fill; + this.TechniquesListView.FullRowSelect = true; + this.TechniquesListView.HideSelection = false; + this.TechniquesListView.Location = new System.Drawing.Point(0, 0); + this.TechniquesListView.MultiSelect = false; + this.TechniquesListView.Name = "TechniquesListView"; + this.TechniquesListView.Size = new System.Drawing.Size(235, 448); + this.TechniquesListView.TabIndex = 0; + this.TechniquesListView.UseCompatibleStateImageBehavior = false; + this.TechniquesListView.View = System.Windows.Forms.View.Details; + this.TechniquesListView.SelectedIndexChanged += new System.EventHandler(this.TechniquesListView_SelectedIndexChanged); + // + // TechniquesNameColumn + // + this.TechniquesNameColumn.Text = "Name"; + this.TechniquesNameColumn.Width = 208; + // + // TechniquePanel + // + this.TechniquePanel.Controls.Add(this.TechniqueTextBox); + this.TechniquePanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.TechniquePanel.Enabled = false; + this.TechniquePanel.Location = new System.Drawing.Point(0, 0); + this.TechniquePanel.Name = "TechniquePanel"; + this.TechniquePanel.Size = new System.Drawing.Size(531, 448); + this.TechniquePanel.TabIndex = 0; + // + // TechniqueTextBox + // + this.TechniqueTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TechniqueTextBox.AutoCompleteBracketsList = new char[] { + '(', + ')', + '{', + '}', + '[', + ']', + '\"', + '\"', + '\'', + '\''}; + this.TechniqueTextBox.AutoIndentChars = false; + this.TechniqueTextBox.AutoIndentCharsPatterns = "\n^\\s*[\\w\\.]+(\\s\\w+)?\\s*(?=)\\s*(?[^;]+);\n^\\s*(case|default)\\s*[^:]*(" + + "?:)\\s*(?[^;]+);\n"; + this.TechniqueTextBox.AutoIndentExistingLines = false; + this.TechniqueTextBox.AutoScrollMinSize = new System.Drawing.Size(27, 14); + this.TechniqueTextBox.BackBrush = null; + this.TechniqueTextBox.CharHeight = 14; + this.TechniqueTextBox.CharWidth = 8; + this.TechniqueTextBox.Cursor = System.Windows.Forms.Cursors.IBeam; + this.TechniqueTextBox.DelayedEventsInterval = 10; + this.TechniqueTextBox.DisabledColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180))))); + this.TechniqueTextBox.IsReplaceMode = false; + this.TechniqueTextBox.Language = FastColoredTextBoxNS.Language.CSharp; + this.TechniqueTextBox.LeftBracket = '('; + this.TechniqueTextBox.LeftBracket2 = '{'; + this.TechniqueTextBox.Location = new System.Drawing.Point(3, 0); + this.TechniqueTextBox.Name = "TechniqueTextBox"; + this.TechniqueTextBox.Paddings = new System.Windows.Forms.Padding(0); + this.TechniqueTextBox.RightBracket = ')'; + this.TechniqueTextBox.RightBracket2 = '}'; + this.TechniqueTextBox.SelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255))))); + this.TechniqueTextBox.ServiceColors = ((FastColoredTextBoxNS.ServiceColors)(resources.GetObject("TechniqueTextBox.ServiceColors"))); + this.TechniqueTextBox.Size = new System.Drawing.Size(523, 448); + this.TechniqueTextBox.TabIndex = 1; + this.TechniqueTextBox.Zoom = 100; + // + // FxcForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(788, 508); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.MainTabControl); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "FxcForm"; + this.Text = "FXC Viewer - CodeWalker by dexyfex"; + this.MainTabControl.ResumeLayout(false); + this.ShadersTabPage.ResumeLayout(false); + this.DetailsTabPage.ResumeLayout(false); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.ShaderPanel.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.ShaderTextBox)).EndInit(); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.TechniquesTabPage.ResumeLayout(false); + this.splitContainer2.Panel1.ResumeLayout(false); + this.splitContainer2.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); + this.splitContainer2.ResumeLayout(false); + this.TechniquePanel.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.TechniqueTextBox)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TabControl MainTabControl; + private System.Windows.Forms.TabPage ShadersTabPage; + private System.Windows.Forms.TabPage DetailsTabPage; + private WinForms.PropertyGridFix DetailsPropertyGrid; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Panel ShaderPanel; + private System.Windows.Forms.ListView ShadersListView; + private System.Windows.Forms.ColumnHeader ShadersNameColumn; + private FastColoredTextBoxNS.FastColoredTextBox ShaderTextBox; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.TabPage TechniquesTabPage; + private System.Windows.Forms.SplitContainer splitContainer2; + private System.Windows.Forms.ListView TechniquesListView; + private System.Windows.Forms.ColumnHeader TechniquesNameColumn; + private System.Windows.Forms.Panel TechniquePanel; + private FastColoredTextBoxNS.FastColoredTextBox TechniqueTextBox; + } +} \ No newline at end of file diff --git a/Forms/FxcForm.cs b/Forms/FxcForm.cs new file mode 100644 index 0000000..97e9e05 --- /dev/null +++ b/Forms/FxcForm.cs @@ -0,0 +1,197 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class FxcForm : Form + { + private FxcFile Fxc; + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + + + + public FxcForm() + { + InitializeComponent(); + } + + + + + private void UpdateFormTitle() + { + Text = fileName + " - FXC Viewer - CodeWalker by dexyfex"; + } + + + public void LoadFxc(FxcFile fxc) + { + Fxc = fxc; + + fileName = fxc?.Name; + if (string.IsNullOrEmpty(fileName)) + { + fileName = fxc?.FileEntry?.Name; + } + + UpdateFormTitle(); + + DetailsPropertyGrid.SelectedObject = fxc; + + + ShadersListView.Items.Clear(); + TechniquesListView.Items.Clear(); + if ((fxc == null) || (fxc.Shaders == null)) return; + + foreach (var shader in fxc.Shaders) + { + var item = ShadersListView.Items.Add(shader.Name); + item.Tag = shader; + } + + if (fxc.Techniques != null) + { + foreach (var technique in fxc.Techniques) + { + var item = TechniquesListView.Items.Add(technique.ToString()); + item.Tag = technique; + } + } + + + if (!string.IsNullOrEmpty(fxc.LastError)) + { + StatusLabel.Text = fxc.LastError; + } + else + { + StatusLabel.Text = (fxc.Shaders?.Length??0).ToString() + " shaders, " + (fxc.Techniques?.Length??0).ToString() + " techniques"; + } + } + + + private void LoadShader(FxcShader s) + { + if (s == null) + { + ShaderPanel.Enabled = false; + ShaderTextBox.Text = string.Empty; + } + else + { + ShaderPanel.Enabled = true; + if (!string.IsNullOrEmpty(s.LastError)) + { + StringBuilder sb = new StringBuilder(); + sb.Append("Error: "); + sb.AppendLine(s.LastError); + sb.AppendLine(); + sb.AppendLine(s.Disassembly); + ShaderTextBox.Text = sb.ToString(); + } + else + { + ShaderTextBox.Text = s.Disassembly; + } + } + } + + private void LoadTechnique(FxcTechnique t) + { + if (t == null) + { + TechniquePanel.Enabled = false; + TechniqueTextBox.Text = string.Empty; + } + else + { + TechniquePanel.Enabled = true; + StringBuilder sb = new StringBuilder(); + sb.AppendLine("technique " + t.Name); + sb.AppendLine("{"); + if (t.Passes != null) + { + for (int i = 0; i < t.Passes.Length; i++) + { + var pass = t.Passes[i]; + sb.AppendLine(" pass p" + i.ToString());// + pass.ToString()); + sb.AppendLine(" {"); + + var vs = Fxc?.GetVS(pass.VS); + var ps = Fxc?.GetPS(pass.PS); + var cs = Fxc?.GetCS(pass.CS); + var ds = Fxc?.GetDS(pass.DS); + var gs = Fxc?.GetGS(pass.GS); + var hs = Fxc?.GetHS(pass.HS); + + if (vs != null) sb.AppendLine(" vertexShader = " + vs.Name + "();"); + if (ps != null) sb.AppendLine(" pixelShader = " + ps.Name + "();"); + if (cs != null) sb.AppendLine(" computeShader = " + cs.Name + "();"); + if (ds != null) sb.AppendLine(" domainShader = " + ds.Name + "();"); + if (gs != null) sb.AppendLine(" geometryShader = " + gs.Name + "();"); + if (hs != null) sb.AppendLine(" hullShader = " + hs.Name + "();"); + + if ((pass.Params != null) && (pass.Params.Length > 0)) + { + //TODO: properly display the params (what are they all? cbuffers etc) + + //sb.AppendLine(); + //foreach (var param in pass.Params) + //{ + // sb.AppendLine(" " + param.ToString()); + //} + } + sb.AppendLine(" }"); + } + } + sb.AppendLine("}"); + TechniqueTextBox.Text = sb.ToString(); + } + } + + + private void ShadersListView_SelectedIndexChanged(object sender, EventArgs e) + { + FxcShader s = null; + if (ShadersListView.SelectedItems.Count == 1) + { + s = ShadersListView.SelectedItems[0].Tag as FxcShader; + } + + LoadShader(s); + + } + + private void TechniquesListView_SelectedIndexChanged(object sender, EventArgs e) + { + FxcTechnique t = null; + if (TechniquesListView.SelectedItems.Count == 1) + { + t = TechniquesListView.SelectedItems[0].Tag as FxcTechnique; + } + + LoadTechnique(t); + + } + } +} diff --git a/Forms/FxcForm.resx b/Forms/FxcForm.resx new file mode 100644 index 0000000..e888a3b --- /dev/null +++ b/Forms/FxcForm.resx @@ -0,0 +1,448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdGYXN0Q29sb3JlZFRleHRCb3gsIFZlcnNpb249Mi4xNi4yMS4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWZiOGFhMTJiOTk0ZWY2MWIMAwAAAFFTeXN0 + ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2Vu + PWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACJGYXN0Q29sb3JlZFRleHRCb3hOUy5TZXJ2aWNlQ29sb3JzBgAA + ACg8Q29sbGFwc2VNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxDb2xsYXBzZU1hcmtlckJh + Y2tDb2xvcj5rX19CYWNraW5nRmllbGQqPENvbGxhcHNlTWFya2VyQm9yZGVyQ29sb3I+a19fQmFja2lu + Z0ZpZWxkJjxFeHBhbmRNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkJjxFeHBhbmRNYXJrZXJC + YWNrQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxFeHBhbmRNYXJrZXJCb3JkZXJDb2xvcj5rX19CYWNraW5n + RmllbGQEBAQEBAQUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5EcmF3aW5nLkNvbG9yAwAA + ABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAAUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5E + cmF3aW5nLkNvbG9yAwAAABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAACAAAABfz///8UU3lzdGVtLkRy + YXdpbmcuQ29sb3IEAAAABG5hbWUFdmFsdWUKa25vd25Db2xvcgVzdGF0ZQEAAAAJBwcDAAAACgAAAAAA + AAAAlgABAAH7/////P///woAAAAAAAAAAKQAAQAB+v////z///8KAAAAAAAAAACWAAEAAfn////8//// + CgAAAAAAAAAAlgABAAH4/////P///woAAAAAAAAAAKQAAQAB9/////z///8KAAAAAAAAAACWAAEACw== + + + + 17, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdGYXN0Q29sb3JlZFRleHRCb3gsIFZlcnNpb249Mi4xNi4yMS4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWZiOGFhMTJiOTk0ZWY2MWIMAwAAAFFTeXN0 + ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2Vu + PWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACJGYXN0Q29sb3JlZFRleHRCb3hOUy5TZXJ2aWNlQ29sb3JzBgAA + ACg8Q29sbGFwc2VNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxDb2xsYXBzZU1hcmtlckJh + Y2tDb2xvcj5rX19CYWNraW5nRmllbGQqPENvbGxhcHNlTWFya2VyQm9yZGVyQ29sb3I+a19fQmFja2lu + Z0ZpZWxkJjxFeHBhbmRNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkJjxFeHBhbmRNYXJrZXJC + YWNrQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxFeHBhbmRNYXJrZXJCb3JkZXJDb2xvcj5rX19CYWNraW5n + RmllbGQEBAQEBAQUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5EcmF3aW5nLkNvbG9yAwAA + ABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAAUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5E + cmF3aW5nLkNvbG9yAwAAABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAACAAAABfz///8UU3lzdGVtLkRy + YXdpbmcuQ29sb3IEAAAABG5hbWUFdmFsdWUKa25vd25Db2xvcgVzdGF0ZQEAAAAJBwcDAAAACgAAAAAA + AAAAlgABAAH7/////P///woAAAAAAAAAAKQAAQAB+v////z///8KAAAAAAAAAACWAAEAAfn////8//// + CgAAAAAAAAAAlgABAAH4/////P///woAAAAAAAAAAKQAAQAB9/////z///8KAAAAAAAAAACWAAEACw== + + + + + + AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA + 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 + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//r7//v8//7+/wAAAAAAAAAA + APb4/7/F84eP0e/0//7+/wAAAAAAAP7+//z9//v8//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz9//b5//X4//v8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////w////4 + P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA + AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA + AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v// + /////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/GxtForm.Designer.cs b/Forms/GxtForm.Designer.cs new file mode 100644 index 0000000..3fdf16d --- /dev/null +++ b/Forms/GxtForm.Designer.cs @@ -0,0 +1,82 @@ +namespace CodeWalker.Forms +{ + partial class GxtForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GxtForm)); + this.MainTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.CloseButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // MainTextBox + // + this.MainTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTextBox.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.MainTextBox.HideSelection = false; + this.MainTextBox.Location = new System.Drawing.Point(12, 12); + this.MainTextBox.Multiline = true; + this.MainTextBox.Name = "MainTextBox"; + this.MainTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.MainTextBox.Size = new System.Drawing.Size(660, 367); + this.MainTextBox.TabIndex = 0; + this.MainTextBox.WordWrap = false; + // + // CloseButton + // + this.CloseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.CloseButton.Location = new System.Drawing.Point(597, 389); + this.CloseButton.Name = "CloseButton"; + this.CloseButton.Size = new System.Drawing.Size(75, 23); + this.CloseButton.TabIndex = 1; + this.CloseButton.Text = "Close"; + this.CloseButton.UseVisualStyleBackColor = true; + this.CloseButton.Click += new System.EventHandler(this.CloseButton_Click); + // + // GxtForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(684, 421); + this.Controls.Add(this.CloseButton); + this.Controls.Add(this.MainTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "GxtForm"; + this.Text = "GXT Viewer - CodeWalker by dexyfex"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private WinForms.TextBoxFix MainTextBox; + private System.Windows.Forms.Button CloseButton; + } +} \ No newline at end of file diff --git a/Forms/GxtForm.cs b/Forms/GxtForm.cs new file mode 100644 index 0000000..59023e0 --- /dev/null +++ b/Forms/GxtForm.cs @@ -0,0 +1,79 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class GxtForm : Form + { + + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + + + public GxtForm() + { + InitializeComponent(); + } + + + private void UpdateFormTitle() + { + Text = fileName + " - GXT Viewer - CodeWalker by dexyfex"; + } + + + public void LoadGxt2(Gxt2File gxt) + { + + fileName = gxt?.Name; + if (string.IsNullOrEmpty(fileName)) + { + fileName = gxt?.FileEntry?.Name; + } + + UpdateFormTitle(); + + StringBuilder sb = new StringBuilder(); + + if ((gxt != null) && (gxt.TextEntries != null)) + { + foreach (var entry in gxt.TextEntries) + { + sb.Append("0x"); + sb.Append(entry.Hash.ToString("X").PadLeft(8, '0')); + sb.Append(" = "); + sb.Append(entry.Text); + sb.AppendLine(); + } + } + + + MainTextBox.Text = sb.ToString(); + + } + + private void CloseButton_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/Forms/GxtForm.resx b/Forms/GxtForm.resx new file mode 100644 index 0000000..1431f6b --- /dev/null +++ b/Forms/GxtForm.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/HexForm.Designer.cs b/Forms/HexForm.Designer.cs new file mode 100644 index 0000000..519019f --- /dev/null +++ b/Forms/HexForm.Designer.cs @@ -0,0 +1,123 @@ +namespace CodeWalker.Forms +{ + partial class HexForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HexForm)); + this.LineSizeDropDown = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.HexTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.statusStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // LineSizeDropDown + // + this.LineSizeDropDown.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.LineSizeDropDown.FormattingEnabled = true; + this.LineSizeDropDown.Items.AddRange(new object[] { + "8", + "16", + "32", + "Text"}); + this.LineSizeDropDown.Location = new System.Drawing.Point(79, 7); + this.LineSizeDropDown.Name = "LineSizeDropDown"; + this.LineSizeDropDown.Size = new System.Drawing.Size(49, 21); + this.LineSizeDropDown.TabIndex = 102; + this.LineSizeDropDown.SelectedIndexChanged += new System.EventHandler(this.LineSizeDropDown_SelectedIndexChanged); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(22, 10); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(51, 13); + this.label1.TabIndex = 103; + this.label1.Text = "Line size:"; + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel}); + this.statusStrip1.Location = new System.Drawing.Point(0, 488); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Size = new System.Drawing.Size(748, 22); + this.statusStrip1.TabIndex = 104; + this.statusStrip1.Text = "statusStrip1"; + // + // StatusLabel + // + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(733, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // HexTextBox + // + this.HexTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.HexTextBox.Font = new System.Drawing.Font("Courier New", 8.25F); + this.HexTextBox.HideSelection = false; + this.HexTextBox.Location = new System.Drawing.Point(0, 34); + this.HexTextBox.Multiline = true; + this.HexTextBox.Name = "HexTextBox"; + this.HexTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.HexTextBox.Size = new System.Drawing.Size(748, 451); + this.HexTextBox.TabIndex = 105; + this.HexTextBox.WordWrap = false; + // + // HexForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(748, 510); + this.Controls.Add(this.HexTextBox); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.label1); + this.Controls.Add(this.LineSizeDropDown); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "HexForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Hex Viewer - CodeWalker by dexyfex"; + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.ComboBox LineSizeDropDown; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private WinForms.TextBoxFix HexTextBox; + } +} \ No newline at end of file diff --git a/Forms/HexForm.cs b/Forms/HexForm.cs new file mode 100644 index 0000000..6184043 --- /dev/null +++ b/Forms/HexForm.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class HexForm : Form + { + + private byte[] data; + public byte[] Data + { + get { return data; } + set + { + data = value; + UpdateTextBoxFromData(); + } + } + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + + public HexForm() + { + InitializeComponent(); + + LineSizeDropDown.Text = "16"; + } + + + public void LoadData(string filename, string filepath, byte[] data) + { + FileName = filename; + FilePath = filepath; + Data = data; + } + + private void UpdateFormTitle() + { + Text = fileName + " - Hex Viewer - CodeWalker by dexyfex"; + } + + private void UpdateTextBoxFromData() + { + if (data == null) + { + HexTextBox.Text = ""; + return; + } + if (data.Length > (1048576 * 5)) + { + HexTextBox.Text = "[File size > 5MB - Not shown due to performance limitations - Please use an external viewer for this file.]"; + return; + } + + + Cursor = Cursors.WaitCursor; + + //int selline = -1; + //int selstartc = -1; + //int selendc = -1; + + bool ishex = (LineSizeDropDown.Text != "Text"); + + + if (ishex) + { + int charsperln = int.Parse(LineSizeDropDown.Text); + int lines = (data.Length / charsperln) + (((data.Length % charsperln) > 0) ? 1 : 0); + StringBuilder hexb = new StringBuilder(); + StringBuilder texb = new StringBuilder(); + StringBuilder finb = new StringBuilder(); + + //if (offset > 0) + //{ + // selline = offset / charsperln; + //} + for (int i = 0; i < lines; i++) + { + int pos = i * charsperln; + int poslim = pos + charsperln; + hexb.Clear(); + texb.Clear(); + hexb.AppendFormat("{0:X4}: ", pos); + for (int c = pos; c < poslim; c++) + { + if (c < data.Length) + { + byte b = data[c]; + hexb.AppendFormat("{0:X2} ", b); + if (char.IsControl((char)b)) + { + texb.Append("."); + } + else + { + texb.Append(Encoding.ASCII.GetString(data, c, 1)); + } + } + else + { + hexb.Append(" "); + texb.Append(" "); + } + } + + //if (i == selline) selstartc = finb.Length; + finb.AppendLine(hexb.ToString() + "| " + texb.ToString()); + //if (i == selline) selendc = finb.Length - 1; + } + + HexTextBox.Text = finb.ToString(); + + } + else + { + + string text = Encoding.UTF8.GetString(data); + + + HexTextBox.Text = text; + + //if (offset > 0) + //{ + // selstartc = offset; + // selendc = offset + length; + //} + } + + Cursor = Cursors.Default; + } + + private void LineSizeDropDown_SelectedIndexChanged(object sender, EventArgs e) + { + UpdateTextBoxFromData(); + } + } +} diff --git a/Forms/HexForm.resx b/Forms/HexForm.resx new file mode 100644 index 0000000..4c38f15 --- /dev/null +++ b/Forms/HexForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA + AABAAAAAAQAYAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv8/u3v+Pn6//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AP7+/vX3/rzA3OHl9fz9/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7//+zv+3Z6qcLI5Pr7/wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAP7+/+br+15in6+33vf5/wAAAAAAAAAAAAAAAP7+//7+/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//v8//v8//3+/wAAAAAAAAAAAAAAAAAAAP7+/+Ho+1dana20 + 4/b4/wAAAAAAAPz9//P2/+Tp/ezw/vz9/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///X4 + /9Pa+tPa+/H1//z9/wAAAAAAAAAAAAAAAP7+/93k+SsscaSr3PX3/wAAAP7+//L1/7W98AcWgrvC8Pj6 + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/+bs/xohiAEJdrvF9+7y//z9/wAAAAAAAAAA + AP7+/9rh+CEkapmh0/T3/wAAAPj6/9HZ/AEHcgEEb9LZ+/r7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAP7//+/z/3F+zAAAXwQLcZai3fb4/wAAAAAAAAAAAP3+/97l/E9Tmaau4fT3/wAAAO/0/1dd + sAAAV7a/8/H1//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPr8/+jv/46Y3QUUf6Ot + 5PX4/wAAAAAAAAAAAP3+/9zj+3Z6wLe/7fX4/wAAAPD0/212xnaAzerw//z9/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv8/+/z/+Dm+/D0//z9/wAAAAAAAP7+//j6/9Pd+UhLjb/H + 9/D0//3+//n7/+nt/+jt//n7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AP7///7+//7+//7+/wAAAAAAAPr8/+7z/83W+ImU2A0UdFNarr/K9env//X4//z9//3+//7//wAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///j6/+Pq/255 + xhckjE5XsVVftUlTqwAKeTA9nr3H8+7z//v8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+//b4/9Tc+Sc0mRonj8rV/crX/ZSb48rX/brG8wwWgQAEdJei + 4efu//n7//7+//z9//z9//z9//z9//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//f5/+3y/+nv/+ft + /8vV+io2mImU2M7c/7vG9yIvlQAOfCg4mM3Y/s/c/4aR1AQRfGtzwtni/ebt/9vi/tri/tXd+9Tc+O3x + /vz9/wAAAAAAAAAAAAAAAAAAAAAAAPn6/87V+FVftkRPrFlnvSEqjQoUfmJvwWFvvg0TfQQIcxEchwAD + cy89n19rvVVitQwZgwAAaiMrkT9NqTVBoiw3mhQihig1mNLX+fv8/wAAAAAAAAAAAAAAAAAAAAAAAPb5 + /52l4EFLqoCK03yF0VBctGhyw52o5GVrvQAAaneBzsHM+jA3mhYgiTtIpJOf3ouW2AAAbmh0wbbA8bS+ + 7qiz5pCb16+56e/z//3+/wAAAAAAAAAAAAAAAAAAAAAAAPv8//H1/+vw/+zx/+nv/7/J9YqP3MbP/8LM + +hwqkFZftaCp5EhRrcTQ+9jj/8rW/UJMqn6J0ebt//X3//f5//b4//X3//f5//z9/wAAAAAAAAAAAAAA + AAAAAAAAAP7+//z9//3+/wAAAAAAAP3+/+7z/6at64iP3aWs7XN8zRIfhyUykp2o5MHM+oKM0xonjY6X + 2+jv//v8/wAAAP7+//n7//b5//r7//7//wAAAAAAAAAAAAAAAP7+//f5/+rw/9Pa9fL0/v7//wAAAAAA + APv8//H1/+Tr/7i/91liu0NPq0VQrS06m0NNqDdCoYqU1+nv//v8/wAAAAAAAPn7/9zi/qSt59ri/fL1 + //v8//7//wAAAPz9//D0/8rT+h0sjkVQrPD0/wAAAAAAAAAAAAAAAAAAAPz9/+7z/8LL9Jqk4aGq6LW/ + 8c3W9+Xs/vH1//v8/wAAAAAAAAAAAPf5/6at5gAAbxIfh6u16+Po/fr7/wAAAPb5/6ev5gAIeAAPernC + 8fX4/wAAAAAAAP3+//v8//z9/wAAAP3+//j6//P3//P2//b4//r8//7+//7+//v8//r8//3+/wAAAPv8 + /+Xr/nuIzwAAbBseg5Sb2fb5/wAAAPf5/8DF8pWe3d/n/vT3//39/wAAAPv8/+zx/87V9+3x/v3+/wAA + AP3+//j6//X4//v8/wAAAAAAAPn7/+Dm/snR9fD0//39//z8/fv8/+3y/8LK9aGq4dfd9/n7/wAAAPz9 + //b5//X4//v8/wAAAAAAAP7+/+7z/4aP1gEPet7k/f39/wAAAPf5/83U+ZCZ2u3x/v7+/wAAAPP3/215 + wgAJd7fB8/L1//7+/wAAAP3+//j6//f5//r8//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAPj6/87W/AAA + X2duue3y//7+/wAAAPD0/05asBQfidzj/P39/wAAAPX4/6Su6AAAXBccgtff/vv8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPP3/3F8xhYli9Xe/fn6/wAAAAAAAO3y/1pltQAJd9be + /fv8/wAAAPz9/+rw/36I0Bknjs/W+vv8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAPf5/8HI7tnf+/X4//7+/wAAAAAAAO/0/3R7xgAAb9ng/Pz9/wAAAAAAAPn7/+Ln/dLY+fP2//3+ + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//r7//v8//7+/wAAAAAAAAAA + APb4/7/F84eP0e/0//7+/wAAAAAAAP7+//z9//v8//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz9//b5//X4//v8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////w////4 + P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA + AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA + AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v// + /////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/MetaForm.Designer.cs b/Forms/MetaForm.Designer.cs new file mode 100644 index 0000000..1252a02 --- /dev/null +++ b/Forms/MetaForm.Designer.cs @@ -0,0 +1,371 @@ +namespace CodeWalker.Forms +{ + partial class MetaForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MetaForm)); + this.MainToolbar = new System.Windows.Forms.ToolStrip(); + this.NewButton = new System.Windows.Forms.ToolStripSplitButton(); + this.OpenButton = new System.Windows.Forms.ToolStripSplitButton(); + this.SaveButton = new System.Windows.Forms.ToolStripSplitButton(); + this.MainStatusStrip = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.MainMenu = new System.Windows.Forms.MenuStrip(); + this.FileMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveAsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.FileCloseMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.wIPToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.wIPToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.XmlTextBox = new FastColoredTextBoxNS.FastColoredTextBox(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.RawPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog(); + this.MainToolbar.SuspendLayout(); + this.MainStatusStrip.SuspendLayout(); + this.MainMenu.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.XmlTextBox)).BeginInit(); + this.tabPage2.SuspendLayout(); + this.SuspendLayout(); + // + // MainToolbar + // + this.MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.NewButton, + this.OpenButton, + this.SaveButton}); + this.MainToolbar.Location = new System.Drawing.Point(0, 24); + this.MainToolbar.Name = "MainToolbar"; + this.MainToolbar.Size = new System.Drawing.Size(839, 25); + this.MainToolbar.TabIndex = 6; + this.MainToolbar.Text = "Main Toolbar"; + // + // NewButton + // + this.NewButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.NewButton.Image = ((System.Drawing.Image)(resources.GetObject("NewButton.Image"))); + this.NewButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.NewButton.Name = "NewButton"; + this.NewButton.Size = new System.Drawing.Size(32, 22); + this.NewButton.Text = "New..."; + this.NewButton.ButtonClick += new System.EventHandler(this.NewButton_ButtonClick); + // + // OpenButton + // + this.OpenButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.OpenButton.Image = ((System.Drawing.Image)(resources.GetObject("OpenButton.Image"))); + this.OpenButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.OpenButton.Name = "OpenButton"; + this.OpenButton.Size = new System.Drawing.Size(32, 22); + this.OpenButton.Text = "Open..."; + this.OpenButton.ButtonClick += new System.EventHandler(this.OpenButton_ButtonClick); + // + // SaveButton + // + this.SaveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.SaveButton.Image = ((System.Drawing.Image)(resources.GetObject("SaveButton.Image"))); + this.SaveButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.SaveButton.Name = "SaveButton"; + this.SaveButton.Size = new System.Drawing.Size(32, 22); + this.SaveButton.Text = "Save"; + this.SaveButton.ButtonClick += new System.EventHandler(this.SaveButton_ButtonClick); + // + // MainStatusStrip + // + this.MainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel}); + this.MainStatusStrip.Location = new System.Drawing.Point(0, 535); + this.MainStatusStrip.Name = "MainStatusStrip"; + this.MainStatusStrip.Size = new System.Drawing.Size(839, 22); + this.MainStatusStrip.TabIndex = 4; + this.MainStatusStrip.Text = "Main Status Strip"; + // + // StatusLabel + // + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(824, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // MainMenu + // + this.MainMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileMenu, + this.EditMenu, + this.ViewMenu}); + this.MainMenu.Location = new System.Drawing.Point(0, 0); + this.MainMenu.Name = "MainMenu"; + this.MainMenu.Size = new System.Drawing.Size(839, 24); + this.MainMenu.TabIndex = 5; + this.MainMenu.Text = "Main Menu"; + // + // FileMenu + // + this.FileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileNewMenu, + this.FileOpenMenu, + this.FileSaveMenu, + this.FileSaveAsMenu, + this.toolStripSeparator1, + this.FileCloseMenu}); + this.FileMenu.Name = "FileMenu"; + this.FileMenu.Size = new System.Drawing.Size(37, 20); + this.FileMenu.Text = "File"; + // + // FileNewMenu + // + this.FileNewMenu.Name = "FileNewMenu"; + this.FileNewMenu.Size = new System.Drawing.Size(145, 22); + this.FileNewMenu.Text = "New"; + this.FileNewMenu.Click += new System.EventHandler(this.FileNewMenu_Click); + // + // FileOpenMenu + // + this.FileOpenMenu.Name = "FileOpenMenu"; + this.FileOpenMenu.Size = new System.Drawing.Size(145, 22); + this.FileOpenMenu.Text = "Open..."; + this.FileOpenMenu.Click += new System.EventHandler(this.FileOpenMenu_Click); + // + // FileSaveMenu + // + this.FileSaveMenu.Name = "FileSaveMenu"; + this.FileSaveMenu.Size = new System.Drawing.Size(145, 22); + this.FileSaveMenu.Text = "Save"; + this.FileSaveMenu.Click += new System.EventHandler(this.FileSaveMenu_Click); + // + // FileSaveAsMenu + // + this.FileSaveAsMenu.Name = "FileSaveAsMenu"; + this.FileSaveAsMenu.Size = new System.Drawing.Size(145, 22); + this.FileSaveAsMenu.Text = "Save As..."; + this.FileSaveAsMenu.Click += new System.EventHandler(this.FileSaveAsMenu_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(142, 6); + // + // FileCloseMenu + // + this.FileCloseMenu.Name = "FileCloseMenu"; + this.FileCloseMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); + this.FileCloseMenu.Size = new System.Drawing.Size(145, 22); + this.FileCloseMenu.Text = "Close"; + this.FileCloseMenu.Click += new System.EventHandler(this.FileCloseMenu_Click); + // + // EditMenu + // + this.EditMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.wIPToolStripMenuItem}); + this.EditMenu.Enabled = false; + this.EditMenu.Name = "EditMenu"; + this.EditMenu.Size = new System.Drawing.Size(39, 20); + this.EditMenu.Text = "Edit"; + // + // wIPToolStripMenuItem + // + this.wIPToolStripMenuItem.Name = "wIPToolStripMenuItem"; + this.wIPToolStripMenuItem.Size = new System.Drawing.Size(106, 22); + this.wIPToolStripMenuItem.Text = "[WIP!]"; + // + // ViewMenu + // + this.ViewMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.wIPToolStripMenuItem1}); + this.ViewMenu.Enabled = false; + this.ViewMenu.Name = "ViewMenu"; + this.ViewMenu.Size = new System.Drawing.Size(44, 20); + this.ViewMenu.Text = "View"; + // + // wIPToolStripMenuItem1 + // + this.wIPToolStripMenuItem1.Name = "wIPToolStripMenuItem1"; + this.wIPToolStripMenuItem1.Size = new System.Drawing.Size(106, 22); + this.wIPToolStripMenuItem1.Text = "[WIP!]"; + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.Location = new System.Drawing.Point(0, 49); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(839, 486); + this.tabControl1.TabIndex = 7; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.XmlTextBox); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(831, 460); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "XML"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // XmlTextBox + // + this.XmlTextBox.AutoCompleteBracketsList = new char[] { + '(', + ')', + '{', + '}', + '[', + ']', + '\"', + '\"', + '\'', + '\''}; + this.XmlTextBox.AutoIndentChars = false; + this.XmlTextBox.AutoIndentCharsPatterns = ""; + this.XmlTextBox.AutoIndentExistingLines = false; + this.XmlTextBox.AutoScrollMinSize = new System.Drawing.Size(27, 14); + this.XmlTextBox.BackBrush = null; + this.XmlTextBox.CharHeight = 14; + this.XmlTextBox.CharWidth = 8; + this.XmlTextBox.CommentPrefix = null; + this.XmlTextBox.Cursor = System.Windows.Forms.Cursors.IBeam; + this.XmlTextBox.DelayedEventsInterval = 1; + this.XmlTextBox.DisabledColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180))))); + this.XmlTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.XmlTextBox.Font = new System.Drawing.Font("Courier New", 9.75F); + this.XmlTextBox.IsReplaceMode = false; + this.XmlTextBox.Language = FastColoredTextBoxNS.Language.XML; + this.XmlTextBox.LeftBracket = '<'; + this.XmlTextBox.LeftBracket2 = '('; + this.XmlTextBox.Location = new System.Drawing.Point(3, 3); + this.XmlTextBox.Name = "XmlTextBox"; + this.XmlTextBox.Paddings = new System.Windows.Forms.Padding(0); + this.XmlTextBox.RightBracket = '>'; + this.XmlTextBox.RightBracket2 = ')'; + this.XmlTextBox.SelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255))))); + this.XmlTextBox.ServiceColors = ((FastColoredTextBoxNS.ServiceColors)(resources.GetObject("XmlTextBox.ServiceColors"))); + this.XmlTextBox.Size = new System.Drawing.Size(825, 454); + this.XmlTextBox.TabIndex = 1; + this.XmlTextBox.Zoom = 100; + this.XmlTextBox.TextChanged += new System.EventHandler(this.XmlTextBox_TextChanged); + this.XmlTextBox.VisibleRangeChangedDelayed += new System.EventHandler(this.XmlTextBox_VisibleRangeChangedDelayed); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.RawPropertyGrid); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(831, 460); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Raw Data"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // RawPropertyGrid + // + this.RawPropertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.RawPropertyGrid.HelpVisible = false; + this.RawPropertyGrid.Location = new System.Drawing.Point(3, 3); + this.RawPropertyGrid.Name = "RawPropertyGrid"; + this.RawPropertyGrid.Size = new System.Drawing.Size(825, 454); + this.RawPropertyGrid.TabIndex = 0; + // + // OpenFileDialog + // + this.OpenFileDialog.Filter = "XML files|*.xml|All files|*.*"; + // + // SaveFileDialog + // + this.SaveFileDialog.Filter = "XML files|*.xml|All files|*.*"; + // + // MetaForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(839, 557); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.MainToolbar); + this.Controls.Add(this.MainStatusStrip); + this.Controls.Add(this.MainMenu); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "MetaForm"; + this.Text = "Meta Editor - CodeWalker by dexyfex"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MetaForm_FormClosing); + this.MainToolbar.ResumeLayout(false); + this.MainToolbar.PerformLayout(); + this.MainStatusStrip.ResumeLayout(false); + this.MainStatusStrip.PerformLayout(); + this.MainMenu.ResumeLayout(false); + this.MainMenu.PerformLayout(); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.XmlTextBox)).EndInit(); + this.tabPage2.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ToolStrip MainToolbar; + private System.Windows.Forms.ToolStripSplitButton NewButton; + private System.Windows.Forms.ToolStripSplitButton OpenButton; + private System.Windows.Forms.ToolStripSplitButton SaveButton; + private System.Windows.Forms.StatusStrip MainStatusStrip; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.MenuStrip MainMenu; + private System.Windows.Forms.ToolStripMenuItem FileMenu; + private System.Windows.Forms.ToolStripMenuItem EditMenu; + private System.Windows.Forms.ToolStripMenuItem ViewMenu; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private FastColoredTextBoxNS.FastColoredTextBox XmlTextBox; + private WinForms.PropertyGridFix RawPropertyGrid; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + private System.Windows.Forms.SaveFileDialog SaveFileDialog; + private System.Windows.Forms.ToolStripMenuItem FileNewMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenMenu; + private System.Windows.Forms.ToolStripMenuItem FileSaveMenu; + private System.Windows.Forms.ToolStripMenuItem FileSaveAsMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem FileCloseMenu; + private System.Windows.Forms.ToolStripMenuItem wIPToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem wIPToolStripMenuItem1; + } +} \ No newline at end of file diff --git a/Forms/MetaForm.cs b/Forms/MetaForm.cs new file mode 100644 index 0000000..e0d1297 --- /dev/null +++ b/Forms/MetaForm.cs @@ -0,0 +1,333 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using FastColoredTextBoxNS; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class MetaForm : Form + { + private string xml; + public string Xml + { + get { return xml; } + set + { + xml = value; + UpdateTextBoxFromData(); + } + } + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + private bool modified = false; + private bool LoadingXml = false; + private bool DelayHighlight = false; + + + public MetaForm() + { + InitializeComponent(); + } + + + private void UpdateFormTitle() + { + string ro = "";// " [Read-Only]"; + Text = fileName + " - Meta Editor" + ro + " - CodeWalker by dexyfex"; + } + + private void UpdateTextBoxFromData() + { + LoadingXml = true; + XmlTextBox.Text = ""; + XmlTextBox.Language = Language.XML; + DelayHighlight = false; + + if (string.IsNullOrEmpty(xml)) + { + LoadingXml = false; + return; + } + //if (xml.Length > (1048576 * 5)) + //{ + // XmlTextBox.Language = Language.Custom; + // XmlTextBox.Text = "[XML size > 10MB - Not shown due to performance limitations - Please use an external viewer for this file.]"; + // return; + //} + //else + if (xml.Length > (1024 * 512)) + { + XmlTextBox.Language = Language.Custom; + DelayHighlight = true; + } + //else + //{ + // XmlTextBox.Language = Language.XML; + //} + + + Cursor = Cursors.WaitCursor; + + + + XmlTextBox.Text = xml; + //XmlTextBox.IsChanged = false; + XmlTextBox.ClearUndo(); + + Cursor = Cursors.Default; + LoadingXml = false; + } + + + private bool CloseDocument() + { + if (modified) + { + var res = MessageBox.Show("Do you want to save the current document before closing it?", "Save before closing", MessageBoxButtons.YesNoCancel); + switch (res) + { + case DialogResult.Yes: + SaveDocument(); + break; + case DialogResult.Cancel: + return false; + } + } + + FilePath = ""; + FileName = ""; + Xml = ""; + RawPropertyGrid.SelectedObject = null; + modified = false; + + return true; + } + private void NewDocument() + { + if (!CloseDocument()) return; //same thing really.. + + FileName = "New.xml"; + } + private void OpenDocument() + { + if (OpenFileDialog.ShowDialog() != DialogResult.OK) return; + + if (!CloseDocument()) return; + + var fn = OpenFileDialog.FileName; + + if (!File.Exists(fn)) return; //couldn't find file? + + Xml = File.ReadAllText(fn); + + modified = false; + FilePath = fn; + FileName = new FileInfo(fn).Name; + RawPropertyGrid.SelectedObject = null; + } + private void SaveDocument(bool saveAs = false) + { + if (string.IsNullOrEmpty(FileName)) saveAs = true; + if (string.IsNullOrEmpty(FilePath)) saveAs = true; + else if ((FilePath.ToLowerInvariant().StartsWith(Settings.Default.GTAFolder.ToLowerInvariant()))) saveAs = true; + if (!File.Exists(FilePath)) saveAs = true; + + var fn = FilePath; + if (saveAs) + { + if (!string.IsNullOrEmpty(fn)) + { + var dir = new FileInfo(fn).DirectoryName; + if (!Directory.Exists(dir)) dir = ""; + SaveFileDialog.InitialDirectory = dir; + } + SaveFileDialog.FileName = FileName; + if (SaveFileDialog.ShowDialog() != DialogResult.OK) return; + fn = SaveFileDialog.FileName; + } + + File.WriteAllText(fn, xml); + + modified = false; + FilePath = fn; + FileName = new FileInfo(fn).Name; + } + + + + public void LoadMeta(YmtFile ymt) + { + var fn = (ymt?.RpfFileEntry?.Name) ?? ""; + if (ymt.Meta != null) { LoadMeta(ymt.Meta); fn += ".xml"; } + else if (ymt.Pso != null) { LoadMeta(ymt.Pso); fn += ".pso.xml"; } + else if (ymt.Rbf != null) { LoadMeta(ymt.Rbf); fn += ".rbf.xml"; } + FileName = fn; + RawPropertyGrid.SelectedObject = ymt; + } + public void LoadMeta(YmfFile ymf) + { + var fn = (ymf?.FileEntry?.Name) ?? ""; + if (ymf.Meta != null) { LoadMeta(ymf.Meta); fn += ".xml"; } + else if (ymf.Pso != null) { LoadMeta(ymf.Pso); fn += ".pso.xml"; } + else if (ymf.Rbf != null) { LoadMeta(ymf.Rbf); fn += ".rbf.xml"; } + FileName = fn; + RawPropertyGrid.SelectedObject = ymf; + } + public void LoadMeta(YmapFile ymap) + { + var fn = (ymap?.RpfFileEntry?.Name) ?? ""; + if (ymap.Meta != null) { LoadMeta(ymap.Meta); fn += ".xml"; } + else if (ymap.Pso != null) { LoadMeta(ymap.Pso); fn += ".pso.xml"; } + else if (ymap.Rbf != null) { LoadMeta(ymap.Rbf); fn += ".rbf.xml"; } + FileName = fn; + RawPropertyGrid.SelectedObject = ymap; + } + public void LoadMeta(YtypFile ytyp) + { + var fn = (ytyp?.FileEntry?.Name) ?? ""; + if (ytyp.Meta != null) { LoadMeta(ytyp.Meta); fn += ".xml"; } + else if (ytyp.Pso != null) { LoadMeta(ytyp.Pso); fn += ".pso.xml"; } + else if (ytyp.Rbf != null) { LoadMeta(ytyp.Rbf); fn += ".rbf.xml"; } + FileName = fn; + RawPropertyGrid.SelectedObject = ytyp; + } + public void LoadMeta(JPsoFile jpso) + { + var fn = jpso?.FileEntry?.Name ?? ""; + if (jpso.Pso != null) { LoadMeta(jpso.Pso); fn += ".pso.xml"; } + FileName = fn; + RawPropertyGrid.SelectedObject = jpso; + } + public void LoadMeta(CutFile cut) + { + var fn = cut?.FileEntry?.Name ?? ""; + if (cut.Pso != null) { LoadMeta(cut.Pso); fn += ".pso.xml"; } + FileName = fn; + RawPropertyGrid.SelectedObject = cut; + } + public void LoadMeta(Meta meta) + { + Xml = MetaXml.GetXml(meta); + modified = false; + } + public void LoadMeta(PsoFile pso) + { + Xml = PsoXml.GetXml(pso); + modified = false; + } + public void LoadMeta(RbfFile rbf) + { + Xml = RbfXml.GetXml(rbf); + modified = false; + } + + + + + Style BlueStyle = new TextStyle(Brushes.Blue, null, FontStyle.Regular); + Style RedStyle = new TextStyle(Brushes.Red, null, FontStyle.Regular); + Style MaroonStyle = new TextStyle(Brushes.Maroon, null, FontStyle.Regular); + + private void HTMLSyntaxHighlight(Range range) + { + //clear style of changed range + range.ClearStyle(BlueStyle, MaroonStyle, RedStyle); + //tag brackets highlighting + range.SetStyle(BlueStyle, @"<|/>|"); + //tag name + range.SetStyle(MaroonStyle, @"<(?[!\w]+)"); + //end of tag + range.SetStyle(MaroonStyle, @"\w+)>"); + //attributes + range.SetStyle(RedStyle, @"(?\S+?)='[^']*'|(?\S+)=""[^""]*""|(?\S+)=\S+"); + //attribute values + range.SetStyle(BlueStyle, @"\S+?=(?'[^']*')|\S+=(?""[^""]*"")|\S+=(?\S+)"); + } + + + private void XmlTextBox_VisibleRangeChangedDelayed(object sender, EventArgs e) + { + //this approach is much faster to load, but no outlining is available + + //highlight only visible area of text + if (DelayHighlight) + { + HTMLSyntaxHighlight(XmlTextBox.VisibleRange); + } + } + + private void XmlTextBox_TextChanged(object sender, FastColoredTextBoxNS.TextChangedEventArgs e) + { + if (!LoadingXml) + { + xml = XmlTextBox.Text; + modified = true; + } + } + + private void NewButton_ButtonClick(object sender, EventArgs e) + { + NewDocument(); + } + + private void OpenButton_ButtonClick(object sender, EventArgs e) + { + OpenDocument(); + } + + private void SaveButton_ButtonClick(object sender, EventArgs e) + { + SaveDocument(); + } + + private void FileNewMenu_Click(object sender, EventArgs e) + { + NewDocument(); + } + + private void FileOpenMenu_Click(object sender, EventArgs e) + { + OpenDocument(); + } + + private void FileSaveMenu_Click(object sender, EventArgs e) + { + SaveDocument(); + } + + private void FileSaveAsMenu_Click(object sender, EventArgs e) + { + SaveDocument(true); + } + + private void FileCloseMenu_Click(object sender, EventArgs e) + { + Close(); + } + + private void MetaForm_FormClosing(object sender, FormClosingEventArgs e) + { + e.Cancel = !CloseDocument(); + } + } +} diff --git a/Forms/MetaForm.resx b/Forms/MetaForm.resx new file mode 100644 index 0000000..026bdb9 --- /dev/null +++ b/Forms/MetaForm.resx @@ -0,0 +1,471 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADESURBVDhPzZI7DgIhGIQ5grUnsPQMnMgLWMo1bDyJiYUV + h7CxEo1Aiw7+E9ldWF+Nk0w2wMy3/z5UqRDCwjk3iTEmGmvsS6Ste2gtJYvrdjklJK9xLtGhcAeEdqtZ + Ouw3uUgA1tgXSH0SGdsyfD0dcwHXAmqRk0pXCNMsN+y893OpPYVDjFw8d9JaD2yMqUNYgjkBCmd36bgJ + 6b+DMUAJkXr9K9QANM6QkfpD/f/gYwCESfgnfgWg/gcw5peAdyzxX6TUDfMCML1omZa9AAAAAElFTkSu + QmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEcSURBVDhPlZKxqsIwFIb7Bvc+idxHuPQVXFpQcOhe8Amc + OqqzCBdU6HQfQIfunVwKoi7FQQeF9GrajufmhDYkTaMY+EjPyf//TZtY9aCUfhVFQRggQbBfSV4PFJ8v + GekMf8HqzqE3jXhIhRwsqKyWxYpJ3bzcMpBD4jgG27Y1RACaZ+sEPvoLbmqCa/f7AzLyJ2gGcDO+bXe6 + ajugDypMiBJQluU3f2DiZ+YmT3eANWIyIyKgFsv/AOs2k4wSgIXneRBFEaRpyhew10ZbwNb3fU1oYrPe + qAF5no/CMNSEJsbjiRqAty9JEk1ownEcNaA6BeK6riY2cdgf+SwC2Gf8BEGgCU2slis+iwB2mQZ4Ak3h + K0QAIeQTi/cp4B9tCZE2c6oRhQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABWSURBVDhPY6AK+Pbt238S8PsvX74YQLVCAEjCyckJjj+8 + /wjHyGIguq2tDdMQUgwAYZghUO2kGwDCID1Q7fgNQMbIamhrADF41IBBaQA5GKqdEsDAAADtDPd9n5qK + lQAAAABJRU5ErkJggg== + + + + 138, 17 + + + 276, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdGYXN0Q29sb3JlZFRleHRCb3gsIFZlcnNpb249Mi4xNi4yMS4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWZiOGFhMTJiOTk0ZWY2MWIMAwAAAFFTeXN0 + ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2Vu + PWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACJGYXN0Q29sb3JlZFRleHRCb3hOUy5TZXJ2aWNlQ29sb3JzBgAA + ACg8Q29sbGFwc2VNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxDb2xsYXBzZU1hcmtlckJh + Y2tDb2xvcj5rX19CYWNraW5nRmllbGQqPENvbGxhcHNlTWFya2VyQm9yZGVyQ29sb3I+a19fQmFja2lu + Z0ZpZWxkJjxFeHBhbmRNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkJjxFeHBhbmRNYXJrZXJC + YWNrQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxFeHBhbmRNYXJrZXJCb3JkZXJDb2xvcj5rX19CYWNraW5n + RmllbGQEBAQEBAQUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5EcmF3aW5nLkNvbG9yAwAA + ABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAAUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5E + cmF3aW5nLkNvbG9yAwAAABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAACAAAABfz///8UU3lzdGVtLkRy + YXdpbmcuQ29sb3IEAAAABG5hbWUFdmFsdWUKa25vd25Db2xvcgVzdGF0ZQEAAAAJBwcDAAAACgAAAAAA + AAAAlgABAAH7/////P///woAAAAAAAAAAKQAAQAB+v////z///8KAAAAAAAAAACWAAEAAfn////8//// + CgAAAAAAAAAATgABAAH4/////P///woAAAAAAAAAAKQAAQAB9/////z///8KAAAAAAAAAACWAAEACw== + + + + 386, 17 + + + 521, 17 + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/ModelForm.Designer.cs b/Forms/ModelForm.Designer.cs new file mode 100644 index 0000000..a67d0fe --- /dev/null +++ b/Forms/ModelForm.Designer.cs @@ -0,0 +1,674 @@ +namespace CodeWalker.Forms +{ + partial class ModelForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ModelForm)); + this.StatsUpdateTimer = new System.Windows.Forms.Timer(this.components); + this.StatusStrip = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.MousedLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.StatsLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.ConsolePanel = new System.Windows.Forms.Panel(); + this.ConsoleTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.ToolsPanel = new System.Windows.Forms.Panel(); + this.ToolsTabControl = new System.Windows.Forms.TabControl(); + this.ToolsModelsTabPage = new System.Windows.Forms.TabPage(); + this.ModelsTreeView = new CodeWalker.WinForms.TreeViewFix(); + this.ToolsTexturesTabPage = new System.Windows.Forms.TabPage(); + this.TexturesTreeView = new CodeWalker.WinForms.TreeViewFix(); + this.ToolsDetailsTabPage = new System.Windows.Forms.TabPage(); + this.DetailsPropertyGrid = new CodeWalker.WinForms.ReadOnlyPropertyGrid(); + this.ToolsOptionsTabPage = new System.Windows.Forms.TabPage(); + this.GridCheckBox = new System.Windows.Forms.CheckBox(); + this.GridCountComboBox = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.GridSizeComboBox = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.StatusBarCheckBox = new System.Windows.Forms.CheckBox(); + this.ErrorConsoleCheckBox = new System.Windows.Forms.CheckBox(); + this.HDRRenderingCheckBox = new System.Windows.Forms.CheckBox(); + this.SkydomeCheckBox = new System.Windows.Forms.CheckBox(); + this.ShadowsCheckBox = new System.Windows.Forms.CheckBox(); + this.WireframeCheckBox = new System.Windows.Forms.CheckBox(); + this.RenderModeComboBox = new System.Windows.Forms.ComboBox(); + this.label11 = new System.Windows.Forms.Label(); + this.TextureSamplerComboBox = new System.Windows.Forms.ComboBox(); + this.TextureCoordsComboBox = new System.Windows.Forms.ComboBox(); + this.label10 = new System.Windows.Forms.Label(); + this.AnisotropicFilteringCheckBox = new System.Windows.Forms.CheckBox(); + this.label14 = new System.Windows.Forms.Label(); + this.ToolsPanelHideButton = new System.Windows.Forms.Button(); + this.ToolsDragPanel = new System.Windows.Forms.Panel(); + this.ToolsPanelShowButton = new System.Windows.Forms.Button(); + this.ShowBoundsCheckBox = new System.Windows.Forms.CheckBox(); + this.ControlLightDirCheckBox = new System.Windows.Forms.CheckBox(); + this.TimeOfDayLabel = new System.Windows.Forms.Label(); + this.label19 = new System.Windows.Forms.Label(); + this.TimeOfDayTrackBar = new System.Windows.Forms.TrackBar(); + this.StatusStrip.SuspendLayout(); + this.ConsolePanel.SuspendLayout(); + this.ToolsPanel.SuspendLayout(); + this.ToolsTabControl.SuspendLayout(); + this.ToolsModelsTabPage.SuspendLayout(); + this.ToolsTexturesTabPage.SuspendLayout(); + this.ToolsDetailsTabPage.SuspendLayout(); + this.ToolsOptionsTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.TimeOfDayTrackBar)).BeginInit(); + this.SuspendLayout(); + // + // StatsUpdateTimer + // + this.StatsUpdateTimer.Enabled = true; + this.StatsUpdateTimer.Interval = 500; + this.StatsUpdateTimer.Tick += new System.EventHandler(this.StatsUpdateTimer_Tick); + // + // StatusStrip + // + this.StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel, + this.MousedLabel, + this.StatsLabel}); + this.StatusStrip.Location = new System.Drawing.Point(0, 582); + this.StatusStrip.Name = "StatusStrip"; + this.StatusStrip.Size = new System.Drawing.Size(877, 22); + this.StatusStrip.TabIndex = 1; + this.StatusStrip.Text = "statusStrip1"; + // + // StatusLabel + // + this.StatusLabel.BackColor = System.Drawing.SystemColors.Control; + this.StatusLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(771, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.Text = "Initialising"; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // MousedLabel + // + this.MousedLabel.BackColor = System.Drawing.SystemColors.Control; + this.MousedLabel.Name = "MousedLabel"; + this.MousedLabel.Size = new System.Drawing.Size(16, 17); + this.MousedLabel.Text = " "; + // + // StatsLabel + // + this.StatsLabel.BackColor = System.Drawing.SystemColors.Control; + this.StatsLabel.Name = "StatsLabel"; + this.StatsLabel.Size = new System.Drawing.Size(75, 17); + this.StatsLabel.Text = "0 geometries"; + // + // ConsolePanel + // + this.ConsolePanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ConsolePanel.BackColor = System.Drawing.SystemColors.Control; + this.ConsolePanel.Controls.Add(this.ConsoleTextBox); + this.ConsolePanel.Location = new System.Drawing.Point(272, 470); + this.ConsolePanel.Name = "ConsolePanel"; + this.ConsolePanel.Size = new System.Drawing.Size(593, 101); + this.ConsolePanel.TabIndex = 3; + this.ConsolePanel.Visible = false; + // + // ConsoleTextBox + // + this.ConsoleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ConsoleTextBox.Location = new System.Drawing.Point(3, 3); + this.ConsoleTextBox.Multiline = true; + this.ConsoleTextBox.Name = "ConsoleTextBox"; + this.ConsoleTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.ConsoleTextBox.Size = new System.Drawing.Size(587, 95); + this.ConsoleTextBox.TabIndex = 0; + // + // ToolsPanel + // + this.ToolsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.ToolsPanel.BackColor = System.Drawing.SystemColors.ControlDark; + this.ToolsPanel.Controls.Add(this.ToolsTabControl); + this.ToolsPanel.Controls.Add(this.ToolsPanelHideButton); + this.ToolsPanel.Controls.Add(this.ToolsDragPanel); + this.ToolsPanel.Location = new System.Drawing.Point(12, 12); + this.ToolsPanel.Name = "ToolsPanel"; + this.ToolsPanel.Size = new System.Drawing.Size(218, 559); + this.ToolsPanel.TabIndex = 2; + this.ToolsPanel.Visible = false; + // + // ToolsTabControl + // + this.ToolsTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ToolsTabControl.Controls.Add(this.ToolsModelsTabPage); + this.ToolsTabControl.Controls.Add(this.ToolsTexturesTabPage); + this.ToolsTabControl.Controls.Add(this.ToolsDetailsTabPage); + this.ToolsTabControl.Controls.Add(this.ToolsOptionsTabPage); + this.ToolsTabControl.Location = new System.Drawing.Point(2, 30); + this.ToolsTabControl.Name = "ToolsTabControl"; + this.ToolsTabControl.SelectedIndex = 0; + this.ToolsTabControl.Size = new System.Drawing.Size(213, 526); + this.ToolsTabControl.TabIndex = 1; + // + // ToolsModelsTabPage + // + this.ToolsModelsTabPage.Controls.Add(this.ModelsTreeView); + this.ToolsModelsTabPage.Location = new System.Drawing.Point(4, 22); + this.ToolsModelsTabPage.Name = "ToolsModelsTabPage"; + this.ToolsModelsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ToolsModelsTabPage.Size = new System.Drawing.Size(205, 500); + this.ToolsModelsTabPage.TabIndex = 0; + this.ToolsModelsTabPage.Text = "Models"; + this.ToolsModelsTabPage.UseVisualStyleBackColor = true; + // + // ModelsTreeView + // + this.ModelsTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ModelsTreeView.CheckBoxes = true; + this.ModelsTreeView.Location = new System.Drawing.Point(0, 3); + this.ModelsTreeView.Name = "ModelsTreeView"; + this.ModelsTreeView.ShowRootLines = false; + this.ModelsTreeView.Size = new System.Drawing.Size(205, 497); + this.ModelsTreeView.TabIndex = 1; + this.ModelsTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.ModelsTreeView_AfterCheck); + this.ModelsTreeView.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.ModelsTreeView_NodeMouseDoubleClick); + this.ModelsTreeView.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ModelsTreeView_KeyPress); + // + // ToolsTexturesTabPage + // + this.ToolsTexturesTabPage.Controls.Add(this.TexturesTreeView); + this.ToolsTexturesTabPage.Location = new System.Drawing.Point(4, 22); + this.ToolsTexturesTabPage.Name = "ToolsTexturesTabPage"; + this.ToolsTexturesTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ToolsTexturesTabPage.Size = new System.Drawing.Size(205, 500); + this.ToolsTexturesTabPage.TabIndex = 1; + this.ToolsTexturesTabPage.Text = "Textures"; + this.ToolsTexturesTabPage.UseVisualStyleBackColor = true; + // + // TexturesTreeView + // + this.TexturesTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TexturesTreeView.Location = new System.Drawing.Point(0, 3); + this.TexturesTreeView.Name = "TexturesTreeView"; + this.TexturesTreeView.ShowRootLines = false; + this.TexturesTreeView.Size = new System.Drawing.Size(205, 497); + this.TexturesTreeView.TabIndex = 1; + // + // ToolsDetailsTabPage + // + this.ToolsDetailsTabPage.Controls.Add(this.DetailsPropertyGrid); + this.ToolsDetailsTabPage.Location = new System.Drawing.Point(4, 22); + this.ToolsDetailsTabPage.Name = "ToolsDetailsTabPage"; + this.ToolsDetailsTabPage.Size = new System.Drawing.Size(205, 500); + this.ToolsDetailsTabPage.TabIndex = 2; + this.ToolsDetailsTabPage.Text = "Details"; + this.ToolsDetailsTabPage.UseVisualStyleBackColor = true; + // + // DetailsPropertyGrid + // + this.DetailsPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.DetailsPropertyGrid.HelpVisible = false; + this.DetailsPropertyGrid.Location = new System.Drawing.Point(0, 3); + this.DetailsPropertyGrid.Name = "DetailsPropertyGrid"; + this.DetailsPropertyGrid.PropertySort = System.Windows.Forms.PropertySort.NoSort; + this.DetailsPropertyGrid.ReadOnly = true; + this.DetailsPropertyGrid.Size = new System.Drawing.Size(205, 497); + this.DetailsPropertyGrid.TabIndex = 1; + this.DetailsPropertyGrid.ToolbarVisible = false; + // + // ToolsOptionsTabPage + // + this.ToolsOptionsTabPage.Controls.Add(this.TimeOfDayLabel); + this.ToolsOptionsTabPage.Controls.Add(this.label19); + this.ToolsOptionsTabPage.Controls.Add(this.TimeOfDayTrackBar); + this.ToolsOptionsTabPage.Controls.Add(this.ControlLightDirCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.ShowBoundsCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.GridCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.GridCountComboBox); + this.ToolsOptionsTabPage.Controls.Add(this.label2); + this.ToolsOptionsTabPage.Controls.Add(this.GridSizeComboBox); + this.ToolsOptionsTabPage.Controls.Add(this.label1); + this.ToolsOptionsTabPage.Controls.Add(this.StatusBarCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.ErrorConsoleCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.HDRRenderingCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.SkydomeCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.ShadowsCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.WireframeCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.RenderModeComboBox); + this.ToolsOptionsTabPage.Controls.Add(this.label11); + this.ToolsOptionsTabPage.Controls.Add(this.TextureSamplerComboBox); + this.ToolsOptionsTabPage.Controls.Add(this.TextureCoordsComboBox); + this.ToolsOptionsTabPage.Controls.Add(this.label10); + this.ToolsOptionsTabPage.Controls.Add(this.AnisotropicFilteringCheckBox); + this.ToolsOptionsTabPage.Controls.Add(this.label14); + this.ToolsOptionsTabPage.Location = new System.Drawing.Point(4, 22); + this.ToolsOptionsTabPage.Name = "ToolsOptionsTabPage"; + this.ToolsOptionsTabPage.Size = new System.Drawing.Size(205, 500); + this.ToolsOptionsTabPage.TabIndex = 3; + this.ToolsOptionsTabPage.Text = "Options"; + this.ToolsOptionsTabPage.UseVisualStyleBackColor = true; + // + // GridCheckBox + // + this.GridCheckBox.AutoSize = true; + this.GridCheckBox.Checked = true; + this.GridCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.GridCheckBox.Location = new System.Drawing.Point(19, 353); + this.GridCheckBox.Name = "GridCheckBox"; + this.GridCheckBox.Size = new System.Drawing.Size(45, 17); + this.GridCheckBox.TabIndex = 16; + this.GridCheckBox.Text = "Grid"; + this.GridCheckBox.UseVisualStyleBackColor = true; + this.GridCheckBox.CheckedChanged += new System.EventHandler(this.GridCheckBox_CheckedChanged); + // + // GridCountComboBox + // + this.GridCountComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.GridCountComboBox.FormattingEnabled = true; + this.GridCountComboBox.Items.AddRange(new object[] { + "20", + "40", + "60", + "100"}); + this.GridCountComboBox.Location = new System.Drawing.Point(83, 403); + this.GridCountComboBox.Name = "GridCountComboBox"; + this.GridCountComboBox.Size = new System.Drawing.Size(114, 21); + this.GridCountComboBox.TabIndex = 20; + this.GridCountComboBox.SelectedIndexChanged += new System.EventHandler(this.GridCountComboBox_SelectedIndexChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(7, 406); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(59, 13); + this.label2.TabIndex = 19; + this.label2.Text = "Grid count:"; + // + // GridSizeComboBox + // + this.GridSizeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.GridSizeComboBox.FormattingEnabled = true; + this.GridSizeComboBox.Items.AddRange(new object[] { + "0.1", + "1.0", + "10", + "100"}); + this.GridSizeComboBox.Location = new System.Drawing.Point(83, 376); + this.GridSizeComboBox.Name = "GridSizeComboBox"; + this.GridSizeComboBox.Size = new System.Drawing.Size(114, 21); + this.GridSizeComboBox.TabIndex = 18; + this.GridSizeComboBox.SelectedIndexChanged += new System.EventHandler(this.GridSizeComboBox_SelectedIndexChanged); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(7, 379); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(70, 13); + this.label1.TabIndex = 17; + this.label1.Text = "Grid unit size:"; + // + // StatusBarCheckBox + // + this.StatusBarCheckBox.AutoSize = true; + this.StatusBarCheckBox.Checked = true; + this.StatusBarCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.StatusBarCheckBox.Location = new System.Drawing.Point(19, 480); + this.StatusBarCheckBox.Name = "StatusBarCheckBox"; + this.StatusBarCheckBox.Size = new System.Drawing.Size(74, 17); + this.StatusBarCheckBox.TabIndex = 21; + this.StatusBarCheckBox.Text = "Status bar"; + this.StatusBarCheckBox.UseVisualStyleBackColor = true; + this.StatusBarCheckBox.CheckedChanged += new System.EventHandler(this.StatusBarCheckBox_CheckedChanged); + // + // ErrorConsoleCheckBox + // + this.ErrorConsoleCheckBox.AutoSize = true; + this.ErrorConsoleCheckBox.Location = new System.Drawing.Point(105, 480); + this.ErrorConsoleCheckBox.Name = "ErrorConsoleCheckBox"; + this.ErrorConsoleCheckBox.Size = new System.Drawing.Size(88, 17); + this.ErrorConsoleCheckBox.TabIndex = 22; + this.ErrorConsoleCheckBox.Text = "Error console"; + this.ErrorConsoleCheckBox.UseVisualStyleBackColor = true; + this.ErrorConsoleCheckBox.CheckedChanged += new System.EventHandler(this.ErrorConsoleCheckBox_CheckedChanged); + // + // HDRRenderingCheckBox + // + this.HDRRenderingCheckBox.AutoSize = true; + this.HDRRenderingCheckBox.Checked = true; + this.HDRRenderingCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.HDRRenderingCheckBox.Location = new System.Drawing.Point(19, 14); + this.HDRRenderingCheckBox.Name = "HDRRenderingCheckBox"; + this.HDRRenderingCheckBox.Size = new System.Drawing.Size(97, 17); + this.HDRRenderingCheckBox.TabIndex = 0; + this.HDRRenderingCheckBox.Text = "HDR rendering"; + this.HDRRenderingCheckBox.UseVisualStyleBackColor = true; + this.HDRRenderingCheckBox.CheckedChanged += new System.EventHandler(this.HDRRenderingCheckBox_CheckedChanged); + // + // SkydomeCheckBox + // + this.SkydomeCheckBox.AutoSize = true; + this.SkydomeCheckBox.Location = new System.Drawing.Point(19, 60); + this.SkydomeCheckBox.Name = "SkydomeCheckBox"; + this.SkydomeCheckBox.Size = new System.Drawing.Size(70, 17); + this.SkydomeCheckBox.TabIndex = 2; + this.SkydomeCheckBox.Text = "Skydome"; + this.SkydomeCheckBox.UseVisualStyleBackColor = true; + this.SkydomeCheckBox.CheckedChanged += new System.EventHandler(this.SkydomeCheckBox_CheckedChanged); + // + // ShadowsCheckBox + // + this.ShadowsCheckBox.AutoSize = true; + this.ShadowsCheckBox.Checked = true; + this.ShadowsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.ShadowsCheckBox.Location = new System.Drawing.Point(19, 37); + this.ShadowsCheckBox.Name = "ShadowsCheckBox"; + this.ShadowsCheckBox.Size = new System.Drawing.Size(70, 17); + this.ShadowsCheckBox.TabIndex = 1; + this.ShadowsCheckBox.Text = "Shadows"; + this.ShadowsCheckBox.UseVisualStyleBackColor = true; + this.ShadowsCheckBox.CheckedChanged += new System.EventHandler(this.ShadowsCheckBox_CheckedChanged); + // + // WireframeCheckBox + // + this.WireframeCheckBox.AutoSize = true; + this.WireframeCheckBox.Location = new System.Drawing.Point(19, 199); + this.WireframeCheckBox.Name = "WireframeCheckBox"; + this.WireframeCheckBox.Size = new System.Drawing.Size(74, 17); + this.WireframeCheckBox.TabIndex = 8; + this.WireframeCheckBox.Text = "Wireframe"; + this.WireframeCheckBox.UseVisualStyleBackColor = true; + this.WireframeCheckBox.CheckedChanged += new System.EventHandler(this.WireframeCheckBox_CheckedChanged); + // + // RenderModeComboBox + // + this.RenderModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.RenderModeComboBox.FormattingEnabled = true; + this.RenderModeComboBox.Items.AddRange(new object[] { + "Default", + "Single texture", + "Vertex normals", + "Vertex tangents", + "Vertex colour 1", + "Vertex colour 2", + "Texture coord 1", + "Texture coord 2", + "Texture coord 3"}); + this.RenderModeComboBox.Location = new System.Drawing.Point(83, 255); + this.RenderModeComboBox.Name = "RenderModeComboBox"; + this.RenderModeComboBox.Size = new System.Drawing.Size(114, 21); + this.RenderModeComboBox.TabIndex = 11; + this.RenderModeComboBox.SelectedIndexChanged += new System.EventHandler(this.RenderModeComboBox_SelectedIndexChanged); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(7, 285); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(67, 13); + this.label11.TabIndex = 12; + this.label11.Text = "Tex sampler:"; + // + // TextureSamplerComboBox + // + this.TextureSamplerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.TextureSamplerComboBox.Enabled = false; + this.TextureSamplerComboBox.FormattingEnabled = true; + this.TextureSamplerComboBox.Location = new System.Drawing.Point(83, 282); + this.TextureSamplerComboBox.Name = "TextureSamplerComboBox"; + this.TextureSamplerComboBox.Size = new System.Drawing.Size(114, 21); + this.TextureSamplerComboBox.TabIndex = 13; + this.TextureSamplerComboBox.SelectedIndexChanged += new System.EventHandler(this.TextureSamplerComboBox_SelectedIndexChanged); + // + // TextureCoordsComboBox + // + this.TextureCoordsComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.TextureCoordsComboBox.Enabled = false; + this.TextureCoordsComboBox.FormattingEnabled = true; + this.TextureCoordsComboBox.Items.AddRange(new object[] { + "Texture coord 1", + "Texture coord 2", + "Texture coord 3"}); + this.TextureCoordsComboBox.Location = new System.Drawing.Point(83, 309); + this.TextureCoordsComboBox.Name = "TextureCoordsComboBox"; + this.TextureCoordsComboBox.Size = new System.Drawing.Size(114, 21); + this.TextureCoordsComboBox.TabIndex = 15; + this.TextureCoordsComboBox.SelectedIndexChanged += new System.EventHandler(this.TextureCoordsComboBox_SelectedIndexChanged); + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(7, 258); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(74, 13); + this.label10.TabIndex = 10; + this.label10.Text = "Render mode:"; + // + // AnisotropicFilteringCheckBox + // + this.AnisotropicFilteringCheckBox.AutoSize = true; + this.AnisotropicFilteringCheckBox.Checked = true; + this.AnisotropicFilteringCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.AnisotropicFilteringCheckBox.Location = new System.Drawing.Point(19, 222); + this.AnisotropicFilteringCheckBox.Name = "AnisotropicFilteringCheckBox"; + this.AnisotropicFilteringCheckBox.Size = new System.Drawing.Size(114, 17); + this.AnisotropicFilteringCheckBox.TabIndex = 9; + this.AnisotropicFilteringCheckBox.Text = "Anisotropic filtering"; + this.AnisotropicFilteringCheckBox.UseVisualStyleBackColor = true; + this.AnisotropicFilteringCheckBox.CheckedChanged += new System.EventHandler(this.AnisotropicFilteringCheckBox_CheckedChanged); + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(7, 312); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(63, 13); + this.label14.TabIndex = 14; + this.label14.Text = "Tex coords:"; + // + // ToolsPanelHideButton + // + this.ToolsPanelHideButton.Location = new System.Drawing.Point(3, 3); + this.ToolsPanelHideButton.Name = "ToolsPanelHideButton"; + this.ToolsPanelHideButton.Size = new System.Drawing.Size(30, 23); + this.ToolsPanelHideButton.TabIndex = 0; + this.ToolsPanelHideButton.Text = "<<"; + this.ToolsPanelHideButton.UseVisualStyleBackColor = true; + this.ToolsPanelHideButton.Click += new System.EventHandler(this.ToolsPanelHideButton_Click); + // + // ToolsDragPanel + // + this.ToolsDragPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Right))); + this.ToolsDragPanel.Cursor = System.Windows.Forms.Cursors.VSplit; + this.ToolsDragPanel.Location = new System.Drawing.Point(215, 0); + this.ToolsDragPanel.Name = "ToolsDragPanel"; + this.ToolsDragPanel.Size = new System.Drawing.Size(4, 559); + this.ToolsDragPanel.TabIndex = 17; + this.ToolsDragPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ToolsDragPanel_MouseDown); + this.ToolsDragPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ToolsDragPanel_MouseMove); + this.ToolsDragPanel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ToolsDragPanel_MouseUp); + // + // ToolsPanelShowButton + // + this.ToolsPanelShowButton.Location = new System.Drawing.Point(15, 15); + this.ToolsPanelShowButton.Name = "ToolsPanelShowButton"; + this.ToolsPanelShowButton.Size = new System.Drawing.Size(30, 23); + this.ToolsPanelShowButton.TabIndex = 0; + this.ToolsPanelShowButton.Text = ">>"; + this.ToolsPanelShowButton.UseVisualStyleBackColor = true; + this.ToolsPanelShowButton.Click += new System.EventHandler(this.ToolsPanelShowButton_Click); + // + // ShowBoundsCheckBox + // + this.ShowBoundsCheckBox.AutoSize = true; + this.ShowBoundsCheckBox.Location = new System.Drawing.Point(19, 176); + this.ShowBoundsCheckBox.Name = "ShowBoundsCheckBox"; + this.ShowBoundsCheckBox.Size = new System.Drawing.Size(124, 17); + this.ShowBoundsCheckBox.TabIndex = 7; + this.ShowBoundsCheckBox.Text = "Show Model Bounds"; + this.ShowBoundsCheckBox.UseVisualStyleBackColor = true; + this.ShowBoundsCheckBox.CheckedChanged += new System.EventHandler(this.ShowBoundsCheckBox_CheckedChanged); + // + // ControlLightDirCheckBox + // + this.ControlLightDirCheckBox.AutoSize = true; + this.ControlLightDirCheckBox.Location = new System.Drawing.Point(19, 83); + this.ControlLightDirCheckBox.Name = "ControlLightDirCheckBox"; + this.ControlLightDirCheckBox.Size = new System.Drawing.Size(124, 17); + this.ControlLightDirCheckBox.TabIndex = 3; + this.ControlLightDirCheckBox.Text = "Control light direction"; + this.ControlLightDirCheckBox.UseVisualStyleBackColor = true; + this.ControlLightDirCheckBox.CheckedChanged += new System.EventHandler(this.ControlLightDirCheckBox_CheckedChanged); + // + // TimeOfDayLabel + // + this.TimeOfDayLabel.AutoSize = true; + this.TimeOfDayLabel.Location = new System.Drawing.Point(78, 109); + this.TimeOfDayLabel.Name = "TimeOfDayLabel"; + this.TimeOfDayLabel.Size = new System.Drawing.Size(34, 13); + this.TimeOfDayLabel.TabIndex = 5; + this.TimeOfDayLabel.Text = "12:00"; + // + // label19 + // + this.label19.AutoSize = true; + this.label19.Location = new System.Drawing.Point(7, 109); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(65, 13); + this.label19.TabIndex = 4; + this.label19.Text = "Time of day:"; + // + // TimeOfDayTrackBar + // + this.TimeOfDayTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TimeOfDayTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.TimeOfDayTrackBar.LargeChange = 60; + this.TimeOfDayTrackBar.Location = new System.Drawing.Point(9, 125); + this.TimeOfDayTrackBar.Maximum = 1440; + this.TimeOfDayTrackBar.Name = "TimeOfDayTrackBar"; + this.TimeOfDayTrackBar.Size = new System.Drawing.Size(188, 45); + this.TimeOfDayTrackBar.TabIndex = 6; + this.TimeOfDayTrackBar.TickFrequency = 60; + this.TimeOfDayTrackBar.Value = 720; + this.TimeOfDayTrackBar.Scroll += new System.EventHandler(this.TimeOfDayTrackBar_Scroll); + // + // ModelForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.MidnightBlue; + this.ClientSize = new System.Drawing.Size(877, 604); + this.Controls.Add(this.ToolsPanel); + this.Controls.Add(this.ConsolePanel); + this.Controls.Add(this.StatusStrip); + this.Controls.Add(this.ToolsPanelShowButton); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.KeyPreview = true; + this.Name = "ModelForm"; + this.Text = "View Model - CodeWalker by dexyfex"; + this.Load += new System.EventHandler(this.ModelForm_Load); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ModelForm_KeyDown); + this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ModelForm_KeyUp); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ModelForm_MouseDown); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ModelForm_MouseMove); + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ModelForm_MouseUp); + this.StatusStrip.ResumeLayout(false); + this.StatusStrip.PerformLayout(); + this.ConsolePanel.ResumeLayout(false); + this.ConsolePanel.PerformLayout(); + this.ToolsPanel.ResumeLayout(false); + this.ToolsTabControl.ResumeLayout(false); + this.ToolsModelsTabPage.ResumeLayout(false); + this.ToolsTexturesTabPage.ResumeLayout(false); + this.ToolsDetailsTabPage.ResumeLayout(false); + this.ToolsOptionsTabPage.ResumeLayout(false); + this.ToolsOptionsTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.TimeOfDayTrackBar)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Timer StatsUpdateTimer; + private System.Windows.Forms.StatusStrip StatusStrip; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.ToolStripStatusLabel MousedLabel; + private System.Windows.Forms.ToolStripStatusLabel StatsLabel; + private System.Windows.Forms.Panel ConsolePanel; + private WinForms.TextBoxFix ConsoleTextBox; + private System.Windows.Forms.Panel ToolsPanel; + private System.Windows.Forms.Panel ToolsDragPanel; + private System.Windows.Forms.Button ToolsPanelHideButton; + private System.Windows.Forms.Button ToolsPanelShowButton; + private System.Windows.Forms.TabControl ToolsTabControl; + private System.Windows.Forms.TabPage ToolsModelsTabPage; + private System.Windows.Forms.TabPage ToolsTexturesTabPage; + private System.Windows.Forms.TabPage ToolsDetailsTabPage; + private WinForms.TreeViewFix ModelsTreeView; + private WinForms.ReadOnlyPropertyGrid DetailsPropertyGrid; + private WinForms.TreeViewFix TexturesTreeView; + private System.Windows.Forms.TabPage ToolsOptionsTabPage; + private System.Windows.Forms.CheckBox WireframeCheckBox; + private System.Windows.Forms.ComboBox RenderModeComboBox; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.ComboBox TextureSamplerComboBox; + private System.Windows.Forms.ComboBox TextureCoordsComboBox; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.CheckBox AnisotropicFilteringCheckBox; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.CheckBox HDRRenderingCheckBox; + private System.Windows.Forms.CheckBox SkydomeCheckBox; + private System.Windows.Forms.CheckBox ShadowsCheckBox; + private System.Windows.Forms.CheckBox StatusBarCheckBox; + private System.Windows.Forms.CheckBox ErrorConsoleCheckBox; + private System.Windows.Forms.CheckBox GridCheckBox; + private System.Windows.Forms.ComboBox GridCountComboBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox GridSizeComboBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.CheckBox ShowBoundsCheckBox; + private System.Windows.Forms.CheckBox ControlLightDirCheckBox; + private System.Windows.Forms.Label TimeOfDayLabel; + private System.Windows.Forms.Label label19; + private System.Windows.Forms.TrackBar TimeOfDayTrackBar; + } +} \ No newline at end of file diff --git a/Forms/ModelForm.cs b/Forms/ModelForm.cs new file mode 100644 index 0000000..df19cda --- /dev/null +++ b/Forms/ModelForm.cs @@ -0,0 +1,2570 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using CodeWalker.Rendering; +using CodeWalker.World; +using SharpDX; +using SharpDX.Direct3D11; +using SharpDX.XInput; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class ModelForm : Form, DXForm + { + public Form Form { get { return this; } } //for DXForm/DXManager use + DXManager dxman = new DXManager(); + public DXManager DXMan { get { return dxman; } } + Device currentdevice; + public Device Device { get { return currentdevice; } } + object rendersyncroot = new object(); + public object RenderSyncRoot { get { return rendersyncroot; } } + + ShaderManager shaders; + + volatile bool formopen = false; + //volatile bool running = false; + volatile bool pauserendering = false; + //volatile bool initialised = false; + + Stopwatch frametimer = new Stopwatch(); + Camera camera = new Camera(); + Timecycle timecycle = new Timecycle(); + Weather weather = new Weather(); + Clouds clouds = new Clouds(); + + bool MouseLButtonDown = false; + bool MouseRButtonDown = false; + int MouseX; + int MouseY; + System.Drawing.Point MouseDownPoint; + System.Drawing.Point MouseLastPoint; + + + + //public GameFileCache GameFileCache { get { return gameFileCache; } } + //GameFileCache gameFileCache = new GameFileCache(); + RenderableCache renderableCache = new RenderableCache(); + + + Vector3 prevworldpos = new Vector3(0, 0, 0); //also the start pos + + Entity camEntity = new Entity(); + volatile bool kbmovefwd = false; + volatile bool kbmovebck = false; + volatile bool kbmovelft = false; + volatile bool kbmovergt = false; + volatile bool kbmoveup = false; + volatile bool kbmovedn = false; + volatile bool kbjump = false; + + KeyBindings keyBindings = new KeyBindings(Settings.Default.KeyBindings); + //bool iseditmode = false; + + + float timeofday = 12.0f; + bool controltimeofday = true; + bool timerunning = false; + float timespeed = 0.5f;//min/sec + //string weathertype = ""; + string individualcloudfrag = "contrails"; + Vector4 currentWindVec = Vector4.Zero; + float currentWindTime = 0.0f; + + bool controllightdir = !Settings.Default.Skydome;//true; //if not, use timecycle + float lightdirx = 2.25f;//radians // approx. light dir on map satellite view + float lightdiry = 0.65f;//radians - used for manual light placement + bool renderskydome = Settings.Default.Skydome; + + bool rendernaturalambientlight = true; + bool renderartificialambientlight = true; + ShaderGlobalLights globalLights = new ShaderGlobalLights(); + + double currentRealTime = 0; + int framecount = 0; + float fcelapsed = 0.0f; + int fps = 0; + + bool initedOk = false; + + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + YdrFile Ydr = null; + YddFile Ydd = null; + YftFile Yft = null; + YbnFile Ybn = null; + YptFile Ypt = null; + YnvFile Ynv = null; + + bool waitforchildrentoload = true; + bool rendercollisionmeshes = false;// Settings.Default.ShowCollisionMeshes; + + bool CtrlPressed = false; + bool ShiftPressed = false; + + Controller xbcontroller = null; + State xbcontrollerstate; + State xbcontrollerstateprev; + Vector4 xbmainaxes = Vector4.Zero; + Vector4 xbmainaxesprev = Vector4.Zero; + Vector2 xbtrigs = Vector2.Zero; + Vector2 xbtrigsprev = Vector2.Zero; + float xbcontrolvelocity = 0.0f; + + bool toolsPanelResizing = false; + int toolsPanelResizeStartX = 0; + int toolsPanelResizeStartLeft = 0; + int toolsPanelResizeStartRight = 0; + + Dictionary DrawableDrawFlags = new Dictionary(); + Dictionary ModelDrawFlags = new Dictionary(); + Dictionary GeometryDrawFlags = new Dictionary(); + + + bool enableGrid = true; + float gridSize = 1.0f; + int gridCount = 40; + List gridVerts = new List(); + object gridSyncRoot = new object(); + + GameFileCache gameFileCache = null; + Archetype currentArchetype = null; + bool updateArchetypeStatus = true; + + + public ModelForm(ExploreForm ExpForm = null) + { + InitializeComponent(); + + + gameFileCache = ExpForm?.GetFileCache(); + + initedOk = dxman.Init(this, false); + } + + private void Init() + { + //called from WorldForm_Load + + if (!initedOk) + { + Close(); + return; + } + + + MouseWheel += ModelForm_MouseWheel; + + string fldr = Settings.Default.GTAFolder; + if (string.IsNullOrEmpty(fldr) || !Directory.Exists(fldr)) + { + SelectFolderForm f = new SelectFolderForm(); + f.ShowDialog(); + if (f.Result == DialogResult.OK) + { + fldr = f.SelectedFolder; + } + else + { + Close(); + return; + } + } + if (!Directory.Exists(fldr)) + { + MessageBox.Show("The specified folder does not exist:\n" + fldr); + Close(); + return; + } + if (!File.Exists(fldr + "\\gta5.exe")) + { + MessageBox.Show("GTA5.exe not found in folder:\n" + fldr); + Close(); + return; + } + + Settings.Default.GTAFolder = fldr; //seems ok, save it for later + + + + + MetaName[] texsamplers = RenderableGeometry.GetTextureSamplerList(); + foreach (var texsampler in texsamplers) + { + TextureSamplerComboBox.Items.Add(texsampler); + } + //TextureSamplerComboBox.SelectedIndex = 0;//LoadSettings will do this.. + + + UpdateGridVerts(); + GridSizeComboBox.SelectedIndex = 1; + GridCountComboBox.SelectedIndex = 1; + + + + InitController(); + + + dxman.Start(); + } + + private void InitController() + { + xbcontroller = new Controller(UserIndex.One); + if (!xbcontroller.IsConnected) + { + var controllers = new[] { new Controller(UserIndex.Two), new Controller(UserIndex.Three), new Controller(UserIndex.Four) }; + foreach (var selectControler in controllers) + { + if (selectControler.IsConnected) + { + xbcontroller = selectControler; + xbcontrollerstate = xbcontroller.GetState(); + xbcontrollerstateprev = xbcontrollerstate; + break; + } + } + } + else + { + xbcontrollerstate = xbcontroller.GetState(); + xbcontrollerstateprev = xbcontrollerstate; + } + + } + + + public void InitScene(Device device) + { + currentdevice = device; + + int width = ClientSize.Width; + int height = ClientSize.Height; + + try + { + shaders = new ShaderManager(device, dxman); + shaders.OnWindowResize(width, height); //init the buffers + } + catch (Exception ex) + { + MessageBox.Show("Error loading shaders!\n" + ex.ToString()); + return; + } + + //shaders.hdrLumBlendSpeed = 1000.0f; + + renderableCache.OnDeviceCreated(device); + + camera.OnWindowResize(width, height); //init the projection stuff + camera.FollowEntity = camEntity; + camera.FollowEntity.Position = prevworldpos; + camera.FollowEntity.Orientation = Quaternion.LookAtLH(Vector3.Zero, Vector3.Up, Vector3.ForwardLH); + camera.TargetDistance = 2.0f; + camera.CurrentDistance = 2.0f; + camera.TargetRotation.Y = 0.2f; + camera.CurrentRotation.Y = 0.2f; + + LoadSettings(); + + + formopen = true; + new Thread(new ThreadStart(ContentThread)).Start(); + + frametimer.Start(); + } + public void CleanupScene() + { + formopen = false; + + renderableCache.OnDeviceDestroyed(); + + shaders.Dispose(); + + + //int count = 0; + //while (running && (count < 5000)) //wait for the content thread to exit gracefully + //{ + // Thread.Sleep(1); + // count++; + //} + + currentdevice = null; + } + public void BuffersResized(int w, int h) + { + lock (rendersyncroot) + { + camera.OnWindowResize(w, h); + shaders.OnWindowResize(w, h); + } + } + public void RenderScene(DeviceContext context) + { + float elapsed = (float)frametimer.Elapsed.TotalSeconds; + framecount++; + fcelapsed += elapsed; + if (fcelapsed >= 0.5f) + { + fps = framecount * 2; + framecount = 0; + fcelapsed -= 0.5f; + } + if (elapsed > 0.1f) elapsed = 0.1f; + frametimer.Restart(); + + currentRealTime += elapsed; + + if (pauserendering) return; + + if (!Monitor.TryEnter(rendersyncroot, 50)) + { return; } //couldn't get a lock, try again next time + //Monitor.Enter(rendersyncroot); + + UpdateControlInputs(elapsed); + + UpdateTimeOfDay(elapsed); + + weather.Update(elapsed); + + //clouds.Update(elapsed); + + UpdateWindVector(elapsed); + + UpdateGlobalLights(); + + camera.SetMousePosition(MouseLastPoint.X, MouseLastPoint.Y); + + camera.Update(elapsed); + + //UpdateWidgets(); + + //HilightBoxes.Clear(); + //BoundingBoxes.Clear(); + //BoundingSpheres.Clear(); + //BeginMouseHitTest(); + + + dxman.ClearRenderTarget(context); + + shaders.BeginFrame(context, currentRealTime, elapsed); + + shaders.EnsureShaderTextures(gameFileCache, renderableCache); + + RenderSky(context); + + //RenderClouds(context); + + shaders.ClearDepth(context); + + //if (renderworld || rendermaps) + //{ + // RenderWorld(); + // if (rendermaps) + // { + // RenderYmaps(); + // } + //} + //else + //{ + RenderSingleItem(); + //} + + RenderGrid(context); + + shaders.RenderQueued(context, camera, currentWindVec); + + //RenderBounds(context); + + //RenderSelection(context); + + //RenderMoused(context); + + //RenderSelectionGeometry(context); + + shaders.RenderFinalPass(context); + + //RenderMarkers(context); + + //RenderWidgets(context); + + renderableCache.RenderThreadSync(); + + Monitor.Exit(rendersyncroot); + + //UpdateMarkerSelectionPanelInvoke(); + } + + + private void ContentThread() + { + //main content loading thread. + //running = true; + + //UpdateStatus("Scanning..."); + + //try + //{ + // GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); //now loads from magic + //} + //catch + //{ + // MessageBox.Show("Keys not found! This shouldn't happen."); + // Close(); + // return; + //} + + //gameFileCache.Init(UpdateStatus, LogError); + + ////UpdateDlcListComboBox(gameFileCache.DlcNameList); + ////EnableCacheDependentUI(); + ////LoadWorld(); + + + //initialised = true; + + ////EnableDLCModsUI(); + + UpdateStatus("Ready"); + + + while (formopen && !IsDisposed) //main asset loop + { + + if ((gameFileCache != null) && (gameFileCache.IsInited)) + { + if (!timecycle.Inited) + { + //UpdateStatus("Loading timecycles..."); + timecycle.Init(gameFileCache, UpdateStatus); + timecycle.SetTime(timeofday); + //UpdateStatus("Timecycles loaded."); + } + if (renderskydome) + { + if (!weather.Inited) + { + //UpdateStatus("Loading weather..."); + weather.Init(gameFileCache, UpdateStatus, timecycle); + //UpdateStatus("Weather loaded."); + } + //if (!clouds.Inited) + //{ + // UpdateStatus("Loading clouds..."); + // clouds.Init(gameFileCache, UpdateStatus, weather); + // UpdateStatus("Clouds loaded."); + //} + } + } + + + + //if ((gameFileCache != null) && (gameFileCache.IsInited)) + //{ + // gameFileCache.ContentThreadProc(); + //} + + renderableCache.ContentThreadProc(); + + if (!(renderableCache.ItemsStillPending)) //gameFileCache.ItemsStillPending || + { + Thread.Sleep(1); //sleep if there's nothing to do + } + } + + //gameFileCache.Clear(); + + //running = false; + } + + + + + + + private void LoadSettings() + { + var s = Settings.Default; + //WindowState = s.WindowMaximized ? FormWindowState.Maximized : WindowState; + //FullScreenCheckBox.Checked = s.FullScreen; + WireframeCheckBox.Checked = s.Wireframe; + HDRRenderingCheckBox.Checked = s.HDR; + ShadowsCheckBox.Checked = s.Shadows; + SkydomeCheckBox.Checked = s.Skydome; + RenderModeComboBox.SelectedIndex = Math.Max(RenderModeComboBox.FindString(s.RenderMode), 0); + TextureSamplerComboBox.SelectedIndex = Math.Max(TextureSamplerComboBox.FindString(s.RenderTextureSampler), 0); + TextureCoordsComboBox.SelectedIndex = Math.Max(TextureCoordsComboBox.FindString(s.RenderTextureSamplerCoord), 0); + AnisotropicFilteringCheckBox.Checked = s.AnisotropicFiltering; + //ErrorConsoleCheckBox.Checked = s.ShowErrorConsole; + //StatusBarCheckBox.Checked = s.ShowStatusBar; + } + + + + + + + + + private void RenderSky(DeviceContext context) + { + if (!renderskydome) return; + if (!weather.Inited) return; + + var shader = shaders.Skydome; + shader.UpdateSkyLocals(weather, globalLights); + + + + + DrawableBase skydomeydr = null; + YddFile skydomeydd = gameFileCache.GetYdd(2640562617); //skydome hash + if ((skydomeydd != null) && (skydomeydd.Loaded) && (skydomeydd.Dict != null)) + { + skydomeydr = skydomeydd.Dict.Values.FirstOrDefault(); + } + + Texture starfield = null; + //Texture moon = null; + YtdFile skydomeytd = gameFileCache.GetYtd(2640562617); //skydome hash + if ((skydomeytd != null) && (skydomeytd.Loaded) && (skydomeytd.TextureDict != null) && (skydomeytd.TextureDict.Dict != null)) + { + skydomeytd.TextureDict.Dict.TryGetValue(1064311147, out starfield); //starfield hash + //skydomeytd.TextureDict.Dict.TryGetValue(234339206, out moon); //moon-new hash + } + + Renderable sdrnd = null; + if (skydomeydr != null) + { + sdrnd = renderableCache.GetRenderable(skydomeydr); + } + + RenderableTexture sftex = null; + if (starfield != null) + { + sftex = renderableCache.GetRenderableTexture(starfield); + } + + //RenderableTexture moontex = null; + //if (moon != null) + //{ + // moontex = renderableCache.GetRenderableTexture(moon); + //} + + if ((sdrnd != null) && (sdrnd.IsLoaded) && (sftex != null) && (sftex.IsLoaded)) + { + shaders.SetDepthStencilMode(context, DepthStencilMode.DisableAll); + shaders.SetRasterizerMode(context, RasterizerMode.Solid); + + RenderableInst rinst = new RenderableInst(); + rinst.Position = Vector3.Zero; + rinst.CamRel = Vector3.Zero; + rinst.Distance = 0.0f; + rinst.BBMin = skydomeydr.BoundingBoxMin.XYZ(); + rinst.BBMax = skydomeydr.BoundingBoxMax.XYZ(); + rinst.BSCenter = Vector3.Zero; + rinst.Radius = skydomeydr.BoundingSphereRadius; + rinst.Orientation = Quaternion.Identity; + rinst.Scale = Vector3.One; + rinst.TintPaletteIndex = 0; + rinst.Renderable = sdrnd; + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.PTT); + shader.SetSceneVars(context, camera, null, globalLights); + shader.SetEntityVars(context, ref rinst); + + RenderableModel rmod = ((sdrnd.HDModels != null) && (sdrnd.HDModels.Length > 0)) ? sdrnd.HDModels[0] : null; + RenderableGeometry rgeom = ((rmod != null) && (rmod.Geometries != null) && (rmod.Geometries.Length > 0)) ? rmod.Geometries[0] : null; + + if ((rgeom != null) && (rgeom.VertexType == VertexType.PTT)) + { + shader.SetModelVars(context, rmod); + shader.SetTextures(context, sftex); + + rgeom.Render(context); + } + + //shaders.SetRasterizerMode(context, RasterizerMode.SolidDblSided); + //shaders.SetDepthStencilMode(context, DepthStencilMode.Enabled); + shader.RenderSun(context, camera, weather, globalLights); + + + //if ((moontex != null) && (moontex.IsLoaded)) + //{ + // shader.RenderMoon(context, camera, weather, globalLights, moontex); + //} + + + + shader.UnbindResources(context); + } + + } + + private void RenderClouds(DeviceContext context) + { + if (!renderskydome) return; + if (!weather.Inited) return; + if (!clouds.Inited) return; + + + var shader = shaders.Clouds; + + shaders.SetDepthStencilMode(context, DepthStencilMode.DisableAll); + shaders.SetRasterizerMode(context, RasterizerMode.Solid); + shaders.SetDefaultBlendState(context); + //shaders.SetAlphaBlendState(context); + + shader.SetShader(context); + shader.UpdateCloudsLocals(clouds, globalLights); + shader.SetSceneVars(context, camera, null, globalLights); + + var vtype = (VertexType)0; + + if (!string.IsNullOrEmpty(individualcloudfrag)) + { + //render one cloud fragment. + + CloudHatFrag frag = clouds.HatManager.FindFrag(individualcloudfrag); + if (frag == null) return; + + for (int i = 0; i < frag.Layers.Length; i++) + { + CloudHatFragLayer layer = frag.Layers[i]; + uint dhash = JenkHash.GenHash(layer.Filename.ToLower()); + Archetype arch = gameFileCache.GetArchetype(dhash); + if (arch == null) + { continue; } + + if (Math.Max(camera.Position.Z, 0.0f) < layer.HeightTigger) continue; + + var drw = TryGetDrawable(arch); + var rnd = TryGetRenderable(arch, drw); + + if ((rnd == null) || (rnd.IsLoaded == false) || (rnd.AllTexturesLoaded == false)) + { continue; } + + + RenderableInst rinst = new RenderableInst(); + rinst.Position = frag.Position;// Vector3.Zero; + rinst.CamRel = Vector3.Zero;// - camera.Position; + rinst.Distance = rinst.CamRel.Length(); + rinst.BBMin = arch.BBMin; + rinst.BBMax = arch.BBMax; + rinst.BSCenter = frag.Position; + rinst.Radius = arch.BSRadius; + rinst.Orientation = Quaternion.Identity; + rinst.Scale = frag.Scale;// Vector3.One; + rinst.TintPaletteIndex = 0; + rinst.Renderable = rnd; + + shader.SetEntityVars(context, ref rinst); + + + for (int mi = 0; mi < rnd.HDModels.Length; mi++) + { + var model = rnd.HDModels[mi]; + + for (int gi = 0; gi < model.Geometries.Length; gi++) + { + var geom = model.Geometries[gi]; + + if (geom.VertexType != vtype) + { + vtype = geom.VertexType; + shader.SetInputLayout(context, vtype); + } + + shader.SetGeomVars(context, geom); + + geom.Render(context); + } + } + + } + + + } + + + + } + + + + + + + + private void UpdateGridVerts() + { + lock (gridSyncRoot) + { + gridVerts.Clear(); + + float s = gridSize * gridCount * 0.5f; + uint cblack = (uint)SharpDX.Color.Black.ToRgba(); + uint cgray = (uint)SharpDX.Color.DimGray.ToRgba(); + uint cred = (uint)SharpDX.Color.DarkRed.ToRgba(); + uint cgrn = (uint)SharpDX.Color.DarkGreen.ToRgba(); + int interval = 10; + + for (int i = 0; i <= gridCount; i++) + { + float o = (gridSize * i) - s; + if ((i % interval) != 0) + { + gridVerts.Add(new VertexTypePC() { Position = new Vector3(o, -s, 0), Colour = cgray }); + gridVerts.Add(new VertexTypePC() { Position = new Vector3(o, s, 0), Colour = cgray }); + gridVerts.Add(new VertexTypePC() { Position = new Vector3(-s, o, 0), Colour = cgray }); + gridVerts.Add(new VertexTypePC() { Position = new Vector3(s, o, 0), Colour = cgray }); + } + } + for (int i = 0; i <= gridCount; i++) //draw main lines last, so they are on top + { + float o = (gridSize * i) - s; + if ((i % interval) == 0) + { + var cx = (o == 0) ? cred : cblack; + var cy = (o == 0) ? cgrn : cblack; + gridVerts.Add(new VertexTypePC() { Position = new Vector3(o, -s, 0), Colour = cy }); + gridVerts.Add(new VertexTypePC() { Position = new Vector3(o, s, 0), Colour = cy }); + gridVerts.Add(new VertexTypePC() { Position = new Vector3(-s, o, 0), Colour = cx }); + gridVerts.Add(new VertexTypePC() { Position = new Vector3(s, o, 0), Colour = cx }); + } + } + + } + } + + private void RenderGrid(DeviceContext context) + { + if (!enableGrid) return; + + lock (gridSyncRoot) + { + if (gridVerts.Count > 0) + { + shaders.SetDepthStencilMode(context, DepthStencilMode.Enabled); + shaders.Paths.RenderLines(context, gridVerts, camera, shaders.GlobalLights); + } + } + } + + + + private void RenderSingleItem() + { + + uint hash = 0; + Archetype arch = null; + + if (Ydr != null) + { + if (Ydr.Loaded) + { + hash = Ydr?.RpfFileEntry?.ShortNameHash ?? 0; + arch = TryGetArchetype(hash); + + RenderDrawable(Ydr.Drawable, arch, null, -camera.Position, hash); + } + } + else if (Ydd != null) + { + //render selected drawable(s)... + if (Ydd.Loaded) + { + foreach (var kvp in Ydd.Dict) + { + if (!DrawableDrawFlags.ContainsKey(kvp.Value))//only render if it's checked... + { + arch = TryGetArchetype(kvp.Key); + + RenderDrawable(kvp.Value, arch, null, -camera.Position, Ydd.RpfFileEntry.ShortNameHash); + } + } + } + } + else if (Ypt != null) + { + if ((Ypt.Loaded) && (Ypt.DrawableDict != null)) + { + foreach (var kvp in Ypt.DrawableDict) + { + if (!DrawableDrawFlags.ContainsKey(kvp.Value))//only render if it's checked... + { + arch = TryGetArchetype(kvp.Key); + + RenderDrawable(kvp.Value, arch, null, -camera.Position, kvp.Key); + } + } + } + } + else if (Yft != null) + { + if (Yft.Loaded) + { + if (Yft.Fragment != null) + { + var f = Yft.Fragment; + + hash = Yft?.RpfFileEntry?.ShortNameHash ?? 0; + arch = TryGetArchetype(hash); + + RenderDrawable(f.Drawable, arch, null, -camera.Position, hash); + + if (f.Unknown_F8h_Data != null) //cloth + { + RenderDrawable(f.Unknown_F8h_Data, arch, null, -camera.Position, hash); + } + //vehicle wheels... + if ((f.PhysicsLODGroup != null) && (f.PhysicsLODGroup.PhysicsLOD1 != null)) + { + var pl1 = f.PhysicsLODGroup.PhysicsLOD1; + if ((pl1.Children != null) && (pl1.Children.data_items != null)) + { + for (int i = 0; i < pl1.Children.data_items.Length; i++) + { + var pch = pl1.Children.data_items[i]; + if ((pch.Drawable1 != null) && (pch.Drawable1.AllModels.Length != 0)) + { + //RenderDrawable(pch.Drawable1, null, null, -camera.Position, hash); + } + } + } + } + } + } + } + else if (Ybn != null) + { + if (Ybn.Loaded) + { + RenderCollisionMesh(Ybn.Bounds, null); + } + } + else if (Ypt != null) + { + if (Ypt.Loaded) + { + } + } + else if (Ynv != null) + { + if (Ynv.Loaded) + { + RenderNavmesh(Ynv); + } + } + + + } + + + + + + + public void LoadModel(YdrFile ydr) + { + if (ydr == null) return; + + FileName = ydr.Name; + Ydr = ydr; + + UpdateModelsUI(ydr.Drawable); + } + public void LoadModels(YddFile ydd) + { + if (ydd == null) return; + + FileName = ydd.Name; + Ydd = ydd; + + UpdateModelsUI(ydd.Dict); + + DetailsPropertyGrid.SelectedObject = ydd; + } + public void LoadModel(YftFile yft) + { + if (yft == null) return; + + FileName = yft.Name; + Yft = yft; + + UpdateModelsUI(yft.Fragment.Drawable); + } + public void LoadModel(YbnFile ybn) + { + if (ybn == null) return; + + FileName = ybn.Name; + Ybn = ybn; + + UpdateBoundsUI(ybn.Bounds); + } + public void LoadParticles(YptFile ypt) + { + if (ypt == null) return; + + FileName = ypt.Name; + Ypt = ypt; + + UpdateModelsUI(ypt.DrawableDict); + + DetailsPropertyGrid.SelectedObject = ypt;//.PtfxList; + } + public void LoadNavmesh(YnvFile ynv) + { + if (ynv == null) return; + + FileName = ynv.Name; + Ynv = ynv; + + //UpdateModelsUI(ypt.Particles.Drawable); + } + + + + + + + + + private void UpdateFormTitle() + { + Text = fileName + " - CodeWalker by dexyfex"; + } + + + + private void UpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateStatus(text); })); + } + else + { + StatusLabel.Text = text; + } + } + catch { } + } + + private void LogError(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { LogError(text); })); + } + else + { + ConsoleTextBox.AppendText(text + "\r\n"); + } + } + catch { } + } + + + + + private void UpdateTimeOfDayLabel() + { + int v = TimeOfDayTrackBar.Value; + float fh = v / 60.0f; + int ih = (int)fh; + int im = v - (ih * 60); + if (ih == 24) ih = 0; + TimeOfDayLabel.Text = string.Format("{0:00}:{1:00}", ih, im); + } + + private void UpdateTimeOfDay(float elapsed) + { + if (timerunning) + { + float helapsed = elapsed * timespeed / 60.0f; + timeofday += helapsed; + while (timeofday >= 24.0f) timeofday -= 24.0f; + while (timeofday < 0.0f) timeofday += 24.0f; + timecycle.SetTime(timeofday); + } + + } + + private void UpdateGlobalLights() + { + Vector3 lightdir = Vector3.Zero;//will be updated before each frame from X and Y vars + Color4 lightdircolour = Color4.White; + Color4 lightdirambcolour = new Color4(0.5f, 0.5f, 0.5f, 1.0f); + Color4 lightnaturalupcolour = new Color4(0.0f); + Color4 lightnaturaldowncolour = new Color4(0.0f); + Color4 lightartificialupcolour = new Color4(0.0f); + Color4 lightartificialdowncolour = new Color4(0.0f); + bool hdr = shaders.hdr; + float hdrint = 1.0f; + Vector3 sundir = Vector3.Up; + Vector3 moondir = Vector3.Down; + Vector3 moonax = Vector3.UnitZ; + + if (controllightdir || !timecycle.Inited) + { + float cryd = (float)Math.Cos(lightdiry); + lightdir.X = -(float)Math.Sin(-lightdirx) * cryd; + lightdir.Y = -(float)Math.Cos(-lightdirx) * cryd; + lightdir.Z = (float)Math.Sin(lightdiry); + lightdircolour = Color4.White; + lightdirambcolour = new Color4(0.5f, 0.5f, 0.5f, 1.0f); + if (hdr && weather.Inited) + { + lightdircolour *= weather.CurrentValues.skyHdr; + lightdircolour.Alpha = 1.0f; + lightdirambcolour *= weather.CurrentValues.skyHdr; + lightdirambcolour.Alpha = 1.0f; + hdrint = weather.CurrentValues.skyHdr; + } + sundir = lightdir; + moondir = -lightdir; + moonax = Vector3.Normalize(Vector3.UnitY); + } + else + { + float sunroll = timecycle.sun_roll * (float)Math.PI / 180.0f; //122 + float moonroll = timecycle.moon_roll * (float)Math.PI / 180.0f; //-122 + float moonwobamp = timecycle.moon_wobble_amp; //0.2 + float moonwobfreq = timecycle.moon_wobble_freq; //2 + float moonwoboffs = timecycle.moon_wobble_offset; //0.375 + float dayval = (0.5f + (timeofday - 6.0f) / 14.0f); + float nightval = (((timeofday > 12.0f) ? (timeofday - 7.0f) : (timeofday + 17.0f)) / 9.0f); + float daycyc = (float)Math.PI * dayval; + float nightcyc = (float)Math.PI * nightval; + Vector3 sdir = new Vector3((float)Math.Sin(daycyc), -(float)Math.Cos(daycyc), 0.0f); + Vector3 mdir = new Vector3(-(float)Math.Sin(nightcyc), 0.0f, -(float)Math.Cos(nightcyc)); + Quaternion saxis = Quaternion.RotationYawPitchRoll(0.0f, sunroll, 0.0f); + Quaternion maxis = Quaternion.RotationYawPitchRoll(0.0f, -moonroll, 0.0f); + sundir = Vector3.Normalize(saxis.Multiply(sdir)); + moondir = Vector3.Normalize(maxis.Multiply(mdir)); + moonax = Vector3.Normalize(maxis.Multiply(Vector3.UnitY)); + //bool usemoon = false; + + lightdir = sundir; + + //if (lightdir.Z < -0.5f) lightdir.Z = -lightdir.Z; //make sure the lightsource is always above the horizon... + + if ((timeofday < 5.0f) || (timeofday > 21.0f)) + { + lightdir = moondir; + //usemoon = true; + } + + if (lightdir.Z < 0) + { + lightdir.Z = 0; //don't let the light source go below the horizon... + } + + //lightdir = Vector3.Normalize(weather.CurrentValues.sunDirection); + + if (weather != null && weather.Inited) + { + lightdircolour = (Color4)weather.CurrentValues.lightDirCol; + lightdirambcolour = (Color4)weather.CurrentValues.lightDirAmbCol; + lightnaturalupcolour = (Color4)weather.CurrentValues.lightNaturalAmbUp; + lightnaturaldowncolour = (Color4)weather.CurrentValues.lightNaturalAmbDown; + lightartificialupcolour = (Color4)weather.CurrentValues.lightArtificialExtUp; + lightartificialdowncolour = (Color4)weather.CurrentValues.lightArtificialExtDown; + float lamult = weather.CurrentValues.lightDirAmbIntensityMult; + float abounce = weather.CurrentValues.lightDirAmbBounce; + float minmult = hdr ? 0.1f : 0.5f; + lightdircolour *= Math.Max(lightdircolour.Alpha, minmult); + lightdirambcolour *= lightdirambcolour.Alpha * lamult; // 0.1f * lamult; + + //if (usemoon) + //{ + // lightdircolour *= weather.CurrentValues.skyMoonIten; + //} + + + lightnaturalupcolour *= lightnaturalupcolour.Alpha * weather.CurrentValues.lightNaturalAmbUpIntensityMult; + lightnaturaldowncolour *= lightnaturaldowncolour.Alpha; + lightartificialupcolour *= lightartificialupcolour.Alpha; + lightartificialdowncolour *= lightartificialdowncolour.Alpha; + + if (!hdr) + { + Color4 maxdirc = new Color4(1.0f); + Color4 maxambc = new Color4(0.5f); + lightdircolour = Color4.Min(lightdircolour, maxdirc); + lightdirambcolour = Color4.Min(lightdirambcolour, maxambc); + lightnaturalupcolour = Color4.Min(lightnaturalupcolour, maxambc); + lightnaturaldowncolour = Color4.Min(lightnaturaldowncolour, maxambc); + lightartificialupcolour = Color4.Min(lightartificialupcolour, maxambc); + lightartificialdowncolour = Color4.Min(lightartificialdowncolour, maxambc); + } + else + { + hdrint = weather.CurrentValues.skyHdr;//.lightDirCol.W; + } + } + + + } + + globalLights.Weather = weather; + globalLights.HdrEnabled = hdr; + globalLights.SpecularEnabled = true;// !MapViewEnabled;//disable specular for map view. + globalLights.HdrIntensity = Math.Max(hdrint, 1.0f); + globalLights.CurrentSunDir = sundir; + globalLights.CurrentMoonDir = moondir; + globalLights.MoonAxis = moonax; + globalLights.Params.LightDir = lightdir; + globalLights.Params.LightDirColour = lightdircolour; + globalLights.Params.LightDirAmbColour = lightdirambcolour; + globalLights.Params.LightNaturalAmbUp = rendernaturalambientlight ? lightnaturalupcolour : Color4.Black; + globalLights.Params.LightNaturalAmbDown = rendernaturalambientlight ? lightnaturaldowncolour : Color4.Black; + globalLights.Params.LightArtificialAmbUp = renderartificialambientlight ? lightartificialupcolour : Color4.Black; + globalLights.Params.LightArtificialAmbDown = renderartificialambientlight ? lightartificialdowncolour : Color4.Black; + + + if (shaders != null) + { + shaders.SetGlobalLightParams(globalLights); + } + + } + + private void UpdateWindVector(float elapsed) + { + //wind still needs a lot of work. + //currently just feed the wind vector with small oscillations... + currentWindTime += elapsed; + if (currentWindTime >= 200.0f) currentWindTime -= 200.0f; + + float dirval = (float)(currentWindTime * 0.01 * Math.PI); + float dirval1 = (float)Math.Sin(currentWindTime * 0.100 * Math.PI) * 0.3f; + float dirval2 = (float)(currentWindTime * 0.333 * Math.PI); + float dirval3 = (float)(currentWindTime * 0.5 * Math.PI); + float dirval4 = (float)Math.Sin(currentWindTime * 0.223 * Math.PI) * 0.4f; + float dirval5 = (float)Math.Sin(currentWindTime * 0.4 * Math.PI) * 5.5f; + + currentWindVec.Z = (float)Math.Sin(dirval) * dirval1 + (float)Math.Cos(dirval2) * dirval4; + currentWindVec.W = (float)Math.Cos(dirval) * dirval5 + (float)Math.Sin(dirval3) * dirval4; + + float strval = (float)(currentWindTime * 0.1 * Math.PI); + float strval2 = (float)(currentWindTime * 0.825 * Math.PI); + float strval3 = (float)(currentWindTime * 0.333 * Math.PI); + float strval4 = (float)(currentWindTime * 0.666 * Math.PI); + float strbase = 0.1f * ((float)Math.Sin(strval * 0.5)); + float strbase2 = 0.02f * ((float)Math.Sin(strval2 * 0.1)); + + currentWindVec.X = (float)Math.Sin(strval) * strbase + ((float)Math.Cos(strval3) * strbase2); + currentWindVec.Y = (float)Math.Cos(strval2) * strbase + ((float)Math.Sin(strval4 - strval3) * strbase2); + } + + + + private void UpdateControlInputs(float elapsed) + { + var s = Settings.Default; + + float moveSpeed = 10.0f; + + bool xbenable = (xbcontroller != null) && (xbcontroller.IsConnected); + float lx = 0, ly = 0, rx = 0, ry = 0, lt = 0, rt = 0; //input axes + if (xbenable) + { + xbcontrollerstateprev = xbcontrollerstate; + xbcontrollerstate = xbcontroller.GetState(); + xbmainaxesprev = xbmainaxes; + xbtrigsprev = xbtrigs; + xbmainaxes = ControllerMainAxes(); + xbtrigs = ControllerTriggers(); + lx = xbmainaxes.X; + ly = xbmainaxes.Y; + rx = xbmainaxes.Z; + ry = xbmainaxes.W; + lt = xbtrigs.X; + rt = xbtrigs.Y; + float lamt = s.XInputLThumbSensitivity * elapsed; + float ramt = s.XInputRThumbSensitivity * elapsed; + ly = s.XInputLThumbInvert ? ly : -ly; + ry = s.XInputRThumbInvert ? ry : -ry; + lx *= lamt; + ly *= lamt; + rx *= ramt; + ry *= ramt; + + //if (ControllerButtonJustPressed(GamepadButtonFlags.Start)) + //{ + // SetControlMode(ControlMode == WorldControlMode.Free ? WorldControlMode.Ped : WorldControlMode.Free); + //} + } + + + + Vector3 movevec = Vector3.Zero; + + //if (MapViewEnabled == true) + //{ + // if (kbmovefwd) movevec.Y += 1.0f; + // if (kbmovebck) movevec.Y -= 1.0f; + // if (kbmovelft) movevec.X -= 1.0f; + // if (kbmovergt) movevec.X += 1.0f; + // if (kbmoveup) movevec.Y += 1.0f; + // if (kbmovedn) movevec.Y -= 1.0f; + // movevec *= elapsed * 100.0f * Math.Min(camera.OrthographicTargetSize * 0.01f, 30.0f); + // float mapviewscale = 1.0f / camera.Height; + // float fdx = MapViewDragX * mapviewscale; + // float fdy = MapViewDragY * mapviewscale; + // movevec.X -= fdx * camera.OrthographicSize; + // movevec.Y += fdy * camera.OrthographicSize; + //} + //else + { + //normal movement + if (kbmovefwd) movevec.Z -= 1.0f; + if (kbmovebck) movevec.Z += 1.0f; + if (kbmovelft) movevec.X -= 1.0f; + if (kbmovergt) movevec.X += 1.0f; + if (kbmoveup) movevec.Y += 1.0f; + if (kbmovedn) movevec.Y -= 1.0f; + movevec *= elapsed * moveSpeed * Math.Min(camera.TargetDistance, 50.0f); + } + + + Vector3 movewvec = camera.ViewInvQuaternion.Multiply(movevec); + camEntity.Position += movewvec; + + //MapViewDragX = 0; + //MapViewDragY = 0; + + + + + if (xbenable) + { + camera.ControllerRotate(lx + rx, ly + ry); + + float zoom = 0.0f; + float zoomspd = s.XInputZoomSpeed; + float zoomamt = zoomspd * elapsed; + if (ControllerButtonPressed(GamepadButtonFlags.DPadUp)) zoom += zoomamt; + if (ControllerButtonPressed(GamepadButtonFlags.DPadDown)) zoom -= zoomamt; + + camera.ControllerZoom(zoom); + + float acc = 0.0f; + float accspd = s.XInputMoveSpeed;//actually accel speed... + acc += rt * accspd; + acc -= lt * accspd; + + Vector3 newdir = camera.ViewDirection; //maybe use the "vehicle" direction...? + xbcontrolvelocity += (acc * elapsed); + + if (ControllerButtonPressed(GamepadButtonFlags.A | GamepadButtonFlags.RightShoulder)) //handbrake... + { + xbcontrolvelocity *= Math.Max(0.75f - elapsed, 0);//not ideal for low fps... + //xbcontrolvelocity = 0.0f; + if (Math.Abs(xbcontrolvelocity) < 0.001f) xbcontrolvelocity = 0.0f; + } + + camEntity.Velocity = newdir * xbcontrolvelocity; + camEntity.Position += camEntity.Velocity * elapsed; + + + //fire! + //if (ControllerButtonJustPressed(GamepadButtonFlags.LeftShoulder)) + //{ + // SpawnTestEntity(true); + //} + + } + + + + } + + private Vector4 ControllerMainAxes() + { + var gp = xbcontrollerstate.Gamepad; + var ldz = Gamepad.LeftThumbDeadZone; + var rdz = Gamepad.RightThumbDeadZone; + float ltnrng = -(short.MinValue + ldz); + float ltprng = (short.MaxValue - ldz); + float rtnrng = -(short.MinValue + rdz); + float rtprng = (short.MaxValue - rdz); + + float lx = (gp.LeftThumbX < 0) ? Math.Min((gp.LeftThumbX + ldz) / ltnrng, 0) : + (gp.LeftThumbX > 0) ? Math.Max((gp.LeftThumbX - ldz) / ltprng, 0) : 0; + float ly = (gp.LeftThumbY < 0) ? Math.Min((gp.LeftThumbY + ldz) / ltnrng, 0) : + (gp.LeftThumbY > 0) ? Math.Max((gp.LeftThumbY - ldz) / ltprng, 0) : 0; + float rx = (gp.RightThumbX < 0) ? Math.Min((gp.RightThumbX + rdz) / rtnrng, 0) : + (gp.RightThumbX > 0) ? Math.Max((gp.RightThumbX - rdz) / rtprng, 0) : 0; + float ry = (gp.RightThumbY < 0) ? Math.Min((gp.RightThumbY + rdz) / rtnrng, 0) : + (gp.RightThumbY > 0) ? Math.Max((gp.RightThumbY - rdz) / rtprng, 0) : 0; + + return new Vector4(lx, ly, rx, ry); + } + private Vector2 ControllerTriggers() + { + var gp = xbcontrollerstate.Gamepad; + var tt = Gamepad.TriggerThreshold; + float trng = byte.MaxValue - tt; + float lt = Math.Max((gp.LeftTrigger - tt) / trng, 0); + float rt = Math.Max((gp.RightTrigger - tt) / trng, 0); + return new Vector2(lt, rt); + } + private bool ControllerButtonPressed(GamepadButtonFlags b) + { + return ((xbcontrollerstate.Gamepad.Buttons & b) != 0); + } + private bool ControllerButtonJustPressed(GamepadButtonFlags b) + { + return (((xbcontrollerstate.Gamepad.Buttons & b) != 0) && ((xbcontrollerstateprev.Gamepad.Buttons & b) == 0)); + } + + + + + private void UpdateModelsUI(DrawableBase drawable) + { + DetailsPropertyGrid.SelectedObject = drawable; + + DrawableDrawFlags.Clear(); + ModelDrawFlags.Clear(); + GeometryDrawFlags.Clear(); + ModelsTreeView.Nodes.Clear(); + ModelsTreeView.ShowRootLines = false; + TexturesTreeView.Nodes.Clear(); + if (drawable != null) + { + AddDrawableModelsTreeNodes(drawable.DrawableModelsHigh, "High Detail", true); + AddDrawableModelsTreeNodes(drawable.DrawableModelsMedium, "Medium Detail", false); + AddDrawableModelsTreeNodes(drawable.DrawableModelsLow, "Low Detail", false); + AddDrawableModelsTreeNodes(drawable.DrawableModelsVeryLow, "Very Low Detail", false); + //AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsX, "X Detail", false); + } + } + private void UpdateModelsUI(FragType frag) + { + DetailsPropertyGrid.SelectedObject = frag; + + var drawable = frag.Drawable; + + DrawableDrawFlags.Clear(); + ModelDrawFlags.Clear(); + GeometryDrawFlags.Clear(); + ModelsTreeView.Nodes.Clear(); + ModelsTreeView.ShowRootLines = false; + TexturesTreeView.Nodes.Clear(); + if (drawable != null) + { + AddDrawableModelsTreeNodes(drawable.DrawableModelsHigh, "High Detail", true); + AddDrawableModelsTreeNodes(drawable.DrawableModelsMedium, "Medium Detail", false); + AddDrawableModelsTreeNodes(drawable.DrawableModelsLow, "Low Detail", false); + AddDrawableModelsTreeNodes(drawable.DrawableModelsVeryLow, "Very Low Detail", false); + //AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsX, "X Detail", false); + } + } + private void UpdateModelsUI(Dictionary dict) + { + //DetailsPropertyGrid.SelectedObject = dict; //this won't look good... + + DrawableDrawFlags.Clear(); + ModelDrawFlags.Clear(); + GeometryDrawFlags.Clear(); + ModelsTreeView.Nodes.Clear(); + ModelsTreeView.ShowRootLines = true; + TexturesTreeView.Nodes.Clear(); + + bool check = true; + if (dict != null) + { + foreach (var kvp in dict) + { + AddDrawableTreeNode(kvp.Value, kvp.Key, check); + check = false; + } + } + + ToolsPanel.Visible = true; //show the panel by default for dictionaries... + } + private void UpdateBoundsUI(Bounds bounds) + { + DetailsPropertyGrid.SelectedObject = bounds; + } + private void UpdateNavmeshUI(YnvFile ynv) + { + DetailsPropertyGrid.SelectedObject = ynv.Nav; + } + + + private void AddDrawableTreeNode(DrawableBase drawable, uint hash, bool check) + { + MetaHash mhash = new MetaHash(hash); + + var dnode = ModelsTreeView.Nodes.Add(mhash.ToString()); + dnode.Tag = drawable; + dnode.Checked = check; + + AddDrawableModelsTreeNodes(drawable.DrawableModelsHigh, "High Detail", true, dnode); + AddDrawableModelsTreeNodes(drawable.DrawableModelsMedium, "Medium Detail", false, dnode); + AddDrawableModelsTreeNodes(drawable.DrawableModelsLow, "Low Detail", false, dnode); + AddDrawableModelsTreeNodes(drawable.DrawableModelsVeryLow, "Very Low Detail", false, dnode); + //AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsX, "X Detail", false, dnode); + + } + private void AddDrawableModelsTreeNodes(ResourcePointerList64 models, string prefix, bool check, TreeNode parentDrawableNode = null) + { + if (models == null) return; + if (models.data_items == null) return; + + for (int mi = 0; mi < models.data_items.Length; mi++) + { + var tnc = (parentDrawableNode != null) ? parentDrawableNode.Nodes : ModelsTreeView.Nodes; + + var model = models.data_items[mi]; + string mprefix = prefix + " " + (mi + 1).ToString(); + var mnode = tnc.Add(mprefix + " " + model.ToString()); + mnode.Tag = model; + mnode.Checked = check; + + var tmnode = TexturesTreeView.Nodes.Add(mprefix + " " + model.ToString()); + tmnode.Tag = model; + + if (!check) + { + ModelDrawFlags[model] = false; + } + + if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + + foreach (var geom in model.Geometries.data_items) + { + var gname = geom.ToString(); + var gnode = mnode.Nodes.Add(gname); + gnode.Tag = geom; + gnode.Checked = true;// check; + + var tgnode = tmnode.Nodes.Add(gname); + tgnode.Tag = geom; + + if ((geom.Shader != null) && (geom.Shader.ParametersList != null) && (geom.Shader.ParametersList.Hashes != null)) + { + var pl = geom.Shader.ParametersList; + var h = pl.Hashes; + var p = pl.Parameters; + for (int ip = 0; ip < h.Length; ip++) + { + var hash = pl.Hashes[ip]; + var parm = pl.Parameters[ip]; + var tex = parm.Data as TextureBase; + if (tex != null) + { + var t = tex as Texture; + var tstr = tex.Name.Trim(); + if (t != null) + { + tstr = string.Format("{0} ({1}x{2}, embedded)", tex.Name, t.Width, t.Height); + } + var tnode = tgnode.Nodes.Add(hash.ToString().Trim() + ": " + tstr); + tnode.Tag = tex; + } + } + tgnode.Expand(); + } + + } + + mnode.Expand(); + tmnode.Expand(); + } + } + private void UpdateSelectionDrawFlags(TreeNode node) + { + //update the selection draw flags depending on tag and checked/unchecked + var drwbl = node.Tag as DrawableBase; + var model = node.Tag as DrawableModel; + var geom = node.Tag as DrawableGeometry; + bool rem = node.Checked; + lock (rendersyncroot) + { + if (drwbl != null) + { + if (rem) + { + if (DrawableDrawFlags.ContainsKey(drwbl)) + { + DrawableDrawFlags.Remove(drwbl); + } + } + else + { + DrawableDrawFlags[drwbl] = false; + } + } + if (model != null) + { + if (rem) + { + if (ModelDrawFlags.ContainsKey(model)) + { + ModelDrawFlags.Remove(model); + } + } + else + { + ModelDrawFlags[model] = false; + } + } + if (geom != null) + { + if (rem) + { + if (GeometryDrawFlags.ContainsKey(geom)) + { + GeometryDrawFlags.Remove(geom); + } + } + else + { + GeometryDrawFlags[geom] = false; + } + } + updateArchetypeStatus = true; + } + } + + + + + + + + private Archetype TryGetArchetype(uint hash) + { + if ((gameFileCache == null) || (!gameFileCache.IsInited)) return null; + + var arch = gameFileCache.GetArchetype(hash); + + if ((arch != null) && (arch != currentArchetype) && (updateArchetypeStatus)) + { + UpdateStatus("Archetype: " + arch.Name.ToString()); + currentArchetype = arch; + updateArchetypeStatus = false; + } + + return arch; + } + + private DrawableBase TryGetDrawable(Archetype arche) + { + if (arche == null) return null; + if ((gameFileCache == null) || (!gameFileCache.IsInited)) return null; + + uint drawhash = arche.Hash; + DrawableBase drawable = null; + if ((arche.DrawableDict != 0))// && (arche.DrawableDict != arche.Hash)) + { + //try get drawable from ydd... + YddFile ydd = gameFileCache.GetYdd(arche.DrawableDict); + if (ydd != null) + { + if (ydd.Loaded && (ydd.Dict != null)) + { + Drawable d; + ydd.Dict.TryGetValue(drawhash, out d); //can't out to base class? + drawable = d; + if (drawable == null) + { + return null; //drawable wasn't in dict!! + } + } + else + { + return null; //ydd not loaded yet, or has no dict + } + } + else + { + //return null; //couldn't find drawable dict... quit now? + } + } + if (drawable == null) + { + //try get drawable from ydr. + YdrFile ydr = gameFileCache.GetYdr(drawhash); + if (ydr != null) + { + if (ydr.Loaded) + { + drawable = ydr.Drawable; + } + } + else + { + YftFile yft = gameFileCache.GetYft(drawhash); + if (yft != null) + { + if (yft.Loaded) + { + if (yft.Fragment != null) + { + drawable = yft.Fragment.Drawable; + } + } + } + } + } + + return drawable; + } + + private Renderable TryGetRenderable(Archetype arche, DrawableBase drawable, uint txdHash = 0) + { + if (drawable == null) return null; + //BUG: only last texdict used!! needs to cache textures per archetype........ + //(but is it possible to have the same drawable with different archetypes?) + uint texDict = (arche != null) ? arche.TextureDict.Hash : txdHash; + uint clipDict = (arche != null) ? arche.ClipDict.Hash : 0; + var yptTextDict = Ypt?.PtfxList?.TextureDictionary; + + Renderable rndbl = renderableCache.GetRenderable(drawable); + if (rndbl == null) return null; + + + var gfc = gameFileCache; + if ((gfc != null) && (!gfc.IsInited)) + { + gfc = null; + } + + + //if (clipDict != 0) + //{ + // YcdFile ycd = gameFileCache.GetYcd(clipDict); + // if ((ycd != null) && (ycd.Loaded)) + // { + // ClipMapEntry cme; + // if (ycd.ClipMap.TryGetValue(arche.Hash, out cme)) + // { + // } + // else + // { } + // } + //} + + + bool alltexsloaded = true; + int missingtexcount = 0; + for (int mi = 0; mi < rndbl.HDModels.Length; mi++) + { + var model = rndbl.HDModels[mi]; + + //if (!RenderIsModelFinalRender(model) && !renderproxies) + //{ + // continue; //filter out reflection proxy models... + //} + + + foreach (var geom in model.Geometries) + { + if (geom.Textures != null) + { + for (int i = 0; i < geom.Textures.Length; i++) + { + var tex = geom.Textures[i]; + var ttex = tex as Texture; + RenderableTexture rdtex = null; + if ((ttex == null) && (tex != null)) + { + //TextureRef means this RenderableTexture needs to be loaded from texture dict... + if (yptTextDict != null) //for ypt files, first try the embedded tex dict.. + { + var dtex = yptTextDict.Lookup(tex.NameHash); + rdtex = renderableCache.GetRenderableTexture(dtex); + } + else if (texDict != 0) + { + YtdFile ytd = gfc?.GetYtd(texDict); + if ((ytd != null) && (ytd.Loaded) && (ytd.TextureDict != null)) + { + var dtex = ytd.TextureDict.Lookup(tex.NameHash); + if (dtex == null) + { + //not present in dictionary... check already loaded texture dicts... + YtdFile ytd2 = gfc?.TryGetTextureDictForTexture(tex.NameHash); + if ((ytd2 != null) && (ytd2.Loaded) && (ytd2.TextureDict != null)) + { + dtex = ytd2.TextureDict.Lookup(tex.NameHash); + } + else + { + //couldn't find texture dict? + //first try going through ytd hierarchy... + dtex = gfc?.TryFindTextureInParent(tex.NameHash, texDict); + + + //if (dtex == null) + //{ //try for a texture dict with the same hash as the archetype? + // dtex = gameFileCache.TryFindTextureInParent(tex.TextureRef.NameHash, arche.Hash); + // if (dtex != null) + // { } + //} + } + } + if (dtex != null) + { + geom.Textures[i] = dtex; //cache it for next time to avoid the lookup... + rdtex = renderableCache.GetRenderableTexture(dtex); + } + if (rdtex == null) + { } //nothing to see here :( + } + else if ((ytd == null)) + { + Texture dtex = null; + if (drawable.ShaderGroup.TextureDictionary != null) + { + dtex = drawable.ShaderGroup.TextureDictionary.Lookup(tex.NameHash); + if (dtex == null) + { + //dtex = drawable.ShaderGroup.TextureDictionary.Textures.data_items[0]; + } + } + if (dtex == null) + { + YtdFile ytd2 = gfc?.TryGetTextureDictForTexture(tex.NameHash); + if ((ytd2 != null) && (ytd2.Loaded) && (ytd2.TextureDict != null)) + { + dtex = ytd2.TextureDict.Lookup(tex.NameHash); + } + if (dtex == null) + { + dtex = gfc?.TryFindTextureInParent(tex.NameHash, texDict); + } + } + rdtex = renderableCache.GetRenderableTexture(dtex); + if (rdtex == null) + { missingtexcount -= 2; } //(give extra chance..) couldn't find the texture! :( + } + else if (ytd != null) + { + alltexsloaded = false;//ytd not loaded yet + //missingtexcount++; + } + } + else //no texdict specified, nothing to see here.. + { + YtdFile ytd2 = gfc?.TryGetTextureDictForTexture(tex.NameHash); + if ((ytd2 != null) && (ytd2.Loaded) && (ytd2.TextureDict != null)) + { + var dtex = ytd2.TextureDict.Lookup(tex.NameHash); + rdtex = renderableCache.GetRenderableTexture(dtex); + } + } + } + else if (ttex != null) //ensure embedded renderable texture + { + rdtex = renderableCache.GetRenderableTexture(ttex); + } + else if (tex == null) + { } //tex wasn't loaded? shouldn't happen.. + + + geom.RenderableTextures[i] = rdtex; + if (rdtex != null) + { + if (!rdtex.IsLoaded) + { + alltexsloaded = false; + missingtexcount++; + } + } + else + { + //alltexsloaded = false; + missingtexcount++; + } + + + } + } + } + } + + rndbl.AllTexturesLoaded = alltexsloaded || (missingtexcount < 2); + + return rndbl; + } + + + + private bool RenderDrawable(DrawableBase drawable, Archetype arche, YmapEntityDef entity, Vector3 camrel, uint txdHash = 0) + { + //enqueue a single drawable for rendering. + + if (drawable == null) + return false; + + Renderable rndbl = TryGetRenderable(arche, drawable, txdHash); + if (rndbl == null) + return false; + + return RenderRenderable(rndbl, arche, entity, camrel); + } + + + private bool RenderRenderable(Renderable rndbl, Archetype arche, YmapEntityDef entity, Vector3 camrel) + { + //enqueue a single renderable for rendering. + + if (!rndbl.IsLoaded) return false; + + + //if (((SelectionMode == MapSelectionMode.Entity) || (SelectionMode == MapSelectionMode.EntityExtension) || (SelectionMode == MapSelectionMode.ArchetypeExtension))) + //{ + // UpdateMouseHit(rndbl, arche, entity, camrel); + //} + + bool isselected = true;// (rndbl.Key == SelectedItem.Drawable); + + Vector3 position = Vector3.Zero; + Vector3 scale = Vector3.One; + Quaternion orientation = Quaternion.Identity; + uint tintPaletteIndex = 0; + Vector3 bbmin = (arche != null) ? arche.BBMin : rndbl.Key.BoundingBoxMin.XYZ(); + Vector3 bbmax = (arche != null) ? arche.BBMax : rndbl.Key.BoundingBoxMax.XYZ(); + Vector3 bscen = (arche != null) ? arche.BSCenter : rndbl.Key.BoundingCenter; + float radius = (arche != null) ? arche.BSRadius : rndbl.Key.BoundingSphereRadius; + float distance = (camrel + bscen).Length(); + if (entity != null) + { + position = entity.Position; + scale = entity.Scale; + orientation = entity.Orientation; + tintPaletteIndex = entity.CEntityDef.tintValue; + bbmin = entity.BBMin; + bbmax = entity.BBMax; + bscen = entity.BSCenter; + } + + + if (rendercollisionmeshes)// && collisionmeshlayerdrawable) + { + Drawable sdrawable = rndbl.Key as Drawable; + if ((sdrawable != null) && (sdrawable.Bound != null)) + { + RenderCollisionMesh(sdrawable.Bound, entity); + } + } + + + bool retval = true;// false; + if (rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload)) + { + RenderableGeometryInst rginst = new RenderableGeometryInst(); + rginst.Inst.Renderable = rndbl; + rginst.Inst.CamRel = camrel; + rginst.Inst.Position = position; + rginst.Inst.Scale = scale; + rginst.Inst.Orientation = orientation; + rginst.Inst.TintPaletteIndex = tintPaletteIndex; + rginst.Inst.BBMin = bbmin; + rginst.Inst.BBMax = bbmax; + rginst.Inst.BSCenter = bscen; + rginst.Inst.Radius = radius; + rginst.Inst.Distance = distance; + + + RenderableModel[] models = isselected ? rndbl.AllModels : rndbl.HDModels; + + for (int mi = 0; mi < models.Length; mi++) + { + var model = models[mi]; + + if (isselected) + { + if (ModelDrawFlags.ContainsKey(model.DrawableModel)) + { continue; } //filter out models in selected item that aren't flagged for drawing. + } + + if (!RenderIsModelFinalRender(model))// && !renderproxies) + { continue; } //filter out reflection proxy models... + + for (int gi = 0; gi < model.Geometries.Length; gi++) + { + var geom = model.Geometries[gi]; + + if (isselected) + { + if (GeometryDrawFlags.ContainsKey(geom.DrawableGeom)) + { continue; } //filter out geometries in selected item that aren't flagged for drawing. + } + + rginst.Geom = geom; + + shaders.Enqueue(rginst); + } + } + } + else + { + retval = false; + } + return retval; + } + + + private void RenderCollisionMesh(Bounds bounds, YmapEntityDef entity) + { + //enqueue a single collision mesh for rendering. + + Vector3 position; + Vector3 scale; + Quaternion orientation; + if (entity != null) + { + position = entity.Position; + scale = entity.Scale; + orientation = entity.Orientation; + } + else + { + position = Vector3.Zero; + scale = Vector3.One; + orientation = Quaternion.Identity; + } + + switch (bounds.Type) + { + case 10: //BoundComposite + BoundComposite boundcomp = bounds as BoundComposite; + if (boundcomp != null) + { + RenderableBoundComposite rndbc = renderableCache.GetRenderableBoundComp(boundcomp); + if (rndbc.IsLoaded) + { + RenderableBoundGeometryInst rbginst = new RenderableBoundGeometryInst(); + rbginst.Inst.Renderable = rndbc; + rbginst.Inst.Orientation = orientation; + rbginst.Inst.Scale = scale; + foreach (var geom in rndbc.Geometries) + { + if (geom == null) continue; + rbginst.Geom = geom; + rbginst.Inst.Position = position + orientation.Multiply(geom.BoundGeom.CenterGeom * scale); + rbginst.Inst.CamRel = rbginst.Inst.Position - camera.Position; + shaders.Enqueue(rbginst); + } + + //UpdateMouseHits(rndbc, entity); + } + } + else + { } + break; + case 3: //BoundBox - found in drawables - TODO + BoundBox boundbox = bounds as BoundBox; + if (boundbox == null) + { } + break; + case 0: //BoundSphere - found in drawables - TODO + BoundSphere boundsphere = bounds as BoundSphere; + if (boundsphere == null) + { } + break; + default: + break; + } + } + + + private void RenderNavmesh(YnvFile ynv) + { + RenderablePathBatch rnd = renderableCache.GetRenderablePathBatch(ynv); + if ((rnd != null) && (rnd.IsLoaded)) + { + shaders.Enqueue(rnd); + } + } + + + + private bool RenderIsModelFinalRender(RenderableModel model) + { + + if ((model.Unk2Ch & 1) == 0) //smallest bit is proxy/"final render" bit? seems to work... + { + return false;// renderproxies; + } + return true; + + //switch (model.Unk2Ch) + //{ + // case 65784: //0000010000000011111000 //reflection proxy? + // case 65788: //0000010000000011111100 + // case 131312: //0000100000000011110000 //reflection proxy? + // case 131320: //0000100000000011111000 //reflection proxy? + // case 131324: //0000100000000011111100 //shadow/reflection proxy? + // case 196834: //0000110000000011100010 //shadow proxy? (tree branches) + // case 196848: //0000110000000011110000 //reflection proxy? + // case 196856: //0000110000000011111000 //reflection proxy? hotel nr golf course + // case 262392: //0001000000000011111000 //reflection proxy? + // case 327932: //0001010000000011111100 //reflection proxy? (alamo/sandy shores) + // case 983268: //0011110000000011100100 //big reflection proxy? + // case 2293988://1000110000000011100100 //big reflection proxy? + // //case 1442047://golf course water proxy, but other things also + // //case 1114367://mike house water proxy, but other things also + // return renderproxies; + //} + //return true; + } + + + + + + + + + + + + private void ModelForm_Load(object sender, EventArgs e) + { + Init(); + } + + private void ModelForm_MouseDown(object sender, MouseEventArgs e) + { + switch (e.Button) + { + case MouseButtons.Left: MouseLButtonDown = true; break; + case MouseButtons.Right: MouseRButtonDown = true; break; + } + + MouseDownPoint = e.Location; + MouseLastPoint = MouseDownPoint; + + + if (MouseRButtonDown) + { + //SelectMousedItem(); + } + + MouseX = e.X; //to stop jumps happening on mousedown, sometimes the last MouseMove event was somewhere else... (eg after clicked a menu) + MouseY = e.Y; + } + + private void ModelForm_MouseUp(object sender, MouseEventArgs e) + { + switch (e.Button) + { + case MouseButtons.Left: MouseLButtonDown = false; break; + case MouseButtons.Right: MouseRButtonDown = false; break; + } + + //lock (MouseControlSyncRoot) + //{ + // MouseControlButtons &= ~e.Button; + //} + + } + + private void ModelForm_MouseMove(object sender, MouseEventArgs e) + { + int dx = e.X - MouseX; + int dy = e.Y - MouseY; + + if (MouseLButtonDown) + { + camera.MouseRotate(dx, dy); + } + if (MouseRButtonDown) + { + if (controllightdir) + { + lightdirx += (dx * camera.Sensitivity); + lightdiry += (dy * camera.Sensitivity); + } + else if (controltimeofday) + { + timeofday += (dx - dy) / 30.0f; + while (timeofday >= 24.0f) timeofday -= 24.0f; + while (timeofday < 0.0f) timeofday += 24.0f; + timecycle.SetTime(timeofday); + + float fv = timeofday * 60.0f; + TimeOfDayTrackBar.Value = (int)fv; + UpdateTimeOfDayLabel(); + } + } + + MouseX = e.X; + MouseY = e.Y; + MouseLastPoint = e.Location; + + + + } + + private void ModelForm_MouseWheel(object sender, MouseEventArgs e) + { + if (e.Delta != 0) + { + //if (ControlMode == WorldControlMode.Free) + //{ + camera.MouseZoom(e.Delta); + //} + //else + //{ + // lock (MouseControlSyncRoot) + // { + // MouseControlWheel += e.Delta; + // } + //} + } + + } + + private void StatsUpdateTimer_Tick(object sender, EventArgs e) + { + int rgc = (shaders != null) ? shaders.RenderedGeometries : 0; + int crc = renderableCache.LoadedRenderableCount; + int ctc = renderableCache.LoadedTextureCount; + int tcrc = renderableCache.MemCachedRenderableCount; + int tctc = renderableCache.MemCachedTextureCount; + long vr = renderableCache.TotalGraphicsMemoryUse + (shaders != null ? shaders.TotalGraphicsMemoryUse : 0); + string vram = TextUtil.GetBytesReadable(vr); + //StatsLabel.Text = string.Format("Drawn: {0} geom, Loaded: {1}/{5} dr, {2}/{6} tx, Vram: {3}, Fps: {4}", rgc, crc, ctc, vram, fps, tcrc, tctc); + StatsLabel.Text = string.Format("Drawn: {0} geom, Loaded: {1} dr, {2} tx, Vram: {3}, Fps: {4}", rgc, crc, ctc, vram, fps); + + if (timerunning) + { + float fv = timeofday * 60.0f; + //TimeOfDayTrackBar.Value = (int)fv; + UpdateTimeOfDayLabel(); + } + + //CameraPositionTextBox.Text = FloatUtil.GetVector3String(camera.Position, "0.##"); + } + + private void ModelForm_KeyDown(object sender, KeyEventArgs e) + { + if (ActiveControl is TextBox) + { + var tb = ActiveControl as TextBox; + if (!tb.ReadOnly) return; //don't move the camera when typing! + } + if (ActiveControl is ComboBox) + { + var cb = ActiveControl as ComboBox; + if (cb.DropDownStyle != ComboBoxStyle.DropDownList) return; //nontypable combobox + } + + var k = e.KeyCode; + + bool ctrl = (e.Modifiers & Keys.Control) > 0; + bool shift = (e.Modifiers & Keys.Shift) > 0; + CtrlPressed = ctrl; + ShiftPressed = shift; + + bool enablemove = true;// (!iseditmode) || (MouseLButtonDown && (GrabbedMarker == null) && (GrabbedWidget == null)); + + enablemove = enablemove && (!ctrl); + + //WASD move the camera entity... + if (enablemove) + { + if (k == keyBindings.MoveForward) kbmovefwd = true; + if (k == keyBindings.MoveBackward) kbmovebck = true; + if (k == keyBindings.MoveLeft) kbmovelft = true; + if (k == keyBindings.MoveRight) kbmovergt = true; + if (k == keyBindings.MoveUp) kbmoveup = true; + if (k == keyBindings.MoveDown) kbmovedn = true; + if (k == keyBindings.Jump) kbjump = true; + } + + bool moving = kbmovefwd || kbmovebck || kbmovelft || kbmovergt || kbmoveup || kbmovedn || kbjump; + + + if (!ctrl) + { + if (k == keyBindings.MoveSlowerZoomIn) + { + camera.MouseZoom(1); + } + if (k == keyBindings.MoveFasterZoomOut) + { + camera.MouseZoom(-1); + } + } + + + + if (!moving) //don't trigger further actions if moving. + { + + if (!ctrl) + { + //switch widget modes and spaces. + //if ((k == keyBindings.ExitEditMode)) + //{ + // if (Widget.Mode == WidgetMode.Default) ToggleWidgetSpace(); + // else SetWidgetMode("Default"); + //} + //if ((k == keyBindings.EditPosition))// && !enablemove) + //{ + // if (Widget.Mode == WidgetMode.Position) ToggleWidgetSpace(); + // else SetWidgetMode("Position"); + //} + //if ((k == keyBindings.EditRotation))// && !enablemove) + //{ + // if (Widget.Mode == WidgetMode.Rotation) ToggleWidgetSpace(); + // else SetWidgetMode("Rotation"); + //} + //if ((k == keyBindings.EditScale))// && !enablemove) + //{ + // if (Widget.Mode == WidgetMode.Scale) ToggleWidgetSpace(); + // else SetWidgetMode("Scale"); + //} + //if (k == keyBindings.ToggleMouseSelect) + //{ + // SetMouseSelect(!MouseSelectEnabled); + //} + //if (k == keyBindings.ToggleToolbar) + //{ + // ToggleToolbar(); + //} + //if (k == Keys.P) + //{ + // //TEMPORARY! + // SetControlMode((ControlMode == WorldControlMode.Free) ? WorldControlMode.Ped : WorldControlMode.Free); + //} + } + else + { + //switch (k) + //{ + // case Keys.N: + // New(); + // break; + // case Keys.O: + // Open(); + // break; + // case Keys.S: + // if (shift) SaveAll(); + // else Save(); + // break; + // case Keys.Z: + // Undo(); + // break; + // case Keys.Y: + // Redo(); + // break; + // case Keys.C: + // CopyItem(); + // break; + // case Keys.V: + // PasteItem(); + // break; + // case Keys.U: + // ToolsPanelShowButton.Visible = !ToolsPanelShowButton.Visible; + // break; + //} + } + //if (k == Keys.Escape) //temporary? panic get cursor back + //{ + // if (ControlMode != WorldControlMode.Free) SetControlMode(WorldControlMode.Free); + //} + } + + //if (ControlMode != WorldControlMode.Free) + //{ + // e.Handled = true; + //} + } + + private void ModelForm_KeyUp(object sender, KeyEventArgs e) + { + bool ctrl = (e.Modifiers & Keys.Control) > 0; + bool shift = (e.Modifiers & Keys.Shift) > 0; + CtrlPressed = ctrl; + ShiftPressed = shift; + + if (ActiveControl is TextBox) + { + var tb = ActiveControl as TextBox; + if (!tb.ReadOnly) return; //don't move the camera when typing! + } + if (ActiveControl is ComboBox) + { + var cb = ActiveControl as ComboBox; + if (cb.DropDownStyle != ComboBoxStyle.DropDownList) return; //non-typable combobox + } + + + var k = e.KeyCode; + if (k == keyBindings.MoveForward) kbmovefwd = false; + if (k == keyBindings.MoveBackward) kbmovebck = false; + if (k == keyBindings.MoveLeft) kbmovelft = false; + if (k == keyBindings.MoveRight) kbmovergt = false; + if (k == keyBindings.MoveUp) kbmoveup = false; + if (k == keyBindings.MoveDown) kbmovedn = false; + if (k == keyBindings.Jump) kbjump = false; + + + //if (ControlMode != WorldControlMode.Free) + //{ + // e.Handled = true; + //} + } + + private void ToolsPanelShowButton_Click(object sender, EventArgs e) + { + ToolsPanel.Visible = true; + } + + private void ToolsPanelHideButton_Click(object sender, EventArgs e) + { + ToolsPanel.Visible = false; + } + + private void ToolsDragPanel_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + toolsPanelResizing = true; + toolsPanelResizeStartX = e.X + ToolsPanel.Left + ToolsDragPanel.Left; + toolsPanelResizeStartLeft = ToolsPanel.Left; + toolsPanelResizeStartRight = ToolsPanel.Right; + } + } + + private void ToolsDragPanel_MouseUp(object sender, MouseEventArgs e) + { + toolsPanelResizing = false; + } + + private void ToolsDragPanel_MouseMove(object sender, MouseEventArgs e) + { + if (toolsPanelResizing) + { + int rx = e.X + ToolsPanel.Left + ToolsDragPanel.Left; + int dx = rx - toolsPanelResizeStartX; + ToolsPanel.Width = toolsPanelResizeStartRight - toolsPanelResizeStartLeft + dx; + } + } + + private void ModelsTreeView_AfterCheck(object sender, TreeViewEventArgs e) + { + if (e.Node != null) + { + UpdateSelectionDrawFlags(e.Node); + } + } + + private void ModelsTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) + { + if (e.Node != null) + { + e.Node.Checked = !e.Node.Checked; + //UpdateSelectionDrawFlags(e.Node); + } + } + + private void ModelsTreeView_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; //stops annoying ding sound... + } + + private void HDRRenderingCheckBox_CheckedChanged(object sender, EventArgs e) + { + lock (rendersyncroot) + { + shaders.hdr = HDRRenderingCheckBox.Checked; + } + } + + private void ShadowsCheckBox_CheckedChanged(object sender, EventArgs e) + { + lock (rendersyncroot) + { + shaders.shadows = ShadowsCheckBox.Checked; + } + } + + private void SkydomeCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderskydome = SkydomeCheckBox.Checked; + //controllightdir = !renderskydome; + } + + private void ControlLightDirCheckBox_CheckedChanged(object sender, EventArgs e) + { + controllightdir = ControlLightDirCheckBox.Checked; + } + + private void TimeOfDayTrackBar_Scroll(object sender, EventArgs e) + { + int v = TimeOfDayTrackBar.Value; + float fh = v / 60.0f; + UpdateTimeOfDayLabel(); + lock (rendersyncroot) + { + timeofday = fh; + timecycle.SetTime(timeofday); + } + } + + private void ShowBoundsCheckBox_CheckedChanged(object sender, EventArgs e) + { + rendercollisionmeshes = ShowBoundsCheckBox.Checked; + } + + private void WireframeCheckBox_CheckedChanged(object sender, EventArgs e) + { + shaders.wireframe = WireframeCheckBox.Checked; + } + + private void AnisotropicFilteringCheckBox_CheckedChanged(object sender, EventArgs e) + { + shaders.AnisotropicFiltering = AnisotropicFilteringCheckBox.Checked; + } + + private void RenderModeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + TextureSamplerComboBox.Enabled = false; + TextureCoordsComboBox.Enabled = false; + switch (RenderModeComboBox.Text) + { + default: + case "Default": + shaders.RenderMode = WorldRenderMode.Default; + break; + case "Single texture": + shaders.RenderMode = WorldRenderMode.SingleTexture; + TextureSamplerComboBox.Enabled = true; + TextureCoordsComboBox.Enabled = true; + break; + case "Vertex normals": + shaders.RenderMode = WorldRenderMode.VertexNormals; + break; + case "Vertex tangents": + shaders.RenderMode = WorldRenderMode.VertexTangents; + break; + case "Vertex colour 1": + shaders.RenderMode = WorldRenderMode.VertexColour; + shaders.RenderVertexColourIndex = 1; + break; + case "Vertex colour 2": + shaders.RenderMode = WorldRenderMode.VertexColour; + shaders.RenderVertexColourIndex = 2; + break; + case "Vertex colour 3": + shaders.RenderMode = WorldRenderMode.VertexColour; + shaders.RenderVertexColourIndex = 3; + break; + case "Texture coord 1": + shaders.RenderMode = WorldRenderMode.TextureCoord; + shaders.RenderTextureCoordIndex = 1; + break; + case "Texture coord 2": + shaders.RenderMode = WorldRenderMode.TextureCoord; + shaders.RenderTextureCoordIndex = 2; + break; + case "Texture coord 3": + shaders.RenderMode = WorldRenderMode.TextureCoord; + shaders.RenderTextureCoordIndex = 3; + break; + } + } + + private void TextureSamplerComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (TextureSamplerComboBox.SelectedItem is MetaName) + { + shaders.RenderTextureSampler = (MetaName)TextureSamplerComboBox.SelectedItem; + } + } + + private void TextureCoordsComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + switch (TextureCoordsComboBox.Text) + { + default: + case "Texture coord 1": + shaders.RenderTextureSamplerCoord = 1; + break; + case "Texture coord 2": + shaders.RenderTextureSamplerCoord = 2; + break; + case "Texture coord 3": + shaders.RenderTextureSamplerCoord = 3; + break; + } + } + + private void GridCheckBox_CheckedChanged(object sender, EventArgs e) + { + enableGrid = GridCheckBox.Checked; + } + + private void GridSizeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + float newgs; + float.TryParse(GridSizeComboBox.Text, out newgs); + if (newgs != gridSize) + { + gridSize = newgs; + UpdateGridVerts(); + } + } + + private void GridCountComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + int newgc; + int.TryParse(GridCountComboBox.Text, out newgc); + if (newgc != gridCount) + { + gridCount = newgc; + UpdateGridVerts(); + } + } + + private void ErrorConsoleCheckBox_CheckedChanged(object sender, EventArgs e) + { + ConsolePanel.Visible = ErrorConsoleCheckBox.Checked; + } + + private void StatusBarCheckBox_CheckedChanged(object sender, EventArgs e) + { + StatusStrip.Visible = StatusBarCheckBox.Checked; + } + } +} diff --git a/Forms/ModelForm.resx b/Forms/ModelForm.resx new file mode 100644 index 0000000..0f54839 --- /dev/null +++ b/Forms/ModelForm.resx @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 166, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/RelForm.Designer.cs b/Forms/RelForm.Designer.cs new file mode 100644 index 0000000..d524f2c --- /dev/null +++ b/Forms/RelForm.Designer.cs @@ -0,0 +1,143 @@ +namespace CodeWalker.Forms +{ + partial class RelForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RelForm)); + this.RelPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.MainTabControl = new System.Windows.Forms.TabControl(); + this.NameTableTabPage = new System.Windows.Forms.TabPage(); + this.DetailsTabPage = new System.Windows.Forms.TabPage(); + this.MainTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.CloseButton = new System.Windows.Forms.Button(); + this.MainTabControl.SuspendLayout(); + this.NameTableTabPage.SuspendLayout(); + this.DetailsTabPage.SuspendLayout(); + this.SuspendLayout(); + // + // RelPropertyGrid + // + this.RelPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.RelPropertyGrid.HelpVisible = false; + this.RelPropertyGrid.Location = new System.Drawing.Point(6, 6); + this.RelPropertyGrid.Name = "RelPropertyGrid"; + this.RelPropertyGrid.Size = new System.Drawing.Size(644, 356); + this.RelPropertyGrid.TabIndex = 0; + // + // MainTabControl + // + this.MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTabControl.Controls.Add(this.NameTableTabPage); + this.MainTabControl.Controls.Add(this.DetailsTabPage); + this.MainTabControl.Location = new System.Drawing.Point(5, 5); + this.MainTabControl.Margin = new System.Windows.Forms.Padding(0); + this.MainTabControl.Name = "MainTabControl"; + this.MainTabControl.SelectedIndex = 0; + this.MainTabControl.Size = new System.Drawing.Size(664, 394); + this.MainTabControl.TabIndex = 1; + // + // NameTableTabPage + // + this.NameTableTabPage.Controls.Add(this.MainTextBox); + this.NameTableTabPage.Location = new System.Drawing.Point(4, 22); + this.NameTableTabPage.Name = "NameTableTabPage"; + this.NameTableTabPage.Padding = new System.Windows.Forms.Padding(3); + this.NameTableTabPage.Size = new System.Drawing.Size(656, 368); + this.NameTableTabPage.TabIndex = 0; + this.NameTableTabPage.Text = "Names"; + this.NameTableTabPage.UseVisualStyleBackColor = true; + // + // DetailsTabPage + // + this.DetailsTabPage.Controls.Add(this.RelPropertyGrid); + this.DetailsTabPage.Location = new System.Drawing.Point(4, 22); + this.DetailsTabPage.Name = "DetailsTabPage"; + this.DetailsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.DetailsTabPage.Size = new System.Drawing.Size(656, 368); + this.DetailsTabPage.TabIndex = 1; + this.DetailsTabPage.Text = "Details"; + this.DetailsTabPage.UseVisualStyleBackColor = true; + // + // MainTextBox + // + this.MainTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTextBox.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.MainTextBox.HideSelection = false; + this.MainTextBox.Location = new System.Drawing.Point(6, 6); + this.MainTextBox.Multiline = true; + this.MainTextBox.Name = "MainTextBox"; + this.MainTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.MainTextBox.Size = new System.Drawing.Size(644, 356); + this.MainTextBox.TabIndex = 1; + this.MainTextBox.WordWrap = false; + // + // CloseButton + // + this.CloseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.CloseButton.Location = new System.Drawing.Point(584, 409); + this.CloseButton.Name = "CloseButton"; + this.CloseButton.Size = new System.Drawing.Size(75, 23); + this.CloseButton.TabIndex = 2; + this.CloseButton.Text = "Close"; + this.CloseButton.UseVisualStyleBackColor = true; + this.CloseButton.Click += new System.EventHandler(this.CloseButton_Click); + // + // RelForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(671, 441); + this.Controls.Add(this.CloseButton); + this.Controls.Add(this.MainTabControl); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "RelForm"; + this.Text = "REL Viewer - CodeWalker by dexyfex"; + this.MainTabControl.ResumeLayout(false); + this.NameTableTabPage.ResumeLayout(false); + this.NameTableTabPage.PerformLayout(); + this.DetailsTabPage.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private WinForms.PropertyGridFix RelPropertyGrid; + private System.Windows.Forms.TabControl MainTabControl; + private System.Windows.Forms.TabPage NameTableTabPage; + private System.Windows.Forms.TabPage DetailsTabPage; + private WinForms.TextBoxFix MainTextBox; + private System.Windows.Forms.Button CloseButton; + } +} \ No newline at end of file diff --git a/Forms/RelForm.cs b/Forms/RelForm.cs new file mode 100644 index 0000000..15eb008 --- /dev/null +++ b/Forms/RelForm.cs @@ -0,0 +1,108 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class RelForm : Form + { + + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + + + public RelForm() + { + InitializeComponent(); + } + + + + private void UpdateFormTitle() + { + Text = fileName + " - REL Viewer - CodeWalker by dexyfex"; + } + + + public void LoadRel(RelFile rel) + { + + fileName = rel?.Name; + if (string.IsNullOrEmpty(fileName)) + { + fileName = rel?.FileEntry?.Name; + } + + UpdateFormTitle(); + + RelPropertyGrid.SelectedObject = rel; + + + StringBuilder sb = new StringBuilder(); + if (rel != null) + { + if (rel.NameTable != null) + { + sb.AppendLine("NameTable - " + rel.NameTable.Length.ToString() + " entries"); + foreach (var name in rel.NameTable) + { + sb.AppendLine(name); + } + sb.AppendLine(); + } + if (rel.IndexStrings != null) + { + sb.AppendLine("IndexStrings - " + rel.IndexStrings.Length.ToString() + " entries"); + foreach (var rstr in rel.IndexStrings) + { + sb.AppendLine(rstr.Name); + } + sb.AppendLine(); + } + if (rel.IndexHashes != null) + { + sb.AppendLine("IndexHashes - " + rel.IndexHashes.Length.ToString() + " entries"); + foreach (var rhash in rel.IndexHashes) + { + uint h = rhash.Name; + var jstr = JenkIndex.TryGetString(h); + if (!string.IsNullOrEmpty(jstr)) + { + sb.AppendLine(jstr); + } + else + { + sb.AppendLine("0x" + h.ToString("X").PadLeft(8, '0')); + } + } + sb.AppendLine(); + } + } + MainTextBox.Text = sb.ToString(); + + } + + private void CloseButton_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/Forms/RelForm.resx b/Forms/RelForm.resx new file mode 100644 index 0000000..1431f6b --- /dev/null +++ b/Forms/RelForm.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/TextForm.Designer.cs b/Forms/TextForm.Designer.cs new file mode 100644 index 0000000..104a1e3 --- /dev/null +++ b/Forms/TextForm.Designer.cs @@ -0,0 +1,296 @@ +namespace CodeWalker.Forms +{ + partial class TextForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TextForm)); + this.MainTextBox = new FastColoredTextBoxNS.FastColoredTextBox(); + this.MainStatusStrip = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.MainMenu = new System.Windows.Forms.MenuStrip(); + this.FileMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveAsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.FileCloseMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.MainToolbar = new System.Windows.Forms.ToolStrip(); + this.NewButton = new System.Windows.Forms.ToolStripSplitButton(); + this.OpenButton = new System.Windows.Forms.ToolStripSplitButton(); + this.SaveButton = new System.Windows.Forms.ToolStripSplitButton(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog(); + ((System.ComponentModel.ISupportInitialize)(this.MainTextBox)).BeginInit(); + this.MainStatusStrip.SuspendLayout(); + this.MainMenu.SuspendLayout(); + this.MainToolbar.SuspendLayout(); + this.SuspendLayout(); + // + // MainTextBox + // + this.MainTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTextBox.AutoCompleteBracketsList = new char[] { + '(', + ')', + '{', + '}', + '[', + ']', + '\"', + '\"', + '\'', + '\''}; + this.MainTextBox.AutoIndentChars = false; + this.MainTextBox.AutoIndentCharsPatterns = ""; + this.MainTextBox.AutoIndentExistingLines = false; + this.MainTextBox.AutoScrollMinSize = new System.Drawing.Size(27, 14); + this.MainTextBox.BackBrush = null; + this.MainTextBox.CharHeight = 14; + this.MainTextBox.CharWidth = 8; + this.MainTextBox.CommentPrefix = null; + this.MainTextBox.Cursor = System.Windows.Forms.Cursors.IBeam; + this.MainTextBox.DelayedEventsInterval = 10; + this.MainTextBox.DisabledColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180))))); + this.MainTextBox.IsReplaceMode = false; + this.MainTextBox.LeftBracket = '<'; + this.MainTextBox.LeftBracket2 = '('; + this.MainTextBox.Location = new System.Drawing.Point(0, 52); + this.MainTextBox.Name = "MainTextBox"; + this.MainTextBox.Paddings = new System.Windows.Forms.Padding(0); + this.MainTextBox.RightBracket = '>'; + this.MainTextBox.RightBracket2 = ')'; + this.MainTextBox.SelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255))))); + this.MainTextBox.ServiceColors = ((FastColoredTextBoxNS.ServiceColors)(resources.GetObject("MainTextBox.ServiceColors"))); + this.MainTextBox.Size = new System.Drawing.Size(823, 461); + this.MainTextBox.TabIndex = 0; + this.MainTextBox.Zoom = 100; + this.MainTextBox.TextChanged += new System.EventHandler(this.MainTextBox_TextChanged); + // + // MainStatusStrip + // + this.MainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel}); + this.MainStatusStrip.Location = new System.Drawing.Point(0, 516); + this.MainStatusStrip.Name = "MainStatusStrip"; + this.MainStatusStrip.Size = new System.Drawing.Size(823, 22); + this.MainStatusStrip.TabIndex = 1; + this.MainStatusStrip.Text = "Main Status Strip"; + // + // StatusLabel + // + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(808, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // MainMenu + // + this.MainMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileMenu, + this.EditMenu, + this.ViewMenu}); + this.MainMenu.Location = new System.Drawing.Point(0, 0); + this.MainMenu.Name = "MainMenu"; + this.MainMenu.Size = new System.Drawing.Size(823, 24); + this.MainMenu.TabIndex = 2; + this.MainMenu.Text = "Main Menu"; + // + // FileMenu + // + this.FileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileNewMenu, + this.FileOpenMenu, + this.FileSaveMenu, + this.FileSaveAsMenu, + this.toolStripSeparator1, + this.FileCloseMenu}); + this.FileMenu.Name = "FileMenu"; + this.FileMenu.Size = new System.Drawing.Size(37, 20); + this.FileMenu.Text = "File"; + // + // FileNewMenu + // + this.FileNewMenu.Name = "FileNewMenu"; + this.FileNewMenu.Size = new System.Drawing.Size(145, 22); + this.FileNewMenu.Text = "New"; + this.FileNewMenu.Click += new System.EventHandler(this.FileNewMenu_Click); + // + // FileOpenMenu + // + this.FileOpenMenu.Name = "FileOpenMenu"; + this.FileOpenMenu.Size = new System.Drawing.Size(145, 22); + this.FileOpenMenu.Text = "Open..."; + this.FileOpenMenu.Click += new System.EventHandler(this.FileOpenMenu_Click); + // + // FileSaveMenu + // + this.FileSaveMenu.Name = "FileSaveMenu"; + this.FileSaveMenu.Size = new System.Drawing.Size(145, 22); + this.FileSaveMenu.Text = "Save"; + this.FileSaveMenu.Click += new System.EventHandler(this.FileSaveMenu_Click); + // + // FileSaveAsMenu + // + this.FileSaveAsMenu.Name = "FileSaveAsMenu"; + this.FileSaveAsMenu.Size = new System.Drawing.Size(145, 22); + this.FileSaveAsMenu.Text = "Save As..."; + this.FileSaveAsMenu.Click += new System.EventHandler(this.FileSaveAsMenu_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(142, 6); + // + // FileCloseMenu + // + this.FileCloseMenu.Name = "FileCloseMenu"; + this.FileCloseMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); + this.FileCloseMenu.Size = new System.Drawing.Size(145, 22); + this.FileCloseMenu.Text = "Close"; + this.FileCloseMenu.Click += new System.EventHandler(this.FileCloseMenu_Click); + // + // EditMenu + // + this.EditMenu.Enabled = false; + this.EditMenu.Name = "EditMenu"; + this.EditMenu.Size = new System.Drawing.Size(39, 20); + this.EditMenu.Text = "Edit"; + // + // ViewMenu + // + this.ViewMenu.Enabled = false; + this.ViewMenu.Name = "ViewMenu"; + this.ViewMenu.Size = new System.Drawing.Size(44, 20); + this.ViewMenu.Text = "View"; + // + // MainToolbar + // + this.MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.NewButton, + this.OpenButton, + this.SaveButton}); + this.MainToolbar.Location = new System.Drawing.Point(0, 24); + this.MainToolbar.Name = "MainToolbar"; + this.MainToolbar.Size = new System.Drawing.Size(823, 25); + this.MainToolbar.TabIndex = 3; + this.MainToolbar.Text = "Main Toolbar"; + // + // NewButton + // + this.NewButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.NewButton.Image = ((System.Drawing.Image)(resources.GetObject("NewButton.Image"))); + this.NewButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.NewButton.Name = "NewButton"; + this.NewButton.Size = new System.Drawing.Size(32, 22); + this.NewButton.Text = "New..."; + this.NewButton.ButtonClick += new System.EventHandler(this.NewButton_ButtonClick); + // + // OpenButton + // + this.OpenButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.OpenButton.Image = ((System.Drawing.Image)(resources.GetObject("OpenButton.Image"))); + this.OpenButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.OpenButton.Name = "OpenButton"; + this.OpenButton.Size = new System.Drawing.Size(32, 22); + this.OpenButton.Text = "Open..."; + this.OpenButton.ButtonClick += new System.EventHandler(this.OpenButton_ButtonClick); + // + // SaveButton + // + this.SaveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.SaveButton.Image = ((System.Drawing.Image)(resources.GetObject("SaveButton.Image"))); + this.SaveButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.SaveButton.Name = "SaveButton"; + this.SaveButton.Size = new System.Drawing.Size(32, 22); + this.SaveButton.Text = "Save"; + this.SaveButton.ButtonClick += new System.EventHandler(this.SaveButton_ButtonClick); + // + // OpenFileDialog + // + this.OpenFileDialog.Filter = "Text files|*.txt|All files|*.*"; + // + // SaveFileDialog + // + this.SaveFileDialog.Filter = "Text files|*.txt|All files|*.*"; + this.SaveFileDialog.FilterIndex = 2; + // + // TextForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(823, 538); + this.Controls.Add(this.MainToolbar); + this.Controls.Add(this.MainStatusStrip); + this.Controls.Add(this.MainMenu); + this.Controls.Add(this.MainTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.MainMenu; + this.Name = "TextForm"; + this.Text = "Text Editor - CodeWalker by dexyfex"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.TextForm_FormClosing); + ((System.ComponentModel.ISupportInitialize)(this.MainTextBox)).EndInit(); + this.MainStatusStrip.ResumeLayout(false); + this.MainStatusStrip.PerformLayout(); + this.MainMenu.ResumeLayout(false); + this.MainMenu.PerformLayout(); + this.MainToolbar.ResumeLayout(false); + this.MainToolbar.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private FastColoredTextBoxNS.FastColoredTextBox MainTextBox; + private System.Windows.Forms.StatusStrip MainStatusStrip; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.MenuStrip MainMenu; + private System.Windows.Forms.ToolStripMenuItem FileMenu; + private System.Windows.Forms.ToolStripMenuItem EditMenu; + private System.Windows.Forms.ToolStripMenuItem ViewMenu; + private System.Windows.Forms.ToolStrip MainToolbar; + private System.Windows.Forms.ToolStripSplitButton NewButton; + private System.Windows.Forms.ToolStripSplitButton OpenButton; + private System.Windows.Forms.ToolStripSplitButton SaveButton; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + private System.Windows.Forms.SaveFileDialog SaveFileDialog; + private System.Windows.Forms.ToolStripMenuItem FileNewMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenMenu; + private System.Windows.Forms.ToolStripMenuItem FileSaveMenu; + private System.Windows.Forms.ToolStripMenuItem FileSaveAsMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem FileCloseMenu; + } +} \ No newline at end of file diff --git a/Forms/TextForm.cs b/Forms/TextForm.cs new file mode 100644 index 0000000..90ffb49 --- /dev/null +++ b/Forms/TextForm.cs @@ -0,0 +1,208 @@ +using CodeWalker.Properties; +using FastColoredTextBoxNS; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class TextForm : Form + { + private string textValue; + public string TextValue + { + get { return textValue; } + set + { + textValue = value; + UpdateTextBoxFromData(); + } + } + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + private bool modified = false; + + + public TextForm() + { + InitializeComponent(); + } + + + + public void LoadText(string filename, string filepath, string text) + { + FileName = filename; + FilePath = filepath; + TextValue = text; + modified = false; + } + + private void UpdateFormTitle() + { + Text = fileName + " - Text Editor - CodeWalker by dexyfex"; + } + + private void UpdateTextBoxFromData() + { + if (string.IsNullOrEmpty(textValue)) + { + MainTextBox.Text = ""; + return; + } + + Cursor = Cursors.WaitCursor; + + + + MainTextBox.Text = textValue; + //MainTextBox.IsChanged = false; + MainTextBox.ClearUndo(); + + Cursor = Cursors.Default; + } + + + + private bool CloseDocument() + { + if (modified) + { + var res = MessageBox.Show("Do you want to save the current document before closing it?", "Save before closing", MessageBoxButtons.YesNoCancel); + switch (res) + { + case DialogResult.Yes: + SaveDocument(); + break; + case DialogResult.Cancel: + return false; + } + } + + FilePath = ""; + FileName = ""; + TextValue = ""; + modified = false; + + return true; + } + private void NewDocument() + { + if (!CloseDocument()) return; //same thing really.. + + FileName = "New.txt"; + } + private void OpenDocument() + { + if (OpenFileDialog.ShowDialog() != DialogResult.OK) return; + + if (!CloseDocument()) return; + + var fn = OpenFileDialog.FileName; + + if (!File.Exists(fn)) return; //couldn't find file? + + TextValue = File.ReadAllText(fn); + + modified = false; + FilePath = fn; + FileName = new FileInfo(fn).Name; + } + private void SaveDocument(bool saveAs = false) + { + if (string.IsNullOrEmpty(FileName)) saveAs = true; + if (string.IsNullOrEmpty(FilePath)) saveAs = true; + else if ((FilePath.ToLowerInvariant().StartsWith(Settings.Default.GTAFolder.ToLowerInvariant()))) saveAs = true; + if (!File.Exists(FilePath)) saveAs = true; + + var fn = FilePath; + if (saveAs) + { + if (!string.IsNullOrEmpty(fn)) + { + var dir = new FileInfo(fn).DirectoryName; + if (!Directory.Exists(dir)) dir = ""; + SaveFileDialog.InitialDirectory = dir; + } + SaveFileDialog.FileName = FileName; + if (SaveFileDialog.ShowDialog() != DialogResult.OK) return; + fn = SaveFileDialog.FileName; + } + + File.WriteAllText(fn, textValue); + + modified = false; + FilePath = fn; + FileName = new FileInfo(fn).Name; + } + + private void MainTextBox_TextChanged(object sender, TextChangedEventArgs e) + { + textValue = MainTextBox.Text; + modified = true; + } + + private void NewButton_ButtonClick(object sender, EventArgs e) + { + NewDocument(); + } + + private void OpenButton_ButtonClick(object sender, EventArgs e) + { + OpenDocument(); + } + + private void SaveButton_ButtonClick(object sender, EventArgs e) + { + SaveDocument(); + } + + private void FileNewMenu_Click(object sender, EventArgs e) + { + NewDocument(); + } + + private void FileOpenMenu_Click(object sender, EventArgs e) + { + OpenDocument(); + } + + private void FileSaveMenu_Click(object sender, EventArgs e) + { + SaveDocument(); + } + + private void FileSaveAsMenu_Click(object sender, EventArgs e) + { + SaveDocument(true); + } + + private void FileCloseMenu_Click(object sender, EventArgs e) + { + Close(); + } + + private void TextForm_FormClosing(object sender, FormClosingEventArgs e) + { + e.Cancel = !CloseDocument(); + } + } +} diff --git a/Forms/TextForm.resx b/Forms/TextForm.resx new file mode 100644 index 0000000..05f1051 --- /dev/null +++ b/Forms/TextForm.resx @@ -0,0 +1,471 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdGYXN0Q29sb3JlZFRleHRCb3gsIFZlcnNpb249Mi4xNi4yMS4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWZiOGFhMTJiOTk0ZWY2MWIMAwAAAFFTeXN0 + ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2Vu + PWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACJGYXN0Q29sb3JlZFRleHRCb3hOUy5TZXJ2aWNlQ29sb3JzBgAA + ACg8Q29sbGFwc2VNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxDb2xsYXBzZU1hcmtlckJh + Y2tDb2xvcj5rX19CYWNraW5nRmllbGQqPENvbGxhcHNlTWFya2VyQm9yZGVyQ29sb3I+a19fQmFja2lu + Z0ZpZWxkJjxFeHBhbmRNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkJjxFeHBhbmRNYXJrZXJC + YWNrQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxFeHBhbmRNYXJrZXJCb3JkZXJDb2xvcj5rX19CYWNraW5n + RmllbGQEBAQEBAQUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5EcmF3aW5nLkNvbG9yAwAA + ABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAAUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5E + cmF3aW5nLkNvbG9yAwAAABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAACAAAABfz///8UU3lzdGVtLkRy + YXdpbmcuQ29sb3IEAAAABG5hbWUFdmFsdWUKa25vd25Db2xvcgVzdGF0ZQEAAAAJBwcDAAAACgAAAAAA + AAAAlgABAAH7/////P///woAAAAAAAAAAKQAAQAB+v////z///8KAAAAAAAAAACWAAEAAfn////8//// + CgAAAAAAAAAAlgABAAH4/////P///woAAAAAAAAAAKQAAQAB9/////z///8KAAAAAAAAAACWAAEACw== + + + + 17, 17 + + + 155, 17 + + + 265, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADESURBVDhPzZI7DgIhGIQ5grUnsPQMnMgLWMo1bDyJiYUV + h7CxEo1Aiw7+E9ldWF+Nk0w2wMy3/z5UqRDCwjk3iTEmGmvsS6Ste2gtJYvrdjklJK9xLtGhcAeEdqtZ + Ouw3uUgA1tgXSH0SGdsyfD0dcwHXAmqRk0pXCNMsN+y893OpPYVDjFw8d9JaD2yMqUNYgjkBCmd36bgJ + 6b+DMUAJkXr9K9QANM6QkfpD/f/gYwCESfgnfgWg/gcw5peAdyzxX6TUDfMCML1omZa9AAAAAElFTkSu + QmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEcSURBVDhPlZKxqsIwFIb7Bvc+idxHuPQVXFpQcOhe8Amc + OqqzCBdU6HQfQIfunVwKoi7FQQeF9GrajufmhDYkTaMY+EjPyf//TZtY9aCUfhVFQRggQbBfSV4PFJ8v + GekMf8HqzqE3jXhIhRwsqKyWxYpJ3bzcMpBD4jgG27Y1RACaZ+sEPvoLbmqCa/f7AzLyJ2gGcDO+bXe6 + ajugDypMiBJQluU3f2DiZ+YmT3eANWIyIyKgFsv/AOs2k4wSgIXneRBFEaRpyhew10ZbwNb3fU1oYrPe + qAF5no/CMNSEJsbjiRqAty9JEk1ownEcNaA6BeK6riY2cdgf+SwC2Gf8BEGgCU2slis+iwB2mQZ4Ak3h + K0QAIeQTi/cp4B9tCZE2c6oRhQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABWSURBVDhPY6AK+Pbt238S8PsvX74YQLVCAEjCyckJjj+8 + /wjHyGIguq2tDdMQUgwAYZghUO2kGwDCID1Q7fgNQMbIamhrADF41IBBaQA5GKqdEsDAAADtDPd9n5qK + lQAAAABJRU5ErkJggg== + + + + 386, 17 + + + 521, 17 + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/XmlForm.Designer.cs b/Forms/XmlForm.Designer.cs new file mode 100644 index 0000000..1435a3a --- /dev/null +++ b/Forms/XmlForm.Designer.cs @@ -0,0 +1,297 @@ +namespace CodeWalker.Forms +{ + partial class XmlForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XmlForm)); + this.XmlTextBox = new FastColoredTextBoxNS.FastColoredTextBox(); + this.MainStatusStrip = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.MainMenu = new System.Windows.Forms.MenuStrip(); + this.FileMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveAsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.FileCloseMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.MainToolbar = new System.Windows.Forms.ToolStrip(); + this.NewButton = new System.Windows.Forms.ToolStripSplitButton(); + this.OpenButton = new System.Windows.Forms.ToolStripSplitButton(); + this.SaveButton = new System.Windows.Forms.ToolStripSplitButton(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog(); + ((System.ComponentModel.ISupportInitialize)(this.XmlTextBox)).BeginInit(); + this.MainStatusStrip.SuspendLayout(); + this.MainMenu.SuspendLayout(); + this.MainToolbar.SuspendLayout(); + this.SuspendLayout(); + // + // XmlTextBox + // + this.XmlTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.XmlTextBox.AutoCompleteBracketsList = new char[] { + '(', + ')', + '{', + '}', + '[', + ']', + '\"', + '\"', + '\'', + '\''}; + this.XmlTextBox.AutoIndentChars = false; + this.XmlTextBox.AutoIndentCharsPatterns = ""; + this.XmlTextBox.AutoIndentExistingLines = false; + this.XmlTextBox.AutoScrollMinSize = new System.Drawing.Size(27, 14); + this.XmlTextBox.BackBrush = null; + this.XmlTextBox.CharHeight = 14; + this.XmlTextBox.CharWidth = 8; + this.XmlTextBox.CommentPrefix = null; + this.XmlTextBox.Cursor = System.Windows.Forms.Cursors.IBeam; + this.XmlTextBox.DelayedEventsInterval = 1; + this.XmlTextBox.DisabledColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180))))); + this.XmlTextBox.IsReplaceMode = false; + this.XmlTextBox.Language = FastColoredTextBoxNS.Language.XML; + this.XmlTextBox.LeftBracket = '<'; + this.XmlTextBox.LeftBracket2 = '('; + this.XmlTextBox.Location = new System.Drawing.Point(0, 52); + this.XmlTextBox.Name = "XmlTextBox"; + this.XmlTextBox.Paddings = new System.Windows.Forms.Padding(0); + this.XmlTextBox.RightBracket = '>'; + this.XmlTextBox.RightBracket2 = ')'; + this.XmlTextBox.SelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255))))); + this.XmlTextBox.ServiceColors = ((FastColoredTextBoxNS.ServiceColors)(resources.GetObject("XmlTextBox.ServiceColors"))); + this.XmlTextBox.Size = new System.Drawing.Size(834, 482); + this.XmlTextBox.TabIndex = 0; + this.XmlTextBox.Zoom = 100; + this.XmlTextBox.TextChanged += new System.EventHandler(this.XmlTextBox_TextChanged); + this.XmlTextBox.VisibleRangeChangedDelayed += new System.EventHandler(this.XmlTextBox_VisibleRangeChangedDelayed); + // + // MainStatusStrip + // + this.MainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel}); + this.MainStatusStrip.Location = new System.Drawing.Point(0, 537); + this.MainStatusStrip.Name = "MainStatusStrip"; + this.MainStatusStrip.Size = new System.Drawing.Size(834, 22); + this.MainStatusStrip.TabIndex = 1; + this.MainStatusStrip.Text = "Main Status Strip"; + // + // StatusLabel + // + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(819, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // MainMenu + // + this.MainMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileMenu, + this.EditMenu, + this.ViewMenu}); + this.MainMenu.Location = new System.Drawing.Point(0, 0); + this.MainMenu.Name = "MainMenu"; + this.MainMenu.Size = new System.Drawing.Size(834, 24); + this.MainMenu.TabIndex = 2; + this.MainMenu.Text = "Main Menu"; + // + // FileMenu + // + this.FileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileNewMenu, + this.FileOpenMenu, + this.FileSaveMenu, + this.FileSaveAsMenu, + this.toolStripSeparator1, + this.FileCloseMenu}); + this.FileMenu.Name = "FileMenu"; + this.FileMenu.Size = new System.Drawing.Size(37, 20); + this.FileMenu.Text = "File"; + // + // FileNewMenu + // + this.FileNewMenu.Name = "FileNewMenu"; + this.FileNewMenu.Size = new System.Drawing.Size(145, 22); + this.FileNewMenu.Text = "New"; + this.FileNewMenu.Click += new System.EventHandler(this.FileNewMenu_Click); + // + // FileOpenMenu + // + this.FileOpenMenu.Name = "FileOpenMenu"; + this.FileOpenMenu.Size = new System.Drawing.Size(145, 22); + this.FileOpenMenu.Text = "Open..."; + this.FileOpenMenu.Click += new System.EventHandler(this.FileOpenMenu_Click); + // + // FileSaveMenu + // + this.FileSaveMenu.Name = "FileSaveMenu"; + this.FileSaveMenu.Size = new System.Drawing.Size(145, 22); + this.FileSaveMenu.Text = "Save"; + this.FileSaveMenu.Click += new System.EventHandler(this.FileSaveMenu_Click); + // + // FileSaveAsMenu + // + this.FileSaveAsMenu.Name = "FileSaveAsMenu"; + this.FileSaveAsMenu.Size = new System.Drawing.Size(145, 22); + this.FileSaveAsMenu.Text = "Save As..."; + this.FileSaveAsMenu.Click += new System.EventHandler(this.FileSaveAsMenu_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(142, 6); + // + // FileCloseMenu + // + this.FileCloseMenu.Name = "FileCloseMenu"; + this.FileCloseMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); + this.FileCloseMenu.Size = new System.Drawing.Size(145, 22); + this.FileCloseMenu.Text = "Close"; + this.FileCloseMenu.Click += new System.EventHandler(this.FileCloseMenu_Click); + // + // EditMenu + // + this.EditMenu.Enabled = false; + this.EditMenu.Name = "EditMenu"; + this.EditMenu.Size = new System.Drawing.Size(39, 20); + this.EditMenu.Text = "Edit"; + // + // ViewMenu + // + this.ViewMenu.Enabled = false; + this.ViewMenu.Name = "ViewMenu"; + this.ViewMenu.Size = new System.Drawing.Size(44, 20); + this.ViewMenu.Text = "View"; + // + // MainToolbar + // + this.MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.NewButton, + this.OpenButton, + this.SaveButton}); + this.MainToolbar.Location = new System.Drawing.Point(0, 24); + this.MainToolbar.Name = "MainToolbar"; + this.MainToolbar.Size = new System.Drawing.Size(834, 25); + this.MainToolbar.TabIndex = 3; + this.MainToolbar.Text = "Main Toolbar"; + // + // NewButton + // + this.NewButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.NewButton.Image = ((System.Drawing.Image)(resources.GetObject("NewButton.Image"))); + this.NewButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.NewButton.Name = "NewButton"; + this.NewButton.Size = new System.Drawing.Size(32, 22); + this.NewButton.Text = "New..."; + this.NewButton.ButtonClick += new System.EventHandler(this.NewButton_ButtonClick); + // + // OpenButton + // + this.OpenButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.OpenButton.Image = ((System.Drawing.Image)(resources.GetObject("OpenButton.Image"))); + this.OpenButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.OpenButton.Name = "OpenButton"; + this.OpenButton.Size = new System.Drawing.Size(32, 22); + this.OpenButton.Text = "Open..."; + this.OpenButton.ButtonClick += new System.EventHandler(this.OpenButton_ButtonClick); + // + // SaveButton + // + this.SaveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.SaveButton.Image = ((System.Drawing.Image)(resources.GetObject("SaveButton.Image"))); + this.SaveButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.SaveButton.Name = "SaveButton"; + this.SaveButton.Size = new System.Drawing.Size(32, 22); + this.SaveButton.Text = "Save"; + this.SaveButton.ButtonClick += new System.EventHandler(this.SaveButton_ButtonClick); + // + // OpenFileDialog + // + this.OpenFileDialog.Filter = "XML files|*.xml|All files|*.*"; + // + // SaveFileDialog + // + this.SaveFileDialog.Filter = "XML files|*.xml|All files|*.*"; + // + // XmlForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(834, 559); + this.Controls.Add(this.MainToolbar); + this.Controls.Add(this.MainStatusStrip); + this.Controls.Add(this.MainMenu); + this.Controls.Add(this.XmlTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.MainMenu; + this.Name = "XmlForm"; + this.Text = "XML Editor - CodeWalker by dexyfex"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.XmlForm_FormClosing); + ((System.ComponentModel.ISupportInitialize)(this.XmlTextBox)).EndInit(); + this.MainStatusStrip.ResumeLayout(false); + this.MainStatusStrip.PerformLayout(); + this.MainMenu.ResumeLayout(false); + this.MainMenu.PerformLayout(); + this.MainToolbar.ResumeLayout(false); + this.MainToolbar.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private FastColoredTextBoxNS.FastColoredTextBox XmlTextBox; + private System.Windows.Forms.StatusStrip MainStatusStrip; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.MenuStrip MainMenu; + private System.Windows.Forms.ToolStripMenuItem FileMenu; + private System.Windows.Forms.ToolStripMenuItem EditMenu; + private System.Windows.Forms.ToolStripMenuItem ViewMenu; + private System.Windows.Forms.ToolStrip MainToolbar; + private System.Windows.Forms.ToolStripSplitButton NewButton; + private System.Windows.Forms.ToolStripSplitButton OpenButton; + private System.Windows.Forms.ToolStripSplitButton SaveButton; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + private System.Windows.Forms.SaveFileDialog SaveFileDialog; + private System.Windows.Forms.ToolStripMenuItem FileNewMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenMenu; + private System.Windows.Forms.ToolStripMenuItem FileSaveMenu; + private System.Windows.Forms.ToolStripMenuItem FileSaveAsMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem FileCloseMenu; + } +} \ No newline at end of file diff --git a/Forms/XmlForm.cs b/Forms/XmlForm.cs new file mode 100644 index 0000000..529d1ef --- /dev/null +++ b/Forms/XmlForm.cs @@ -0,0 +1,276 @@ +using CodeWalker.Properties; +using FastColoredTextBoxNS; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class XmlForm : Form + { + private string xml; + public string Xml + { + get { return xml; } + set + { + xml = value; + UpdateTextBoxFromData(); + } + } + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + private bool modified = false; + private bool LoadingXml = false; + private bool DelayHighlight = false; + + + public XmlForm() + { + InitializeComponent(); + } + + + + public void LoadXml(string filename, string filepath, string xml) + { + FileName = filename; + FilePath = filepath; + Xml = xml; + modified = false; + } + + private void UpdateFormTitle() + { + Text = fileName + " - XML Editor - CodeWalker by dexyfex"; + } + + private void UpdateTextBoxFromData() + { + LoadingXml = true; + XmlTextBox.Text = ""; + XmlTextBox.Language = Language.XML; + DelayHighlight = false; + + if (string.IsNullOrEmpty(xml)) + { + LoadingXml = false; + return; + } + //if (xml.Length > (1048576 * 5)) + //{ + // XmlTextBox.Language = Language.Custom; + // XmlTextBox.Text = "[XML size > 10MB - Not shown due to performance limitations - Please use an external viewer for this file.]"; + // return; + //} + //else + if (xml.Length > (1024 * 512)) + { + XmlTextBox.Language = Language.Custom; + DelayHighlight = true; + } + //else + //{ + // XmlTextBox.Language = Language.XML; + //} + + + Cursor = Cursors.WaitCursor; + + + + XmlTextBox.Text = xml; + //XmlTextBox.IsChanged = false; + XmlTextBox.ClearUndo(); + + Cursor = Cursors.Default; + LoadingXml = false; + } + + + + private bool CloseDocument() + { + if (modified) + { + var res = MessageBox.Show("Do you want to save the current document before closing it?", "Save before closing", MessageBoxButtons.YesNoCancel); + switch (res) + { + case DialogResult.Yes: + SaveDocument(); + break; + case DialogResult.Cancel: + return false; + } + } + + FilePath = ""; + FileName = ""; + Xml = ""; + modified = false; + + return true; + } + private void NewDocument() + { + if (!CloseDocument()) return; //same thing really.. + + FileName = "New.xml"; + } + private void OpenDocument() + { + if (OpenFileDialog.ShowDialog() != DialogResult.OK) return; + + if (!CloseDocument()) return; + + var fn = OpenFileDialog.FileName; + + if (!File.Exists(fn)) return; //couldn't find file? + + Xml = File.ReadAllText(fn); + + modified = false; + FilePath = fn; + FileName = new FileInfo(fn).Name; + } + private void SaveDocument(bool saveAs = false) + { + if (string.IsNullOrEmpty(FileName)) saveAs = true; + if (string.IsNullOrEmpty(FilePath)) saveAs = true; + else if ((FilePath.ToLowerInvariant().StartsWith(Settings.Default.GTAFolder.ToLowerInvariant()))) saveAs = true; + if (!File.Exists(FilePath)) saveAs = true; + + var fn = FilePath; + if (saveAs) + { + if (!string.IsNullOrEmpty(fn)) + { + var dir = new FileInfo(fn).DirectoryName; + if (!Directory.Exists(dir)) dir = ""; + SaveFileDialog.InitialDirectory = dir; + } + SaveFileDialog.FileName = FileName; + if (SaveFileDialog.ShowDialog() != DialogResult.OK) return; + fn = SaveFileDialog.FileName; + } + + File.WriteAllText(fn, xml); + + modified = false; + FilePath = fn; + FileName = new FileInfo(fn).Name; + } + + + + + + + + Style BlueStyle = new TextStyle(Brushes.Blue, null, FontStyle.Regular); + Style RedStyle = new TextStyle(Brushes.Red, null, FontStyle.Regular); + Style MaroonStyle = new TextStyle(Brushes.Maroon, null, FontStyle.Regular); + + private void HTMLSyntaxHighlight(Range range) + { + //clear style of changed range + range.ClearStyle(BlueStyle, MaroonStyle, RedStyle); + //tag brackets highlighting + range.SetStyle(BlueStyle, @"<|/>|"); + //tag name + range.SetStyle(MaroonStyle, @"<(?[!\w]+)"); + //end of tag + range.SetStyle(MaroonStyle, @"\w+)>"); + //attributes + range.SetStyle(RedStyle, @"(?\S+?)='[^']*'|(?\S+)=""[^""]*""|(?\S+)=\S+"); + //attribute values + range.SetStyle(BlueStyle, @"\S+?=(?'[^']*')|\S+=(?""[^""]*"")|\S+=(?\S+)"); + } + + private void XmlTextBox_VisibleRangeChangedDelayed(object sender, EventArgs e) + { + //this approach is much faster to load, but no outlining is available + + //highlight only visible area of text + if (DelayHighlight) + { + HTMLSyntaxHighlight(XmlTextBox.VisibleRange); + } + } + + + + + private void XmlTextBox_TextChanged(object sender, TextChangedEventArgs e) + { + if (!LoadingXml) + { + xml = XmlTextBox.Text; + modified = true; + } + } + + private void NewButton_ButtonClick(object sender, EventArgs e) + { + NewDocument(); + } + + private void OpenButton_ButtonClick(object sender, EventArgs e) + { + OpenDocument(); + } + + private void SaveButton_ButtonClick(object sender, EventArgs e) + { + SaveDocument(); + } + + private void FileNewMenu_Click(object sender, EventArgs e) + { + NewDocument(); + } + + private void FileOpenMenu_Click(object sender, EventArgs e) + { + OpenDocument(); + } + + private void FileSaveMenu_Click(object sender, EventArgs e) + { + SaveDocument(); + } + + private void FileSaveAsMenu_Click(object sender, EventArgs e) + { + SaveDocument(true); + } + + private void FileCloseMenu_Click(object sender, EventArgs e) + { + Close(); + } + + private void XmlForm_FormClosing(object sender, FormClosingEventArgs e) + { + e.Cancel = !CloseDocument(); + } + } +} diff --git a/Forms/XmlForm.resx b/Forms/XmlForm.resx new file mode 100644 index 0000000..8a86319 --- /dev/null +++ b/Forms/XmlForm.resx @@ -0,0 +1,471 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdGYXN0Q29sb3JlZFRleHRCb3gsIFZlcnNpb249Mi4xNi4yMS4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWZiOGFhMTJiOTk0ZWY2MWIMAwAAAFFTeXN0 + ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2Vu + PWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACJGYXN0Q29sb3JlZFRleHRCb3hOUy5TZXJ2aWNlQ29sb3JzBgAA + ACg8Q29sbGFwc2VNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxDb2xsYXBzZU1hcmtlckJh + Y2tDb2xvcj5rX19CYWNraW5nRmllbGQqPENvbGxhcHNlTWFya2VyQm9yZGVyQ29sb3I+a19fQmFja2lu + Z0ZpZWxkJjxFeHBhbmRNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkJjxFeHBhbmRNYXJrZXJC + YWNrQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxFeHBhbmRNYXJrZXJCb3JkZXJDb2xvcj5rX19CYWNraW5n + RmllbGQEBAQEBAQUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5EcmF3aW5nLkNvbG9yAwAA + ABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAAUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5E + cmF3aW5nLkNvbG9yAwAAABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAACAAAABfz///8UU3lzdGVtLkRy + YXdpbmcuQ29sb3IEAAAABG5hbWUFdmFsdWUKa25vd25Db2xvcgVzdGF0ZQEAAAAJBwcDAAAACgAAAAAA + AAAAlgABAAH7/////P///woAAAAAAAAAAKQAAQAB+v////z///8KAAAAAAAAAACWAAEAAfn////8//// + CgAAAAAAAAAATgABAAH4/////P///woAAAAAAAAAAKQAAQAB9/////z///8KAAAAAAAAAACWAAEACw== + + + + 17, 17 + + + 155, 17 + + + 265, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADESURBVDhPzZI7DgIhGIQ5grUnsPQMnMgLWMo1bDyJiYUV + h7CxEo1Aiw7+E9ldWF+Nk0w2wMy3/z5UqRDCwjk3iTEmGmvsS6Ste2gtJYvrdjklJK9xLtGhcAeEdqtZ + Ouw3uUgA1tgXSH0SGdsyfD0dcwHXAmqRk0pXCNMsN+y893OpPYVDjFw8d9JaD2yMqUNYgjkBCmd36bgJ + 6b+DMUAJkXr9K9QANM6QkfpD/f/gYwCESfgnfgWg/gcw5peAdyzxX6TUDfMCML1omZa9AAAAAElFTkSu + QmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEcSURBVDhPlZKxqsIwFIb7Bvc+idxHuPQVXFpQcOhe8Amc + OqqzCBdU6HQfQIfunVwKoi7FQQeF9GrajufmhDYkTaMY+EjPyf//TZtY9aCUfhVFQRggQbBfSV4PFJ8v + GekMf8HqzqE3jXhIhRwsqKyWxYpJ3bzcMpBD4jgG27Y1RACaZ+sEPvoLbmqCa/f7AzLyJ2gGcDO+bXe6 + ajugDypMiBJQluU3f2DiZ+YmT3eANWIyIyKgFsv/AOs2k4wSgIXneRBFEaRpyhew10ZbwNb3fU1oYrPe + qAF5no/CMNSEJsbjiRqAty9JEk1ownEcNaA6BeK6riY2cdgf+SwC2Gf8BEGgCU2slis+iwB2mQZ4Ak3h + K0QAIeQTi/cp4B9tCZE2c6oRhQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABWSURBVDhPY6AK+Pbt238S8PsvX74YQLVCAEjCyckJjj+8 + /wjHyGIguq2tDdMQUgwAYZghUO2kGwDCID1Q7fgNQMbIamhrADF41IBBaQA5GKqdEsDAAADtDPd9n5qK + lQAAAABJRU5ErkJggg== + + + + 386, 17 + + + 521, 17 + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/YtdForm.Designer.cs b/Forms/YtdForm.Designer.cs new file mode 100644 index 0000000..6e9dc23 --- /dev/null +++ b/Forms/YtdForm.Designer.cs @@ -0,0 +1,400 @@ +namespace CodeWalker.Forms +{ + partial class YtdForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(YtdForm)); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.FileMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.EditMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.NewButton = new System.Windows.Forms.ToolStripSplitButton(); + this.OpenButton = new System.Windows.Forms.ToolStripSplitButton(); + this.SaveButton = new System.Windows.Forms.ToolStripSplitButton(); + this.MainToolbar = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.MainSplitContainer = new System.Windows.Forms.SplitContainer(); + this.TexturesListView = new System.Windows.Forms.ListView(); + this.TextureNameColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.TextureSizeColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.label5 = new System.Windows.Forms.Label(); + this.SelTextureNameTextBox = new System.Windows.Forms.TextBox(); + this.TextureTabControl = new System.Windows.Forms.TabControl(); + this.TextureTabPage = new System.Windows.Forms.TabPage(); + this.SelTextureMipLabel = new System.Windows.Forms.Label(); + this.SelTextureDimensionsLabel = new System.Windows.Forms.Label(); + this.SelTextureMipTrackBar = new System.Windows.Forms.TrackBar(); + this.label4 = new System.Windows.Forms.Label(); + this.SelTexturePictureBox = new System.Windows.Forms.PictureBox(); + this.DetailsTabPage = new System.Windows.Forms.TabPage(); + this.DetailsPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.menuStrip1.SuspendLayout(); + this.toolStrip1.SuspendLayout(); + this.MainToolbar.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.MainSplitContainer)).BeginInit(); + this.MainSplitContainer.Panel1.SuspendLayout(); + this.MainSplitContainer.Panel2.SuspendLayout(); + this.MainSplitContainer.SuspendLayout(); + this.TextureTabControl.SuspendLayout(); + this.TextureTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.SelTextureMipTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.SelTexturePictureBox)).BeginInit(); + this.DetailsTabPage.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileMenu, + this.EditMenu, + this.ViewMenu}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(845, 24); + this.menuStrip1.TabIndex = 0; + this.menuStrip1.Text = "menuStrip1"; + // + // FileMenu + // + this.FileMenu.Enabled = false; + this.FileMenu.Name = "FileMenu"; + this.FileMenu.Size = new System.Drawing.Size(37, 20); + this.FileMenu.Text = "File"; + // + // EditMenu + // + this.EditMenu.Enabled = false; + this.EditMenu.Name = "EditMenu"; + this.EditMenu.Size = new System.Drawing.Size(39, 20); + this.EditMenu.Text = "Edit"; + // + // ViewMenu + // + this.ViewMenu.Enabled = false; + this.ViewMenu.Name = "ViewMenu"; + this.ViewMenu.Size = new System.Drawing.Size(44, 20); + this.ViewMenu.Text = "View"; + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.NewButton, + this.OpenButton, + this.SaveButton}); + this.toolStrip1.Location = new System.Drawing.Point(0, 24); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(845, 25); + this.toolStrip1.TabIndex = 1; + this.toolStrip1.Text = "toolStrip1"; + // + // NewButton + // + this.NewButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.NewButton.Enabled = false; + this.NewButton.Image = ((System.Drawing.Image)(resources.GetObject("NewButton.Image"))); + this.NewButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.NewButton.Name = "NewButton"; + this.NewButton.Size = new System.Drawing.Size(32, 22); + this.NewButton.Text = "New YTD..."; + // + // OpenButton + // + this.OpenButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.OpenButton.Enabled = false; + this.OpenButton.Image = ((System.Drawing.Image)(resources.GetObject("OpenButton.Image"))); + this.OpenButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.OpenButton.Name = "OpenButton"; + this.OpenButton.Size = new System.Drawing.Size(32, 22); + this.OpenButton.Text = "Open YTD..."; + // + // SaveButton + // + this.SaveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.SaveButton.Enabled = false; + this.SaveButton.Image = ((System.Drawing.Image)(resources.GetObject("SaveButton.Image"))); + this.SaveButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.SaveButton.Name = "SaveButton"; + this.SaveButton.Size = new System.Drawing.Size(32, 22); + this.SaveButton.Text = "Save YTD..."; + // + // MainToolbar + // + this.MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel}); + this.MainToolbar.Location = new System.Drawing.Point(0, 538); + this.MainToolbar.Name = "MainToolbar"; + this.MainToolbar.Size = new System.Drawing.Size(845, 22); + this.MainToolbar.TabIndex = 2; + this.MainToolbar.Text = "Toolbar"; + // + // StatusLabel + // + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(830, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // MainSplitContainer + // + this.MainSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.MainSplitContainer.Location = new System.Drawing.Point(0, 49); + this.MainSplitContainer.Name = "MainSplitContainer"; + // + // MainSplitContainer.Panel1 + // + this.MainSplitContainer.Panel1.Controls.Add(this.TexturesListView); + // + // MainSplitContainer.Panel2 + // + this.MainSplitContainer.Panel2.Controls.Add(this.label5); + this.MainSplitContainer.Panel2.Controls.Add(this.SelTextureNameTextBox); + this.MainSplitContainer.Panel2.Controls.Add(this.TextureTabControl); + this.MainSplitContainer.Size = new System.Drawing.Size(845, 489); + this.MainSplitContainer.SplitterDistance = 257; + this.MainSplitContainer.TabIndex = 3; + // + // TexturesListView + // + this.TexturesListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TexturesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.TextureNameColumnHeader, + this.TextureSizeColumnHeader}); + this.TexturesListView.FullRowSelect = true; + this.TexturesListView.HideSelection = false; + this.TexturesListView.Location = new System.Drawing.Point(3, 3); + this.TexturesListView.Name = "TexturesListView"; + this.TexturesListView.ShowItemToolTips = true; + this.TexturesListView.Size = new System.Drawing.Size(251, 483); + this.TexturesListView.TabIndex = 0; + this.TexturesListView.UseCompatibleStateImageBehavior = false; + this.TexturesListView.View = System.Windows.Forms.View.Details; + this.TexturesListView.SelectedIndexChanged += new System.EventHandler(this.TexturesListView_SelectedIndexChanged); + // + // TextureNameColumnHeader + // + this.TextureNameColumnHeader.Text = "Name"; + this.TextureNameColumnHeader.Width = 153; + // + // TextureSizeColumnHeader + // + this.TextureSizeColumnHeader.Text = "Size"; + this.TextureSizeColumnHeader.Width = 72; + // + // label5 + // + this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(262, 6); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(38, 13); + this.label5.TabIndex = 50; + this.label5.Text = "Name:"; + // + // SelTextureNameTextBox + // + this.SelTextureNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.SelTextureNameTextBox.Location = new System.Drawing.Point(306, 3); + this.SelTextureNameTextBox.Name = "SelTextureNameTextBox"; + this.SelTextureNameTextBox.Size = new System.Drawing.Size(271, 20); + this.SelTextureNameTextBox.TabIndex = 46; + // + // TextureTabControl + // + this.TextureTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TextureTabControl.Controls.Add(this.TextureTabPage); + this.TextureTabControl.Controls.Add(this.DetailsTabPage); + this.TextureTabControl.Location = new System.Drawing.Point(3, 3); + this.TextureTabControl.Name = "TextureTabControl"; + this.TextureTabControl.SelectedIndex = 0; + this.TextureTabControl.Size = new System.Drawing.Size(578, 483); + this.TextureTabControl.TabIndex = 0; + // + // TextureTabPage + // + this.TextureTabPage.Controls.Add(this.SelTextureMipLabel); + this.TextureTabPage.Controls.Add(this.SelTextureDimensionsLabel); + this.TextureTabPage.Controls.Add(this.SelTextureMipTrackBar); + this.TextureTabPage.Controls.Add(this.label4); + this.TextureTabPage.Controls.Add(this.SelTexturePictureBox); + this.TextureTabPage.Location = new System.Drawing.Point(4, 22); + this.TextureTabPage.Name = "TextureTabPage"; + this.TextureTabPage.Padding = new System.Windows.Forms.Padding(3); + this.TextureTabPage.Size = new System.Drawing.Size(570, 457); + this.TextureTabPage.TabIndex = 0; + this.TextureTabPage.Text = "Texture"; + this.TextureTabPage.UseVisualStyleBackColor = true; + // + // SelTextureMipLabel + // + this.SelTextureMipLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.SelTextureMipLabel.AutoSize = true; + this.SelTextureMipLabel.Location = new System.Drawing.Point(44, 426); + this.SelTextureMipLabel.Name = "SelTextureMipLabel"; + this.SelTextureMipLabel.Size = new System.Drawing.Size(13, 13); + this.SelTextureMipLabel.TabIndex = 51; + this.SelTextureMipLabel.Text = "0"; + // + // SelTextureDimensionsLabel + // + this.SelTextureDimensionsLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.SelTextureDimensionsLabel.AutoSize = true; + this.SelTextureDimensionsLabel.Location = new System.Drawing.Point(304, 426); + this.SelTextureDimensionsLabel.Name = "SelTextureDimensionsLabel"; + this.SelTextureDimensionsLabel.Size = new System.Drawing.Size(10, 13); + this.SelTextureDimensionsLabel.TabIndex = 49; + this.SelTextureDimensionsLabel.Text = "-"; + // + // SelTextureMipTrackBar + // + this.SelTextureMipTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelTextureMipTrackBar.AutoSize = false; + this.SelTextureMipTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.SelTextureMipTrackBar.LargeChange = 1; + this.SelTextureMipTrackBar.Location = new System.Drawing.Point(63, 420); + this.SelTextureMipTrackBar.Maximum = 0; + this.SelTextureMipTrackBar.Name = "SelTextureMipTrackBar"; + this.SelTextureMipTrackBar.Size = new System.Drawing.Size(234, 31); + this.SelTextureMipTrackBar.TabIndex = 48; + this.SelTextureMipTrackBar.Scroll += new System.EventHandler(this.SelTextureMipTrackBar_Scroll); + // + // label4 + // + this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(13, 426); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(27, 13); + this.label4.TabIndex = 47; + this.label4.Text = "Mip:"; + // + // SelTexturePictureBox + // + this.SelTexturePictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelTexturePictureBox.BackColor = System.Drawing.Color.DarkGray; + this.SelTexturePictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.SelTexturePictureBox.Location = new System.Drawing.Point(6, 6); + this.SelTexturePictureBox.Name = "SelTexturePictureBox"; + this.SelTexturePictureBox.Size = new System.Drawing.Size(558, 408); + this.SelTexturePictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.SelTexturePictureBox.TabIndex = 45; + this.SelTexturePictureBox.TabStop = false; + // + // DetailsTabPage + // + this.DetailsTabPage.Controls.Add(this.DetailsPropertyGrid); + this.DetailsTabPage.Location = new System.Drawing.Point(4, 22); + this.DetailsTabPage.Name = "DetailsTabPage"; + this.DetailsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.DetailsTabPage.Size = new System.Drawing.Size(570, 457); + this.DetailsTabPage.TabIndex = 1; + this.DetailsTabPage.Text = "Details"; + this.DetailsTabPage.UseVisualStyleBackColor = true; + // + // DetailsPropertyGrid + // + this.DetailsPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.DetailsPropertyGrid.HelpVisible = false; + this.DetailsPropertyGrid.Location = new System.Drawing.Point(6, 6); + this.DetailsPropertyGrid.Name = "DetailsPropertyGrid"; + this.DetailsPropertyGrid.Size = new System.Drawing.Size(558, 445); + this.DetailsPropertyGrid.TabIndex = 0; + // + // YtdForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(845, 560); + this.Controls.Add(this.MainSplitContainer); + this.Controls.Add(this.MainToolbar); + this.Controls.Add(this.toolStrip1); + this.Controls.Add(this.menuStrip1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.menuStrip1; + this.Name = "YtdForm"; + this.Text = "Texture Dictionary - CodeWalker by dexyfex"; + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.MainToolbar.ResumeLayout(false); + this.MainToolbar.PerformLayout(); + this.MainSplitContainer.Panel1.ResumeLayout(false); + this.MainSplitContainer.Panel2.ResumeLayout(false); + this.MainSplitContainer.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.MainSplitContainer)).EndInit(); + this.MainSplitContainer.ResumeLayout(false); + this.TextureTabControl.ResumeLayout(false); + this.TextureTabPage.ResumeLayout(false); + this.TextureTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.SelTextureMipTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.SelTexturePictureBox)).EndInit(); + this.DetailsTabPage.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem FileMenu; + private System.Windows.Forms.ToolStripMenuItem EditMenu; + private System.Windows.Forms.ToolStripMenuItem ViewMenu; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripSplitButton NewButton; + private System.Windows.Forms.ToolStripSplitButton OpenButton; + private System.Windows.Forms.ToolStripSplitButton SaveButton; + private System.Windows.Forms.StatusStrip MainToolbar; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.SplitContainer MainSplitContainer; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox SelTextureNameTextBox; + private System.Windows.Forms.TabControl TextureTabControl; + private System.Windows.Forms.TabPage TextureTabPage; + private System.Windows.Forms.Label SelTextureMipLabel; + private System.Windows.Forms.Label SelTextureDimensionsLabel; + private System.Windows.Forms.TrackBar SelTextureMipTrackBar; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.PictureBox SelTexturePictureBox; + private System.Windows.Forms.TabPage DetailsTabPage; + private WinForms.PropertyGridFix DetailsPropertyGrid; + private System.Windows.Forms.ListView TexturesListView; + private System.Windows.Forms.ColumnHeader TextureNameColumnHeader; + private System.Windows.Forms.ColumnHeader TextureSizeColumnHeader; + } +} \ No newline at end of file diff --git a/Forms/YtdForm.cs b/Forms/YtdForm.cs new file mode 100644 index 0000000..2f1f9c8 --- /dev/null +++ b/Forms/YtdForm.cs @@ -0,0 +1,196 @@ +using CodeWalker.GameFiles; +using CodeWalker.Utils; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class YtdForm : Form + { + private string fileName; + private YtdFile Ytd { get; set; } + private TextureDictionary TexDict { get; set; } + + public YtdForm() + { + InitializeComponent(); + } + + + public void LoadYtd(YtdFile ytd) + { + Ytd = ytd; + + fileName = ytd?.Name; + if (string.IsNullOrEmpty(fileName)) + { + fileName = ytd?.RpfFileEntry?.Name; + } + + LoadTexDict(ytd.TextureDict, fileName); + } + public void LoadTexDict(TextureDictionary texdict, string filename) + { + TexDict = texdict; + fileName = filename; + + TexturesListView.Items.Clear(); + SelTexturePictureBox.Image = null; + SelTextureNameTextBox.Text = string.Empty; + SelTextureDimensionsLabel.Text = "-"; + SelTextureMipLabel.Text = "0"; + SelTextureMipTrackBar.Value = 0; + SelTextureMipTrackBar.Maximum = 0; + + if (TexDict == null) + { + return; + } + + + if ((TexDict.Textures == null) || (TexDict.Textures.data_items == null)) return; + var texs = TexDict.Textures.data_items; + + for (int i = 0; i < texs.Length; i++) + { + var tex = texs[i]; + ListViewItem lvi = TexturesListView.Items.Add(tex.Name); + lvi.ToolTipText = tex.Name; + lvi.Tag = tex; + lvi.SubItems.Add(tex.Width.ToString() + " x " + tex.Height.ToString()); + } + + if (TexturesListView.Items.Count > 0) + { + TexturesListView.Items[0].Selected = true; + } + UpdateStatus(GetTexCountStr()); + + + UpdateFormTitle(); + } + + private string GetTexCountStr() + { + var texs = TexDict?.Textures?.data_items; + if (texs == null) return ""; + return texs.Length.ToString() + " texture" + ((texs.Length != 1) ? "s" : ""); + } + + + + private void ShowTextureMip(Texture tex, int mip, bool mipchange) + { + if (tex == null) + { + SelTexturePictureBox.Image = null; + SelTextureNameTextBox.Text = string.Empty; + SelTextureDimensionsLabel.Text = "-"; + SelTextureMipLabel.Text = "0"; + SelTextureMipTrackBar.Value = 0; + SelTextureMipTrackBar.Maximum = 0; + DetailsPropertyGrid.SelectedObject = null; + UpdateStatus(GetTexCountStr()); + return; + } + + + if (mipchange) + { + if (mip >= tex.Levels) mip = tex.Levels - 1; + } + else + { + SelTextureMipTrackBar.Maximum = tex.Levels - 1; + } + + SelTextureNameTextBox.Text = tex.Name; + DetailsPropertyGrid.SelectedObject = tex; + + + try + { + int cmip = Math.Min(Math.Max(mip, 0), tex.Levels - 1); + byte[] pixels = DDSIO.GetPixels(tex, cmip); + int w = tex.Width >> cmip; + int h = tex.Height >> cmip; + Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); + + if (pixels != null) + { + var BoundsRect = new System.Drawing.Rectangle(0, 0, w, h); + BitmapData bmpData = bmp.LockBits(BoundsRect, ImageLockMode.WriteOnly, bmp.PixelFormat); + IntPtr ptr = bmpData.Scan0; + int bytes = bmpData.Stride * bmp.Height; + Marshal.Copy(pixels, 0, ptr, bytes); + bmp.UnlockBits(bmpData); + } + + var dimstr = w.ToString() + " x " + h.ToString(); + + SelTexturePictureBox.Image = bmp; + SelTextureDimensionsLabel.Text = dimstr; + + var str1 = GetTexCountStr(); + var str2 = tex.Name + ", mip " + cmip.ToString() + ", " + dimstr; + if (!string.IsNullOrEmpty(str1)) + { + UpdateStatus(str1 + ". " + str2); + } + else + { + UpdateStatus(str2); + } + } + catch (Exception ex) + { + UpdateStatus("Error reading texture mip: " + ex.ToString()); + SelTexturePictureBox.Image = null; + } + + } + + + + private void UpdateFormTitle() + { + Text = fileName + " - Texture Dictionary - CodeWalker by dexyfex"; + } + + private void UpdateStatus(string text) + { + StatusLabel.Text = text; + } + + + private void TexturesListView_SelectedIndexChanged(object sender, EventArgs e) + { + Texture tex = null; + if (TexturesListView.SelectedItems.Count == 1) + { + tex = TexturesListView.SelectedItems[0].Tag as Texture; + } + ShowTextureMip(tex, 0, false); + } + + private void SelTextureMipTrackBar_Scroll(object sender, EventArgs e) + { + Texture tex = null; + if (TexturesListView.SelectedItems.Count == 1) + { + tex = TexturesListView.SelectedItems[0].Tag as Texture; + } + SelTextureMipLabel.Text = SelTextureMipTrackBar.Value.ToString(); + ShowTextureMip(tex, SelTextureMipTrackBar.Value, true); + } + } +} diff --git a/Forms/YtdForm.resx b/Forms/YtdForm.resx new file mode 100644 index 0000000..5539127 --- /dev/null +++ b/Forms/YtdForm.resx @@ -0,0 +1,447 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 132, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADESURBVDhPzZI7DgIhGIQ5grUnsPQMnMgLWMo1bDyJiYUV + h7CxEo1Aiw7+E9ldWF+Nk0w2wMy3/z5UqRDCwjk3iTEmGmvsS6Ste2gtJYvrdjklJK9xLtGhcAeEdqtZ + Ouw3uUgA1tgXSH0SGdsyfD0dcwHXAmqRk0pXCNMsN+y893OpPYVDjFw8d9JaD2yMqUNYgjkBCmd36bgJ + 6b+DMUAJkXr9K9QANM6QkfpD/f/gYwCESfgnfgWg/gcw5peAdyzxX6TUDfMCML1omZa9AAAAAElFTkSu + QmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEcSURBVDhPlZKxqsIwFIb7Bvc+idxHuPQVXFpQcOhe8Amc + OqqzCBdU6HQfQIfunVwKoi7FQQeF9GrajufmhDYkTaMY+EjPyf//TZtY9aCUfhVFQRggQbBfSV4PFJ8v + GekMf8HqzqE3jXhIhRwsqKyWxYpJ3bzcMpBD4jgG27Y1RACaZ+sEPvoLbmqCa/f7AzLyJ2gGcDO+bXe6 + ajugDypMiBJQluU3f2DiZ+YmT3eANWIyIyKgFsv/AOs2k4wSgIXneRBFEaRpyhew10ZbwNb3fU1oYrPe + qAF5no/CMNSEJsbjiRqAty9JEk1ownEcNaA6BeK6riY2cdgf+SwC2Gf8BEGgCU2slis+iwB2mQZ4Ak3h + K0QAIeQTi/cp4B9tCZE2c6oRhQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABWSURBVDhPY6AK+Pbt238S8PsvX74YQLVCAEjCyckJjj+8 + /wjHyGIguq2tDdMQUgwAYZghUO2kGwDCID1Q7fgNQMbIamhrADF41IBBaQA5GKqdEsDAAADtDPd9n5qK + lQAAAABJRU5ErkJggg== + + + + 237, 17 + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/YvrForm.Designer.cs b/Forms/YvrForm.Designer.cs new file mode 100644 index 0000000..be8f66a --- /dev/null +++ b/Forms/YvrForm.Designer.cs @@ -0,0 +1,82 @@ +namespace CodeWalker.Forms +{ + partial class YvrForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(YvrForm)); + this.CloseButton = new System.Windows.Forms.Button(); + this.MainTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.SuspendLayout(); + // + // CloseButton + // + this.CloseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.CloseButton.Location = new System.Drawing.Point(597, 389); + this.CloseButton.Name = "CloseButton"; + this.CloseButton.Size = new System.Drawing.Size(75, 23); + this.CloseButton.TabIndex = 5; + this.CloseButton.Text = "Close"; + this.CloseButton.UseVisualStyleBackColor = true; + this.CloseButton.Click += new System.EventHandler(this.CloseButton_Click); + // + // MainTextBox + // + this.MainTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTextBox.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.MainTextBox.HideSelection = false; + this.MainTextBox.Location = new System.Drawing.Point(12, 12); + this.MainTextBox.Multiline = true; + this.MainTextBox.Name = "MainTextBox"; + this.MainTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.MainTextBox.Size = new System.Drawing.Size(660, 371); + this.MainTextBox.TabIndex = 4; + this.MainTextBox.WordWrap = false; + // + // YvrForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(684, 421); + this.Controls.Add(this.CloseButton); + this.Controls.Add(this.MainTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "YvrForm"; + this.Text = "Vehicle Records Viewer - CodeWalker by dexyfex"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button CloseButton; + private WinForms.TextBoxFix MainTextBox; + } +} \ No newline at end of file diff --git a/Forms/YvrForm.cs b/Forms/YvrForm.cs new file mode 100644 index 0000000..a440696 --- /dev/null +++ b/Forms/YvrForm.cs @@ -0,0 +1,117 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class YvrForm : Form + { + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + + + + public YvrForm() + { + InitializeComponent(); + } + + + + private void UpdateFormTitle() + { + Text = fileName + " - Vehicle Records Viewer - CodeWalker by dexyfex"; + } + + + + public void LoadYvr(YvrFile yvr) + { + fileName = yvr?.Name; + if (string.IsNullOrEmpty(fileName)) + { + fileName = yvr?.RpfFileEntry?.Name; + } + + UpdateFormTitle(); + + + StringBuilder sb = new StringBuilder(); + + if ((yvr != null) && (yvr.Records != null) && (yvr.Records.Entries != null) && (yvr.Records.Entries.data_items != null)) + { + sb.AppendLine("PositionX, PositionY, PositionZ, Time, VelocityX, VelocityY, VelocityZ, RightX, RightY, RightZ, TopX, TopY, TopZ, SteeringAngle, GasPedalPower, BrakePedalPower, HandbrakeUsed"); + foreach (var entry in yvr.Records.Entries.data_items) + { + sb.Append(FloatUtil.ToString(entry.PositionX)); + sb.Append(", "); + sb.Append(FloatUtil.ToString(entry.PositionY)); + sb.Append(", "); + sb.Append(FloatUtil.ToString(entry.PositionZ)); + sb.Append(", "); + sb.Append(entry.Time.ToString()); + sb.Append(", "); + sb.Append(entry.VelocityX.ToString()); + sb.Append(", "); + sb.Append(entry.VelocityY.ToString()); + sb.Append(", "); + sb.Append(entry.VelocityZ.ToString()); + sb.Append(", "); + sb.Append(entry.RightX.ToString()); + sb.Append(", "); + sb.Append(entry.RightY.ToString()); + sb.Append(", "); + sb.Append(entry.RightZ.ToString()); + sb.Append(", "); + sb.Append(entry.TopX.ToString()); + sb.Append(", "); + sb.Append(entry.TopY.ToString()); + sb.Append(", "); + sb.Append(entry.TopZ.ToString()); + sb.Append(", "); + sb.Append(entry.SteeringAngle.ToString()); + sb.Append(", "); + sb.Append(entry.GasPedalPower.ToString()); + sb.Append(", "); + sb.Append(entry.BrakePedalPower.ToString()); + sb.Append(", "); + sb.Append(entry.HandbrakeUsed.ToString()); + sb.AppendLine(); + } + } + else + { + sb.AppendLine("Unable to load Vehicle Records."); + } + + MainTextBox.Text = sb.ToString(); + + } + + + + + private void CloseButton_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/Forms/YvrForm.resx b/Forms/YvrForm.resx new file mode 100644 index 0000000..1431f6b --- /dev/null +++ b/Forms/YvrForm.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Forms/YwrForm.Designer.cs b/Forms/YwrForm.Designer.cs new file mode 100644 index 0000000..09245a2 --- /dev/null +++ b/Forms/YwrForm.Designer.cs @@ -0,0 +1,82 @@ +namespace CodeWalker.Forms +{ + partial class YwrForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(YwrForm)); + this.CloseButton = new System.Windows.Forms.Button(); + this.MainTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.SuspendLayout(); + // + // CloseButton + // + this.CloseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.CloseButton.Location = new System.Drawing.Point(597, 389); + this.CloseButton.Name = "CloseButton"; + this.CloseButton.Size = new System.Drawing.Size(75, 23); + this.CloseButton.TabIndex = 3; + this.CloseButton.Text = "Close"; + this.CloseButton.UseVisualStyleBackColor = true; + this.CloseButton.Click += new System.EventHandler(this.CloseButton_Click); + // + // MainTextBox + // + this.MainTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTextBox.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.MainTextBox.HideSelection = false; + this.MainTextBox.Location = new System.Drawing.Point(12, 12); + this.MainTextBox.Multiline = true; + this.MainTextBox.Name = "MainTextBox"; + this.MainTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.MainTextBox.Size = new System.Drawing.Size(660, 371); + this.MainTextBox.TabIndex = 2; + this.MainTextBox.WordWrap = false; + // + // YwrForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(684, 421); + this.Controls.Add(this.CloseButton); + this.Controls.Add(this.MainTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "YwrForm"; + this.Text = "Waypoint Records Viewer - CodeWalker by dexyfex"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button CloseButton; + private WinForms.TextBoxFix MainTextBox; + } +} \ No newline at end of file diff --git a/Forms/YwrForm.cs b/Forms/YwrForm.cs new file mode 100644 index 0000000..ee9dd68 --- /dev/null +++ b/Forms/YwrForm.cs @@ -0,0 +1,94 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Forms +{ + public partial class YwrForm : Form + { + + + private string fileName; + public string FileName + { + get { return fileName; } + set + { + fileName = value; + UpdateFormTitle(); + } + } + public string FilePath { get; set; } + + + + + public YwrForm() + { + InitializeComponent(); + } + + + + private void UpdateFormTitle() + { + Text = fileName + " - Waypoint Records Viewer - CodeWalker by dexyfex"; + } + + + public void LoadYwr(YwrFile ywr) + { + fileName = ywr?.Name; + if (string.IsNullOrEmpty(fileName)) + { + fileName = ywr?.RpfFileEntry?.Name; + } + + UpdateFormTitle(); + + + StringBuilder sb = new StringBuilder(); + + if ((ywr != null) && (ywr.Waypoints != null) && (ywr.Waypoints.Entries != null)) + { + sb.AppendLine("PositionX, PositionY, PositionZ, Unk0, Unk1, Unk2, Unk3"); + foreach (var entry in ywr.Waypoints.Entries) + { + sb.Append(FloatUtil.ToString(entry.PositionX)); + sb.Append(", "); + sb.Append(FloatUtil.ToString(entry.PositionY)); + sb.Append(", "); + sb.Append(FloatUtil.ToString(entry.PositionZ)); + sb.Append(", "); + sb.Append(entry.Unk0.ToString()); + sb.Append(", "); + sb.Append(entry.Unk1.ToString()); + sb.Append(", "); + sb.Append(entry.Unk2.ToString()); + sb.Append(", "); + sb.Append(entry.Unk3.ToString()); + sb.AppendLine(); + } + } + else + { + sb.AppendLine("Unable to load Waypoint Records."); + } + + MainTextBox.Text = sb.ToString(); + } + + + private void CloseButton_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/Forms/YwrForm.resx b/Forms/YwrForm.resx new file mode 100644 index 0000000..1431f6b --- /dev/null +++ b/Forms/YwrForm.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/GameFiles/FileTypes/AwcFile.cs b/GameFiles/FileTypes/AwcFile.cs new file mode 100644 index 0000000..d0f509f --- /dev/null +++ b/GameFiles/FileTypes/AwcFile.cs @@ -0,0 +1,702 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TC = System.ComponentModel.TypeConverterAttribute; +using EXP = System.ComponentModel.ExpandableObjectConverter; + +namespace CodeWalker.GameFiles +{ + [TC(typeof(EXP))]public class AwcFile : PackedFile + { + public string Name { get; set; } + public RpfFileEntry FileEntry { get; set; } + public byte[] Data { get; set; } + + public string ErrorMessage { get; set; } + + public uint Magic { get; set; } + public ushort Version { get; set; } + public ushort Flags { get; set; } + public int StreamCount { get; set; } + public int InfoOffset { get; set; } + + public bool MultiChannel { get; set; } + public byte[] MultiChannelData { get; set; } + + public AwcStreamInfo[] StreamInfos { get; set; } + public uint[] AudioIds { get; set; } + public AwcAudio[] Audios { get; set; } + + + public void Load(byte[] data, RpfFileEntry entry) + { + + //adapted from libertyV code + + + //MemoryStream ms = new MemoryStream(data); + Name = entry.Name; + FileEntry = entry; + Data = data; + + if ((data == null) || (data.Length < 8)) + { + ErrorMessage = "Data null or too short!"; + return; //nothing to do, not enough data... + } + + Magic = BitConverter.ToUInt32(data, 0); + + Endianess endianess = Endianess.LittleEndian; + switch (Magic) + { + default: + ErrorMessage = "Unexpected Magic 0x" + Magic.ToString("X"); + return; + case 0x54414441: + endianess = Endianess.LittleEndian; + break; + case 0x41444154: + endianess = Endianess.BigEndian; + break; + } + + using (MemoryStream ms = new MemoryStream(data)) + { + DataReader r = new DataReader(ms, endianess); + + Magic = r.ReadUInt32(); + Version = r.ReadUInt16(); + Flags = r.ReadUInt16(); + StreamCount = r.ReadInt32(); + InfoOffset = r.ReadInt32(); + + + //notes from libertyV: + // first bit - means that there are unknown word for each stream after this header + // second bit - I think that it means that not all the tags are in the start of the file, but all the tags of a stream are near the data tag + // third bit - Multi channel audio + + if ((Flags >> 8) != 0xFF) + { + ErrorMessage = "Flags 0 not supported!"; + return; + } + if ((Flags & 0xF8) != 0) + { + //ErrorMessage = "Flags 1 not supported!"; + //return; + } + + MultiChannel = ((Flags & 4) == 4); + + + var flag0 = ((Flags & 1) == 1); + var infoStart = 16 + (flag0 ? (StreamCount * 2) : 0); + + ms.Position = infoStart; + + List infos = new List(); + Dictionary infoDict = new Dictionary(); + List audioIds = new List(); + List audios = new List(); + + for (int i = 0; i < StreamCount; i++) + { + var info = new AwcStreamInfo(r); + infos.Add(info); + infoDict[info.Id] = info; + } + for (int i = 0; i < StreamCount; i++) + { + var info = infos[i]; + for (int j = 0; j < info.TagCount; j++) + { + var chunk = new AwcChunkInfo(r); + info.Chunks[chunk.Tag] = chunk; + } + } + + StreamInfos = infos.ToArray(); + + + + byte hformat = 0xFA;// 250 0x6061D4FA & 0xFF; //JenkHash.GenHash("format"); + byte hdata = 0x55;// 85 0x5EB5E655 & 0xFF; //JenkHash.GenHash("data"); + byte hycd = 0x5C;// 92 YCD resource chunk... lip sync anims? + byte hunk = 0x36;// 54 unk chunk? small number of bytes (2+) + + + + if (MultiChannel) + { + AwcStreamInfo stream0 = null; + if (!infoDict.TryGetValue(0, out stream0)) + { + ErrorMessage = "Couldn't find MultiChannel stream0"; + return; + } + + AwcChunkInfo chunk72 = null; + if (!stream0.Chunks.TryGetValue(72, out chunk72)) + { + ErrorMessage = "Couldn't find MultiChannel chunk72"; + return; + } + + ms.Position = chunk72.Offset; + + AwcChannelChunkInfo chanInfo = new AwcChannelChunkInfo(r); + if (chanInfo.ChannelCount != StreamCount - 1) + { + ErrorMessage = "Channel Count did not match Stream Count"; + return; + } + + List chunkItems = new List(); + for (int i = 0; i < chanInfo.ChannelCount; i++) + { + var itemInfo = new AwcChannelChunkItemInfo(r); + chunkItems.Add(itemInfo); + audioIds.Add(infos[i + 1].Id); + } + + //AudioStreams.Add(new MultiChannelAudio(new ChunkStream(this.Stream, streamsChunks[0][Tag("data")]), channelsInfoHeader, streamsInfo, header.BigEndian)); + + AwcChunkInfo cdata = null; + if (!stream0.Chunks.TryGetValue(hdata, out cdata)) + { + ErrorMessage = "Couldn't find Stream 0 data chunk"; + return; + } + + ms.Position = cdata.Offset; + var lastPos = cdata.Offset + cdata.Size; + //int chunkSize = 0x800; + uint bigChunkSize = chanInfo.ChunkSize; + var chanCount = chanInfo.ChannelCount; + + MultiChannelData = r.ReadBytes(cdata.Size); + ms.Position = cdata.Offset; + + //var d = data;//temporary + + ////this doesn't seem to work :( + //while (ms.Position < lastPos) + //{ + // uint totalChunks = 0; + // var startPos = ms.Position; + // var curPos = startPos; + // //byte[] chunkdata = r.ReadBytes(chunkSize); + // //ms.Position = startPos; + // AwcChannelChunkHeader[] chanHeaders = new AwcChannelChunkHeader[chanCount]; + // for (int i = 0; i < chanCount; i++) + // { + // var chanHeader = new AwcChannelChunkHeader(r); + // chanHeaders[i] = chanHeader; + // totalChunks += chanHeader.ChunkCount; + // } + // int headerSize = (int)(totalChunks * 4 + chanInfo.ChannelCount * AwcChannelChunkHeader.Size); + // headerSize += (((-headerSize) % chunkSize) + chunkSize) % chunkSize; //todo: simplify this! + // curPos += headerSize; + // AwcChannelChunk[] chanChunks = new AwcChannelChunk[chanCount]; + // for (int i = 0; i < chanCount; i++) + // { + // var chanChunk = new AwcChannelChunk(r, chanHeaders[i], chunkItems[i]); + // chanChunks[i] = chanChunk; + // curPos += chanChunk.TotalDataSize; + // } + // if (curPos - startPos > chanInfo.ChunkSize) + // { + // ErrorMessage = "Chunk was bigger than the chunk size"; + // break; + // } + // if ((totalChunks == 0) || ((startPos + chanInfo.ChunkSize) > lastPos)) + // { + // ErrorMessage = "Unable to read chunk"; + // break; + // } + // var newPos = startPos + bigChunkSize; + // if (newPos >= lastPos) break; + // ms.Position = newPos; + //} + + + + } + else + { + + for (int i = 0; i < StreamCount; i++) + { + var info = infos[i]; + + AwcChunkInfo cformat = null; + if (!info.Chunks.TryGetValue(hformat, out cformat)) + { + ErrorMessage = "Couldn't find Stream " + i.ToString() + " format chunk"; + continue; + } + + AwcChunkInfo cdata = null; + if (!info.Chunks.TryGetValue(hdata, out cdata)) + { + ErrorMessage = "Couldn't find Stream " + i.ToString() + " data chunk"; + continue; + } + + AwcChunkInfo cycd = null; + AwcAudioAnimClipDict oycd = null; + if (info.Chunks.TryGetValue(hycd, out cycd)) + { + ms.Position = cycd.Offset; + oycd = new AwcAudioAnimClipDict(r, cycd); + } + + AwcChunkInfo cunk = null; + AwcAudioUnk ounk = null; + if (info.Chunks.TryGetValue(hunk, out cunk)) + { + ms.Position = cunk.Offset; + ounk = new AwcAudioUnk(r, cunk); + } + + + ms.Position = cformat.Offset; + AwcFormatChunk formatChunk = new AwcFormatChunk(r); + + ms.Position = cdata.Offset; + AwcAudio audio = new AwcAudio(r, info, formatChunk, cdata); + + audio.ClipDict = oycd; + audio.UnkData = ounk; + + audios.Add(audio); + audioIds.Add(info.Id); + } + } + + + Audios = audios.ToArray(); + AudioIds = audioIds.ToArray(); + + + } + + } + + } + + + [TC(typeof(EXP))] public class AwcStreamInfo + { + public uint RawVal { get; set; } + public uint TagCount { get; set; } + public uint Id { get; set; } + + public Dictionary Chunks { get; set; } = new Dictionary(); + + public AwcStreamInfo(DataReader r) + { + RawVal = r.ReadUInt32(); + TagCount = (RawVal >> 29); + Id = (RawVal & 0x1FFFFFFF); + } + + public override string ToString() + { + return Id.ToString("X") + ": " + TagCount.ToString() + " tags"; + } + } + + [TC(typeof(EXP))] public class AwcChunkInfo + { + public ulong RawVal { get; set; } + public byte Tag { get; set; } + public int Size { get; set; } + public int Offset { get; set; } + + public AwcChunkInfo(DataReader r) + { + RawVal = r.ReadUInt64(); + Tag = (byte)(RawVal >> 56); + Size = (int)((RawVal >> 28) & 0x0FFFFFFF); + Offset = (int)(RawVal & 0x0FFFFFFF); + } + + public override string ToString() + { + return Tag.ToString() + ": " + Size.ToString() + ", " + Offset.ToString(); + } + } + + [TC(typeof(EXP))] public class AwcChannelChunkInfo + { + public uint Unk0 { get; set; } + public uint ChunkSize { get; set; } + public uint ChannelCount { get; set; } + + public AwcChannelChunkInfo(DataReader r) + { + Unk0 = r.ReadUInt32(); + ChunkSize = r.ReadUInt32(); + ChannelCount = r.ReadUInt32(); + } + + public override string ToString() + { + return Unk0.ToString() + ": " + ChunkSize.ToString() + ", " + ChannelCount.ToString() + " channels"; + } + } + + [TC(typeof(EXP))] public class AwcChannelChunkItemInfo + { + public uint Id { get; set; } + public uint Samples { get; set; } + public ushort Unk0 { get; set; } + public ushort SamplesPerSecond { get; set; } + public byte Unk1 { get; set; } + public byte RoundSize { get; set; } + public ushort Unk2 { get; set; } + + public AwcChannelChunkItemInfo(DataReader r) + { + Id = r.ReadUInt32(); + Samples = r.ReadUInt32(); + Unk0 = r.ReadUInt16(); + SamplesPerSecond = r.ReadUInt16(); + Unk1 = r.ReadByte(); + RoundSize = r.ReadByte(); + Unk2 = r.ReadUInt16(); + } + + public override string ToString() + { + return Id.ToString() + ": " + Samples.ToString() + " samples, " + SamplesPerSecond.ToString() + " samples/sec, size: " + RoundSize.ToString(); + } + } + + [TC(typeof(EXP))] public class AwcFormatChunk + { + public uint Samples { get; set; } + public int UnkMinusOne { get; set; } + public ushort SamplesPerSecond { get; set; } + public ushort Unk1 { get; set; } + public ushort Unk2 { get; set; } + public ushort Unk3 { get; set; } + public ushort Unk4 { get; set; } + public byte Unk5 { get; set; } + public byte Unk6 { get; set; } + + public AwcFormatChunk(DataReader r) + { + Samples = r.ReadUInt32(); + UnkMinusOne = r.ReadInt32(); + SamplesPerSecond = r.ReadUInt16(); + Unk1 = r.ReadUInt16(); + Unk2 = r.ReadUInt16(); + Unk3 = r.ReadUInt16(); + Unk4 = r.ReadUInt16(); + Unk5 = r.ReadByte(); + Unk6 = r.ReadByte(); + + //Apparently sometimes this struct is longer? TODO: fix?? + //r.ReadUInt16(); + //r.ReadUInt16(); + } + + + public override string ToString() + { + return Unk1.ToString() + ", " + Unk6.ToString() + ": " + Samples.ToString() + " samples, " + SamplesPerSecond.ToString() + " samples/sec"; + } + } + + [TC(typeof(EXP))] public class AwcAudio + { + public AwcStreamInfo StreamInfo { get; set; } + public AwcFormatChunk Format { get; set; } + public AwcChunkInfo DataInfo { get; set; } + public byte[] Data { get; set; } + + public AwcAudioAnimClipDict ClipDict { get; set; } + public AwcAudioUnk UnkData { get; set; } + + + public short Channels = 1; + public short BitsPerSample = 4;//16; + public int SamplesPerSecond + { + get + { + return Format?.SamplesPerSecond ?? 0; + } + } + public int SampleCount + { + get + { + return (int)(Format?.Samples ?? 0); + } + } + + + public string Name + { + get + { + return "0x" + StreamInfo?.Id.ToString("X").PadLeft(8, '0') ?? "0"; + } + } + public string Type + { + get + { + if (Format == null) return "Unknown"; + + string fmt = "ADPCM"; + switch (Format.Unk6) + { + case 4: + break; + default: + break; + } + + var hz = Format?.SamplesPerSecond ?? 0; + + return fmt + ((hz > 0) ? (", " + hz.ToString() + " Hz") : ""); + } + } + public string LengthStr + { + get + { + if (Format == null) return "0:00"; + float sec = (float)Format.Samples / Format.SamplesPerSecond; + TimeSpan ts = TimeSpan.FromSeconds(sec); + return ts.ToString("m\\:ss"); + } + } + + + public AwcAudio(DataReader r, AwcStreamInfo s, AwcFormatChunk f, AwcChunkInfo d) + { + StreamInfo = s; + Format = f; + DataInfo = d; + + Data = r.ReadBytes(d.Size); + } + + public override string ToString() + { + var hash = (StreamInfo?.Id.ToString("X") ?? "0").PadLeft(8, '0'); + return "0x" + hash + ": " + Format?.ToString() ?? "AwcAudio"; + } + + + + public Stream GetWavStream() + { + MemoryStream ms = new MemoryStream(); + BinaryWriter w = new BinaryWriter(ms); + + + //see http://icculus.org/SDL_sound/downloads/external_documentation/wavecomp.htm + //see https://github.com/naudio/NAudio/blob/master/NAudio/Wave/WaveFormats/AdpcmWaveFormat.cs + //see https://msdn.microsoft.com/en-us/library/windows/desktop/ff538799(v=vs.85).aspx + + + int sampleCount = SampleCount; + int samplesPerSec = SamplesPerSecond; + //short sampleSize = (short)((BitsPerSample / 8) * Channels);//2 + //int avgBytesPerSec = sampleSize * samplesPerSec; + short blockAlign = 512; + + short samplesPerBlock = (short)((((blockAlign - (7 * Channels)) * 8) / (BitsPerSample * Channels)) + 2); + int avgBytesPerSec = ((samplesPerSec / samplesPerBlock) * blockAlign); + + w.Write("RIFF".ToCharArray()); + w.Write(0); //file size written later... + w.Write("WAVE".ToCharArray()); + w.Write("fmt ".ToCharArray()); + w.Write(50); //(PCM:16) //header size + w.Write((short)2); //pcm format tag 1=PCM, 2=ADPCM + w.Write(Channels); + w.Write(samplesPerSec); + w.Write(avgBytesPerSec); + w.Write(blockAlign);// sampleSize); + w.Write(BitsPerSample); + w.Write((short)32);//extra byte count for WAVEFORMATEX + + w.Write(samplesPerBlock); + w.Write((short)7);//num coefficients + w.Write((short)256); //coeff 0 + w.Write((short)0); + w.Write((short)512); //coeff 1 + w.Write((short)-256); + w.Write((short)0); //coeff 2 + w.Write((short)0); + w.Write((short)192); //coeff 3 + w.Write((short)64); + w.Write((short)240); //coeff 4 + w.Write((short)0); + w.Write((short)460); //coeff 5 + w.Write((short)-208); + w.Write((short)392); //coeff 6 + w.Write((short)-232); + + w.Write("data".ToCharArray()); + w.Write(0); //data size written later... + + if (sampleCount != 0) + { + + //var sc = sampleCount * sampleSize; + var datalen = Data.Length; + w.Write(Data); + } + else + { + w.Write(Data); + } + + ms.Position = 4; + w.Write((int)ms.Length - 8); + + ms.Position = 74;// 40; + w.Write((int)ms.Length - 78);// 44); + + w.Flush(); + + ms.Position = 0; + return ms; + } + + + + } + + [TC(typeof(EXP))] public class AwcAudioAnimClipDict + { + public byte[] Data { get; set; } + public ClipDictionary ClipDict { get; set; } + + public AwcAudioAnimClipDict(DataReader r, AwcChunkInfo info) + { + Data = r.ReadBytes(info.Size); + + if ((Data == null) || (Data.Length < 16)) return; + + var data = Data; + + RpfResourceFileEntry resentry = new RpfResourceFileEntry(); + uint rsc7 = BitConverter.ToUInt32(data, 0); + int version = BitConverter.ToInt32(data, 4); + resentry.SystemFlags = BitConverter.ToUInt32(data, 8); + resentry.GraphicsFlags = BitConverter.ToUInt32(data, 12); + + if (rsc7 != 0x37435352) + { } //testing.. + if (version != 46) //46 is Clip Dictionary... + { } + + int newlen = data.Length - 16; //trim the header from the data passed to the next step. + int arrlen = Math.Max(newlen, resentry.SystemSize + resentry.GraphicsSize);//expand it as necessary for the reader. + byte[] newdata = new byte[arrlen]; + Buffer.BlockCopy(data, 16, newdata, 0, newlen); + data = newdata; + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + ClipDict = rd.ReadBlock(); + + + } + + public override string ToString() + { + return (ClipDict?.ClipsMapEntries ?? 0).ToString() + " entries"; + } + } + + [TC(typeof(EXP))] public class AwcAudioUnk + { + public byte[] Data { get; set; } + + public AwcAudioUnk(DataReader r, AwcChunkInfo info) + { + Data = r.ReadBytes(info.Size); + } + + public override string ToString() + { + if (Data == null) return ""; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < Data.Length; i++) + { + if (sb.Length > 0) sb.Append(' '); + sb.Append(Data[i].ToString()); + } + return sb.ToString(); + } + } + + + [TC(typeof(EXP))] public class AwcChannelChunkHeader + { + public static uint Size = 16; //24 for ps3... + + public uint StartChunk { get; set; } + public uint ChunkCount { get; set; } + public uint SamplesToSkip { get; set; } //mostly 0 + public uint SamplesPerChunk { get; set; } + public uint DataSize { get; set; } + + public AwcChannelChunkHeader(DataReader r) + { + StartChunk = r.ReadUInt32(); + ChunkCount = r.ReadUInt32(); + SamplesToSkip = r.ReadUInt32(); + SamplesPerChunk = r.ReadUInt32(); + DataSize = ChunkCount * 0x800; + + //for ps3, two extra ints: + //uint unk0 = r.ReadUint32(); + //DataSize = r.ReadUint32(); + + + } + + } + + [TC(typeof(EXP))] public class AwcChannelChunk + { + public AwcChannelChunkHeader Header { get; set; } + public AwcChannelChunkItemInfo Info { get; set; } + public byte[] Data { get; set; } + + public uint TotalDataSize { get; set; } + + public AwcChannelChunk(DataReader r, AwcChannelChunkHeader h, AwcChannelChunkItemInfo i) + { + Header = h; + Info = i; + + TotalDataSize = h.DataSize; + + var rs = i?.RoundSize ?? 0; + int ds = (int)h.DataSize; + if (rs != 0) + { + TotalDataSize = (uint)(TotalDataSize + (((-ds) % rs) + rs) % rs); + } + } + + } + +} diff --git a/GameFiles/FileTypes/CacheDatFile.cs b/GameFiles/FileTypes/CacheDatFile.cs new file mode 100644 index 0000000..ebc6861 --- /dev/null +++ b/GameFiles/FileTypes/CacheDatFile.cs @@ -0,0 +1,491 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class CacheDatFile : PackedFile + { + public RpfFileEntry FileEntry { get; set; } + + public CacheFileDate[] FileDates { get; set; } + + public Dictionary MapNodeDict { get; set; } + public MapDataStoreNode[] RootMapNodes { get; set; } + //public Dictionary InteriorProxyDict { get; set; } + public Dictionary BoundsStoreDict { get; set; } + + public MapDataStoreNode[] AllMapNodes { get; set; } + public CInteriorProxy[] AllCInteriorProxies { get; set; } + public BoundsStoreItem[] AllBoundsStoreItems { get; set; } + + public void Load(byte[] data, RpfFileEntry entry) + { + FileEntry = entry; + + MemoryStream ms = new MemoryStream(data); + BinaryReader br = new BinaryReader(ms); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; (i < 100) && (i < data.Length); i++) + { + //read version string. + byte b = data[i]; + if (b == 0) break; + sb.Append((char)b); + } + string versionstr = sb.ToString(); + sb.Clear(); + int lastn = 0; + int lspos = 0; + uint structcount = 0; + uint modlen; + bool indates = false; + List lines = new List(); + var dates = new List(); + var allMapNodes = new List(); + var allCInteriorProxies = new List(); + var allBoundsStoreItems = new List(); + for (int i = 100; i < data.Length; i++) + { + byte b = data[i]; + if (b == 0) + break; + if (b == 0xA) + { + lastn = i; + string line = sb.ToString(); + lines.Add(line); + switch (line) + { + case "": + indates = true; + break; + case "": + indates = false; + break; + case "": + break; + case "": + break; + case "fwMapDataStore": + ms.Position = i + 1; + modlen = br.ReadUInt32(); + structcount = modlen / 64; + lspos = i + (int)modlen + 5; + while (ms.Position(); + var rootMapNodes = new List(); + foreach (var mapnode in AllMapNodes) + { + MapNodeDict[mapnode.Name] = mapnode; + if (mapnode.ParentName == 0) + { + rootMapNodes.Add(mapnode); + } + if (mapnode.UnkExtra != null) + { }//notsure what to do with this + } + foreach (var mapnode in AllMapNodes) + { + MapDataStoreNode pnode; + if (MapNodeDict.TryGetValue(mapnode.ParentName, out pnode)) + { + pnode.AddChildToList(mapnode); + } + else if ((mapnode.ParentName != 0)) + { } + } + foreach (var mapnode in AllMapNodes) + { + mapnode.ChildrenListToArray(); + } + RootMapNodes = rootMapNodes.ToArray(); + + + + BoundsStoreDict = new Dictionary(); + foreach (BoundsStoreItem item in AllBoundsStoreItems) + { + BoundsStoreItem mbsi = null; + if (BoundsStoreDict.TryGetValue(item.Name, out mbsi)) + { } + BoundsStoreDict[item.Name] = item; + } + + //InteriorProxyDict = new Dictionary(); + foreach (CInteriorProxy prx in AllCInteriorProxies) + { + //CInteriorProxy mprx = null; + //if (InteriorProxyDict.TryGetValue(prx.Name, out mprx)) + //{ } + //InteriorProxyDict[prx.Name] = prx;//can't do this! multiples with same name different pos + + + MapDataStoreNode mnode = null; + if (MapNodeDict.TryGetValue(prx.Parent, out mnode)) + { + mnode.AddInteriorToList(prx); + } + else + { } + } + foreach (var mapnode in AllMapNodes) + { + mapnode.InteriorProxyListToArray(); + } + + + br.Dispose(); + ms.Dispose(); + + } + + public override string ToString() + { + if (FileEntry != null) + { + return FileEntry.ToString(); + } + return base.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class CacheFileDate + { + public MetaHash FileName { get; set; } + public DateTime TimeStamp { get; set; } + public uint FileID { get; set; } + + public CacheFileDate(string line) + { + string[] parts = line.Split(' '); + if (parts.Length == 3) + { + FileName = new MetaHash(uint.Parse(parts[0])); + TimeStamp = DateTime.FromFileTimeUtc(long.Parse(parts[1])); + FileID = uint.Parse(parts[2]); + } + else + { } //testing + } + + public override string ToString() + { + return FileName.ToString() + ", " + TimeStamp.ToString() + ", " + FileID.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundsStoreItem + { + public MetaHash Name { get; set; } + public Vector3 Min { get; set; } + public Vector3 Max { get; set; } + public uint Layer { get; set; } + + public BoundsStoreItem(Bounds b) + { + Name = 0; + Min = b.BoundingBoxMin; + Max = b.BoundingBoxMax; + Layer = 0; + } + public BoundsStoreItem(BinaryReader br) + { + Name = new MetaHash(br.ReadUInt32()); + Min = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Max = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Layer = br.ReadUInt32(); + } + + public override string ToString() + { + return Name.ToString() + ", " + + Min.ToString() + ", " + + Max.ToString() + ", " + + Layer.ToString(); + } + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class CInteriorProxy + { + public uint Unk01 { get; set; } + public uint Unk02 { get; set; } + public uint Unk03 { get; set; } + public MetaHash Name { get; set; } + public MetaHash Parent { get; set; } + public Vector3 Position { get; set; } + public Quaternion Orientation { get; set; } + public Vector3 BBMin { get; set; } + public Vector3 BBMax { get; set; } + public float Unk11 { get; set; } + public uint Unk12 { get; set; } + public float Unk13 { get; set; } + public uint Unk14 { get; set; } + public float Unk15 { get; set; } + public uint Unk16 { get; set; } + public uint Unk17 { get; set; } + public uint Unk18 { get; set; } + + public CInteriorProxy(BinaryReader br) + { + Unk01 = br.ReadUInt32(); + Unk02 = br.ReadUInt32(); + Unk03 = br.ReadUInt32(); + Name = new MetaHash(br.ReadUInt32()); + Parent = new MetaHash(br.ReadUInt32()); + Position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Orientation = new Quaternion(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + BBMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + BBMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Unk11 = br.ReadSingle(); + Unk12 = br.ReadUInt32(); + Unk13 = br.ReadSingle(); + Unk14 = br.ReadUInt32(); + Unk15 = br.ReadSingle(); + Unk16 = br.ReadUInt32(); + Unk17 = br.ReadUInt32(); + Unk18 = br.ReadUInt32(); + } + + public override string ToString() + { + return Unk01.ToString() + ", " + + Unk02.ToString() + ", " + + Unk03.ToString() + ", " + + Name.ToString() + ", " + + Parent.ToString() + ", " + + Position.ToString() + ", " + + Orientation.ToString() + ", " + + BBMin.ToString() + ", " + + BBMax.ToString() + ", " + + Unk11.ToString() + ", " + + Unk12.ToString() + ", " + + Unk13.ToString() + ", " + + Unk14.ToString() + ", " + + Unk15.ToString() + ", " + + Unk16.ToString() + ", " + + Unk17.ToString() + ", " + + Unk18.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class MapDataStoreNode + { + public MetaHash Name { get; set; } + public MetaHash ParentName { get; set; } + public uint ContentFlags { get; set; } + public Vector3 streamingExtentsMin { get; set; } + public Vector3 streamingExtentsMax { get; set; } + public Vector3 entitiesExtentsMin { get; set; } + public Vector3 entitiesExtentsMax { get; set; } + public byte Unk02 { get; set; } + public byte Unk03 { get; set; } + public byte Unk04 { get; set; } + public byte Unk05 { get; set; } + + public MapDataStoreNodeExtra UnkExtra { get; set; } + + public MapDataStoreNode[] Children { get; set; } + private List ChildrenList; //used when building the array + + public CInteriorProxy[] InteriorProxies { get; set; } + private List InteriorProxyList; + + public MapDataStoreNode(YmapFile ymap) + { + Name = ymap._CMapData.name; + ParentName = ymap._CMapData.parent; + ContentFlags = ymap._CMapData.contentFlags; + streamingExtentsMin = ymap._CMapData.streamingExtentsMin; + streamingExtentsMax = ymap._CMapData.streamingExtentsMax; + entitiesExtentsMin = ymap._CMapData.entitiesExtentsMin; + entitiesExtentsMax = ymap._CMapData.entitiesExtentsMax; + } + public MapDataStoreNode(BinaryReader br) + { + Name = new MetaHash(br.ReadUInt32()); + ParentName = new MetaHash(br.ReadUInt32()); + ContentFlags = br.ReadUInt32(); + streamingExtentsMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + streamingExtentsMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + entitiesExtentsMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + entitiesExtentsMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Unk02 = br.ReadByte(); + Unk03 = br.ReadByte(); + Unk04 = br.ReadByte(); + Unk05 = br.ReadByte(); + + if (Unk05 == 0xFE) + { + UnkExtra = new MapDataStoreNodeExtra(br); + } + } + + + public void AddChildToList(MapDataStoreNode child) + { + if (ChildrenList == null) + { + ChildrenList = new List(); + } + ChildrenList.Add(child); + } + public void ChildrenListToArray() + { + if (ChildrenList != null) + { + Children = ChildrenList.ToArray(); + ChildrenList = null; //plz get this GC + } + } + public void AddInteriorToList(CInteriorProxy iprx) + { + if (InteriorProxyList == null) + { + InteriorProxyList = new List(); + } + InteriorProxyList.Add(iprx); + } + public void InteriorProxyListToArray() + { + if (InteriorProxyList != null) + { + InteriorProxies = InteriorProxyList.ToArray(); + InteriorProxyList = null; //plz get this GC + } + } + + public override string ToString() + { + return Name.ToString() + ", " + + ParentName.ToString() + ", " + + ContentFlags.ToString() + ", " + + streamingExtentsMin.ToString() + ", " + + streamingExtentsMax.ToString() + ", " + + entitiesExtentsMin.ToString() + ", " + + entitiesExtentsMax.ToString();// + ", " + + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class MapDataStoreNodeExtra + { + public uint Unk01; //0 + public byte[] Unk02; //1 - 16 (60 bytes) + public uint Unk03;//16 + public uint Unk04; + public uint Unk05; + public uint Unk06; + public uint Unk07; + public uint Unk08; + public uint Unk09; + public uint Unk10; + + public string Unk02str + { + get + { + StringBuilder sb = new StringBuilder(); + if (Unk02 != null) + { + for (int i = 0; i < Unk02.Length; i++) + { + if (Unk02[i] == 0) break; + sb.Append((char)Unk02[i]); + } + } + return sb.ToString(); + } + } + + public MapDataStoreNodeExtra(BinaryReader br) + { + Unk01 = br.ReadUInt32(); + + Unk02 = new byte[60]; + for (int i = 0; i < 60; i++) + { + Unk02[i] = br.ReadByte(); + } + Unk03 = br.ReadUInt32(); + Unk04 = br.ReadUInt32(); + Unk05 = br.ReadUInt32(); + Unk06 = br.ReadUInt32(); + Unk07 = br.ReadUInt32(); + Unk08 = br.ReadUInt32(); + Unk09 = br.ReadUInt32(); + Unk10 = br.ReadUInt32(); + + } + + + public override string ToString() + { + return Unk01.ToString() + ", " + Unk02str; + } + } + + + +} diff --git a/GameFiles/FileTypes/CutFile.cs b/GameFiles/FileTypes/CutFile.cs new file mode 100644 index 0000000..003302b --- /dev/null +++ b/GameFiles/FileTypes/CutFile.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class CutFile : PackedFile + { + public RpfFileEntry FileEntry { get; set; } + public PsoFile Pso { get; set; } + + + public void Load(byte[] data, RpfFileEntry entry) + { + //MemoryStream ms = new MemoryStream(data); + + FileEntry = entry; + + MemoryStream ms = new MemoryStream(data); + + if (PsoFile.IsPSO(ms)) + { + Pso = new PsoFile(); + Pso.Load(ms); + + //PsoTypes.EnsurePsoTypes(Pso); + + var root = PsoTypes.GetRootEntry(Pso); + if (root != null) + { + } + return; + } + else + { + + } + + + + + } + + } +} diff --git a/GameFiles/FileTypes/DlcContentFile.cs b/GameFiles/FileTypes/DlcContentFile.cs new file mode 100644 index 0000000..3be162f --- /dev/null +++ b/GameFiles/FileTypes/DlcContentFile.cs @@ -0,0 +1,431 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.GameFiles +{ + public class DlcContentFile + { + + public List dataFiles { get; set; } = new List(); + public List contentChangeSets { get; set; } = new List(); + + public RpfFile DlcFile { get; set; } //used by GameFileCache + public Dictionary ExtraMounts { get; set; } = new Dictionary(); + public Dictionary RpfDataFiles { get; set; } = new Dictionary(); + + public DlcExtraTitleUpdateFile ExtraTitleUpdates { get; set; } + + public void Load(XmlDocument doc) + { + + var root = doc.DocumentElement; + + dataFiles.Clear(); + contentChangeSets.Clear(); + + foreach (XmlNode node in root.ChildNodes) + { + switch (node.Name) + { + case "disabledFiles": + foreach (XmlNode disabledFile in node.ChildNodes) + { } //nothing to see here.. + break; + case "includedXmlFiles": + foreach (XmlNode includedXmlFile in node.ChildNodes) + { } //nothing to see here.. + break; + case "includedDataFiles": + foreach (XmlNode includedDataFile in node.ChildNodes) + { } //nothing to see here.. + break; + case "dataFiles": + foreach (XmlNode dataFile in node.ChildNodes) + { + if (dataFile.NodeType == XmlNodeType.Element) + { + dataFiles.Add(new DlcContentDataFile(dataFile)); + } + } + break; + case "contentChangeSets": + foreach (XmlNode contentChangeSet in node.ChildNodes) + { + if (contentChangeSet.NodeType == XmlNodeType.Element) + { + contentChangeSets.Add(new DlcContentChangeSet(contentChangeSet)); + } + } + break; + case "patchFiles": + foreach (XmlNode patchFile in node.ChildNodes) + { } //nothing to see here.. + break; + default: + break; + } + + + } + + + } + + public void LoadDicts(DlcSetupFile setupfile, RpfManager rpfman, GameFileCache gfc) + { + ExtraMounts.Clear(); + RpfDataFiles.Clear(); + + foreach (var datafile in dataFiles) + { + string dfn = GameFileCache.GetDlcPlatformPath(datafile.filename).ToLower(); + if (datafile.fileType == "EXTRA_FOLDER_MOUNT_DATA") + { + string efmdxmlpath = datafile.filename.Replace(setupfile.deviceName + ":", DlcFile.Path).Replace('/', '\\'); + efmdxmlpath = gfc.GetDlcPatchedPath(efmdxmlpath); + XmlDocument efmdxml = rpfman.GetFileXml(efmdxmlpath); + + DlcExtraFolderMountFile efmf = new DlcExtraFolderMountFile(); + efmf.Load(efmdxml); + + ExtraMounts[dfn] = efmf; + } + if (datafile.fileType == "EXTRA_TITLE_UPDATE_DATA") + { + string etudxmlpath = datafile.filename.Replace(setupfile.deviceName + ":", DlcFile.Path).Replace('/', '\\'); + etudxmlpath = gfc.GetDlcPatchedPath(etudxmlpath); + XmlDocument etudxml = rpfman.GetFileXml(etudxmlpath); + + DlcExtraTitleUpdateFile etuf = new DlcExtraTitleUpdateFile(); + etuf.Load(etudxml); + + ExtraTitleUpdates = etuf; + } + if (datafile.fileType == "RPF_FILE") + { + RpfDataFiles[dfn] = datafile; + } + } + + } + + public override string ToString() + { + return dataFiles.Count.ToString() + " dataFiles, " + contentChangeSets.Count.ToString() + " contentChangeSets"; + } + } + + public class DlcContentDataFile + { + public string filename { get; set; } + public string fileType { get; set; } + public string contents { get; set; } + public string installPartition { get; set; } + public bool overlay { get; set; } + public bool disabled { get; set; } + public bool persistent { get; set; } + public bool loadCompletely { get; set; } + public bool locked { get; set; } + + public DlcContentDataFile(XmlNode node) + { + Load(node); + } + public void Load(XmlNode node) + { + foreach (XmlNode child in node.ChildNodes) + { + switch (child.Name) + { + case "filename": + filename = child.InnerText; + break; + case "fileType": + fileType = child.InnerText; + break; + case "contents": + contents = child.InnerText; + break; + case "installPartition": + installPartition = child.InnerText; + break; + case "overlay": + overlay = Xml.GetBoolAttribute(child, "value"); + break; + case "disabled": + disabled = Xml.GetBoolAttribute(child, "value"); + break; + case "persistent": + persistent = Xml.GetBoolAttribute(child, "value"); + break; + case "loadCompletely": + loadCompletely = Xml.GetBoolAttribute(child, "value"); + break; + case "locked": + locked = Xml.GetBoolAttribute(child, "value"); + break; + default: + break; + } + } + } + + public override string ToString() + { + return filename + ": " + fileType + ": " + contents + ": " + installPartition + + (overlay ? ", overlay" : "") + + (disabled ? ", disabled" : "") + + (persistent ? ", persistent" : "") + + (loadCompletely ? ", loadCompletely" : "") + + (locked ? ", locked" : ""); + } + } + + public class DlcContentChangeSet + { + public string changeSetName { get; set; } + public List filesToInvalidate { get; set; } + public List filesToDisable { get; set; } + public List filesToEnable { get; set; } + public List txdToLoad { get; set; } + public List txdToUnload { get; set; } + public List residentResources { get; set; } + public List unregisterResources { get; set; } + public List mapChangeSetData { get; set; } + public string associatedMap { get; set; } + public bool requiresLoadingScreen { get; set; } + public string loadingScreenContext { get; set; } + public bool useCacheLoader { get; set; } + public DlcContentChangeSetExecutionConditions executionConditions { get; set; } + + public DlcContentChangeSet(XmlNode node) + { + Load(node); + } + public void Load(XmlNode node) + { + foreach (XmlNode child in node.ChildNodes) + { + switch (child.Name) + { + case "changeSetName": + changeSetName = child.InnerText; + break; + case "filesToInvalidate": + filesToInvalidate = GetChildStringArray(child); + if (filesToInvalidate != null) + { } + break; + case "filesToDisable": + filesToDisable = GetChildStringArray(child); + if (filesToDisable != null) + { } + break; + case "filesToEnable": + filesToEnable = GetChildStringArray(child); + if (filesToEnable != null) + { } + break; + case "txdToLoad": + txdToLoad = GetChildStringArray(child); + if (txdToLoad != null) + { } + break; + case "txdToUnload": + txdToUnload = GetChildStringArray(child); + if (txdToUnload != null) + { } + break; + case "residentResources": + residentResources = GetChildStringArray(child); + if (residentResources != null) + { } + break; + case "unregisterResources": + unregisterResources = GetChildStringArray(child); + if (unregisterResources != null) + { } + break; + case "mapChangeSetData": + mapChangeSetData = new List(); + foreach (XmlNode mapChangeSetDataItem in child.ChildNodes) + { + mapChangeSetData.Add(new DlcContentChangeSet(mapChangeSetDataItem)); + } + break; + case "associatedMap": + associatedMap = child.InnerText; + break; + case "requiresLoadingScreen": + requiresLoadingScreen = Xml.GetBoolAttribute(child, "value"); + break; + case "loadingScreenContext": + loadingScreenContext = child.InnerText; + break; + case "useCacheLoader": + useCacheLoader = Xml.GetBoolAttribute(child, "value"); + break; + case "executionConditions": + executionConditions = new DlcContentChangeSetExecutionConditions(child); + break; + default: + break; + } + } + } + + private List GetChildStringArray(XmlNode node) + { + if (!node.HasChildNodes) return null; + var result = new List(); + foreach (XmlNode child in node.ChildNodes) + { + if (child.NodeType == XmlNodeType.Element) + { + result.Add(child.InnerText); + } + } + return result; + } + + public override string ToString() + { + return (changeSetName != null) ? changeSetName : (associatedMap != null) ? associatedMap : null; + } + + } + + public class DlcContentChangeSetExecutionConditions + { + public string activeChangesetConditions { get; set; } + public string genericConditions { get; set; } + + public DlcContentChangeSetExecutionConditions(XmlNode node) + { + Load(node); + } + public void Load(XmlNode node) + { + foreach (XmlNode child in node.ChildNodes) + { + if (child.NodeType != XmlNodeType.Element) continue; + switch (child.Name) + { + case "activeChangesetConditions": + activeChangesetConditions = child.InnerText; + break; + case "genericConditions": + genericConditions = child.InnerText; + break; + default: + break; + } + } + } + + public override string ToString() + { + return (string.IsNullOrEmpty(activeChangesetConditions) ? "" : activeChangesetConditions + ", ") + (string.IsNullOrEmpty(genericConditions) ? "" : genericConditions); + } + } + + + + public class DlcExtraFolderMountFile + { + public List FolderMounts { get; set; } = new List(); + + public void Load(XmlDocument doc) + { + var root = doc.DocumentElement; + + XmlNodeList mountitems = doc.SelectNodes("SExtraFolderMountData/FolderMounts/Item"); + FolderMounts.Clear(); + for (int i = 0; i < mountitems.Count; i++) + { + var mount = new DlcExtraFolderMount(); + mount.Init(mountitems[i]); + FolderMounts.Add(mount); + } + + } + + public override string ToString() + { + return "(" + FolderMounts.Count.ToString() + " FolderMounts)"; + } + } + + public class DlcExtraFolderMount + { + public string type { get; set; } + public string platform { get; set; } + public string path { get; set; } + public string mountAs { get; set; } + + public void Init(XmlNode node) + { + type = Xml.GetStringAttribute(node, "type"); + platform = Xml.GetStringAttribute(node, "platform"); + path = Xml.GetChildInnerText(node, "path"); + mountAs = Xml.GetChildInnerText(node, "mountAs"); + } + + public override string ToString() + { + return type + ": " + path + " - " + mountAs + ((platform != null) ? (" (" + platform + ")") : ""); + } + } + + + public class DlcExtraTitleUpdateFile + { + public List Mounts { get; set; } = new List(); + + public void Load(XmlDocument doc) + { + var root = doc.DocumentElement; + + XmlNodeList mountitems = doc.SelectNodes("SExtraTitleUpdateData/Mounts/Item"); + Mounts.Clear(); + for (int i = 0; i < mountitems.Count; i++) + { + var mount = new DlcExtraTitleUpdateMount(); + mount.Init(mountitems[i]); + Mounts.Add(mount); + } + + } + + public override string ToString() + { + return "(" + Mounts.Count.ToString() + " Mounts)"; + } + } + + public class DlcExtraTitleUpdateMount + { + public string type { get; set; } + public string deviceName { get; set; } + public string path { get; set; } + + public void Init(XmlNode node) + { + type = Xml.GetStringAttribute(node, "type"); + deviceName = Xml.GetChildInnerText(node, "deviceName"); + path = Xml.GetChildInnerText(node, "path"); + } + + public override string ToString() + { + return type + ": " + deviceName + " - " + path; + } + } + + + +} diff --git a/GameFiles/FileTypes/DlcSetupFile.cs b/GameFiles/FileTypes/DlcSetupFile.cs new file mode 100644 index 0000000..43b47ee --- /dev/null +++ b/GameFiles/FileTypes/DlcSetupFile.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.GameFiles +{ + public class DlcSetupFile + { + public string deviceName { get; set; } + public string datFile { get; set; } + public string nameHash { get; set; } + public List contentChangeSetGroups { get; set; } + public string type { get; set; } + public string timeStamp { get; set; } + public int order { get; set; } + public int minorOrder { get; set; } + public int subPackCount { get; set; } + public bool isLevelPack { get; set; } + + public RpfFile DlcFile { get; set; } //used by GameFileCache + public DlcContentFile ContentFile { get; set; } + + public void Load(XmlDocument doc) + { + + var root = doc.DocumentElement; + deviceName = Xml.GetChildInnerText(root, "deviceName"); + datFile = Xml.GetChildInnerText(root, "datFile"); + nameHash = Xml.GetChildInnerText(root, "nameHash"); + type = Xml.GetChildInnerText(root, "type"); + timeStamp = Xml.GetChildInnerText(root, "timeStamp"); + order = Xml.GetIntAttribute(root.SelectSingleNode("order"), "value"); + minorOrder = Xml.GetIntAttribute(root.SelectSingleNode("minorOrder"), "value"); + subPackCount = Xml.GetIntAttribute(root.SelectSingleNode("subPackCount"), "value"); + isLevelPack = Xml.GetBoolAttribute(root.SelectSingleNode("isLevelPack"), "value"); + + contentChangeSetGroups = new List(); + var groups = root.SelectNodes("contentChangeSetGroups/Item"); + foreach (XmlNode node in groups) + { + var group = new DlcSetupContentChangesetGroup(); + group.Load(node); + contentChangeSetGroups.Add(group); + } + + if (root.ChildNodes.Count > 15) + { } + } + + public override string ToString() + { + return deviceName + ", " + datFile + ", " + nameHash + ", " + type + ", " + order.ToString() + ", " + ((contentChangeSetGroups != null) ? contentChangeSetGroups.Count.ToString() : "0") + " groups, " + timeStamp; + } + } + + public class DlcSetupContentChangesetGroup + { + public string NameHash { get; set; } + public List ContentChangeSets { get; set; } + + public void Load(XmlNode node) + { + if (node.ChildNodes.Count != 2) + { } + NameHash = Xml.GetChildInnerText(node, "NameHash"); + ContentChangeSets = new List(); + var changesets = node.SelectNodes("ContentChangeSets/Item"); + foreach (XmlNode changeset in changesets) + { + ContentChangeSets.Add(changeset.InnerText); + } + } + + public override string ToString() + { + return NameHash + " (" + ((ContentChangeSets != null) ? ContentChangeSets.Count.ToString() : "0") + " changesets)"; + } + } +} diff --git a/GameFiles/FileTypes/FxcFile.cs b/GameFiles/FileTypes/FxcFile.cs new file mode 100644 index 0000000..561e4f7 --- /dev/null +++ b/GameFiles/FileTypes/FxcFile.cs @@ -0,0 +1,1074 @@ +using SharpDX.D3DCompiler; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +//GTAV FXC file reader by dexyfex. +// use this however you want. some credit would be nice. + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] + public class FxcFile : PackedFile + { + public string Name { get; set; } + public RpfFileEntry FileEntry { get; set; } + public uint Hash { get; set; } + + public VertexType VertexType { get; set; } + public FxcHeaderExt[] Exts { get; set; } + public FxcHeaderChunk[] Chunks { get; set; } + public FxcShader[] Shaders { get; set; } + public FxcCBuffer[] CBuffers1 { get; set; } + public FxcVariable[] Variables1 { get; set; } + public FxcCBuffer[] CBuffers2 { get; set; } + public FxcVariable[] Variables2 { get; set; } + public FxcTechnique[] Techniques { get; set; } + + + public FxcShader[] VertexShaders { get; set; } + public FxcShader[] PixelShaders { get; set; } + public FxcShader[] ComputeShaders { get; set; } + public FxcShader[] DomainShaders { get; set; } + public FxcShader[] GeometryShaders { get; set; } + public FxcShader[] HullShaders { get; set; } + + public Dictionary CBufferDict { get; set; } + public FxcVariable[] GlobalVariables { get; set; } + + + public string LastError { get; set; } + + + + + + + public void Load(byte[] data, RpfFileEntry entry) + { + FileEntry = entry; + Name = entry.Name; + Hash = entry.ShortNameHash; + + LastError = string.Empty; + + MemoryStream ms = new MemoryStream(data); + BinaryReader br = new BinaryReader(ms); + + uint magic_rgxe = br.ReadUInt32(); + if(magic_rgxe!= 1702389618) //"rgxe" + { + return; + } + + VertexType = (VertexType)br.ReadUInt32(); + + byte ec0 = br.ReadByte(); + var exts1 = new List(); + for (int e = 0; e < ec0; e++) + { + FxcHeaderExt ext = new FxcHeaderExt(); + ext.Name = ReadString(br); + ext.Unk0Byte = br.ReadByte(); //0 + ext.Unk1Uint = br.ReadUInt32(); //2 + exts1.Add(ext); + } + Exts = exts1.ToArray(); + + + List[] shadergrps = new List[6]; + + var chunks = new List(); + var shaders = new List(); + int gindex = 0; + while (gindex<6)// (sc0 > 0) + { + var shadergrp = new List(); + shadergrps[gindex] = shadergrp; + + gindex++; + byte sc0 = br.ReadByte(); + if (sc0 == 0) + { + sc0 = br.ReadByte(); //this is a little odd, sometimes a byte skip + } + FxcHeaderChunk chunk = new FxcHeaderChunk(); + chunk.Read(br); + chunk.Gindex = gindex; + chunk.ShaderCount = sc0; + chunks.Add(chunk); + for (int s = 1; s < sc0; s++) + { + bool exbyteflag1 = (gindex==5); //GS seems to be in diff format?? + FxcShader shader = new FxcShader(); + if (!shader.Read(br, exbyteflag1)) + { + LastError += shader.LastError; + gindex = 6; //get outta the loop + break; + } + shaders.Add(shader); + shadergrp.Add(shader); + } + } + + Shaders = shaders.ToArray(); + VertexShaders = shadergrps[0]?.ToArray(); + PixelShaders = shadergrps[1]?.ToArray(); + ComputeShaders = shadergrps[2]?.ToArray(); + DomainShaders = shadergrps[3]?.ToArray(); + GeometryShaders = shadergrps[4]?.ToArray(); + HullShaders = shadergrps[5]?.ToArray(); + + + Chunks = chunks.ToArray(); + + //ms.Dispose(); + //return; + + List globalVars = new List(); + CBufferDict = new Dictionary(); + FxcCBuffer cbtmp = null; + + try //things can be undertain after this... + { + + byte cbCount1 = br.ReadByte(); + if (cbCount1 > 0) + { + var cbuffers1 = new List(); + for (int i = 0; i < cbCount1; i++) //cbuffers? includes? + { + FxcCBuffer cbuf = new FxcCBuffer(); + cbuf.Read(br); + cbuffers1.Add(cbuf); + CBufferDict[cbuf.NameHash] = cbuf; + } + CBuffers1 = cbuffers1.ToArray(); + } + + byte varCount1 = br.ReadByte(); + if (varCount1 > 0) + { + var vars1 = new List(); //cbuffer contents/vars + for (int i = 0; i < varCount1; i++) + { + FxcVariable vari = new FxcVariable(); + vari.Read(br); + vars1.Add(vari); + if (CBufferDict.TryGetValue(vari.CBufferName, out cbtmp)) + { + cbtmp.AddVariable(vari); + } + else + { + globalVars.Add(vari); + } + } + Variables1 = vars1.ToArray(); + } + + + byte cbCount2 = br.ReadByte(); //0,1, +? + if (cbCount2 > 0) + { + var cbuffers2 = new List(); //more cbuffers.. + for (int i = 0; i < cbCount2; i++) + { + FxcCBuffer cbuf = new FxcCBuffer(); + cbuf.Read(br); + cbuffers2.Add(cbuf); + CBufferDict[cbuf.NameHash] = cbuf; + } + CBuffers2 = cbuffers2.ToArray(); + } + + + byte varCount2 = br.ReadByte(); + if (varCount2 > 0) + { + var vars2 = new List(); + for (int i = 0; i < varCount2; i++) //textures/samplers + { + FxcVariable vari = new FxcVariable(); + vari.Read(br); + vars2.Add(vari); + if (CBufferDict.TryGetValue(vari.CBufferName, out cbtmp)) + { + cbtmp.AddVariable(vari); + } + else + { + globalVars.Add(vari); + } + } + Variables2 = vars2.ToArray(); + } + + + byte techCount = br.ReadByte(); + if (techCount > 0) + { + var techniques = new List(); + for (int i = 0; i < techCount; i++) + { + FxcTechnique tech = new FxcTechnique(); + tech.Read(br); + techniques.Add(tech); + } + Techniques = techniques.ToArray(); + } + + + foreach (var cbuf in CBufferDict.Values) + { + cbuf.ConsolidateVariables(); + } + GlobalVariables = globalVars.ToArray(); + + + if (ms.Position != ms.Length) + { } + + } + catch (Exception ex) + { + LastError = ex.ToString(); + } + + ms.Dispose(); + } + + + + public string GetMetaString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("Name: " + Name); + sb.AppendLine("Hash: " + Hash.ToString()); + sb.AppendLine("Vertex type: " + ((uint)VertexType).ToString()); + sb.AppendLine(); + + if (Exts != null) + { + sb.AppendLine("Header"); + foreach (var ext in Exts) + { + sb.AppendLine(" " + ext.ToString()); + } + sb.AppendLine(); + } + + if (Chunks != null) + { + sb.AppendLine("Sections"); + foreach (var chunk in Chunks) + { + sb.AppendLine(" " + chunk.ToString()); + } + sb.AppendLine(); + } + + if (Shaders != null) + { + sb.AppendLine("Shaders (" + Shaders.Length.ToString() + ")"); + foreach (var shader in Shaders) + { + sb.AppendLine(" " + shader.Name); + if ((shader.Params != null) && (shader.Params.Length > 0)) + { + sb.AppendLine(" (Params)"); + foreach (var parm in shader.Params) + { + sb.AppendLine(" " + parm); + } + } + if ((shader.Buffers != null) && (shader.Buffers.Length > 0)) + { + sb.AppendLine(" (Buffers)"); + foreach (var ext in shader.Buffers) + { + sb.AppendLine(" " + ext.ToString()); + } + } + } + sb.AppendLine(); + } + + if (CBuffers1 != null) + { + sb.AppendLine("CBuffers 1 (" + CBuffers1.Length.ToString() + ")"); + foreach (var p in CBuffers1) + { + sb.AppendLine(" " + p.ToString()); + } + sb.AppendLine(); + } + + if (Variables1 != null) + { + sb.AppendLine("Variables 1 (" + Variables1.Length.ToString() + ")"); + foreach (var p in Variables1) + { + sb.AppendLine(" " + p.ToString()); + if ((p.Params != null) && (p.Params.Length > 0)) + { + sb.AppendLine(" (Params)"); + foreach (var c in p.Params) + { + sb.AppendLine(" " + c.ToString()); + } + } + if ((p.Values != null) && (p.Values.Length > 0)) + { + sb.AppendLine(" (Values)"); + foreach (var d in p.Values) + { + sb.AppendLine(" " + d.ToString()); + } + } + } + sb.AppendLine(); + } + + if (CBuffers2 != null) + { + sb.AppendLine("CBuffers 2 (" + CBuffers2.Length.ToString() + ")"); + foreach (var p in CBuffers2) + { + sb.AppendLine(" " + p.ToString()); + } + sb.AppendLine(); + } + + if (Variables2 != null) + { + sb.AppendLine("Variables 2 (" + Variables2.Length.ToString() + ")"); + foreach (var p in Variables2) + { + sb.AppendLine(" " + p.ToString()); + if ((p.Params != null) && (p.Params.Length > 0)) + { + sb.AppendLine(" (Params)"); + foreach (var c in p.Params) + { + sb.AppendLine(" " + c.ToString()); + } + } + if ((p.Values != null) && (p.Values.Length > 0)) + { + sb.AppendLine(" (Values)"); + foreach (var d in p.Values) + { + sb.AppendLine(" " + d.ToString()); + } + } + } + sb.AppendLine(); + } + + if (Techniques != null) + { + sb.AppendLine("Techniques (" + Techniques.Length.ToString() + ")"); + foreach (var t in Techniques) + { + sb.AppendLine(" " + t.Name); + if ((t.PassCount > 0) && (t.Passes != null)) + { + sb.AppendLine(" (Passes)"); + foreach (var p in t.Passes) + { + sb.AppendLine(" " + p.ToString()); + if ((p.ParamCount > 0) && (p.Params != null)) + { + //sb.AppendLine(" Params"); + foreach (var v in p.Params) + { + sb.AppendLine(" " + v.ToString()); + } + } + } + } + } + sb.AppendLine(); + } + + return sb.ToString(); + } + + + public FxcShader GetVS(int id) + { + int i = id - 1; + if ((i < 0) || (VertexShaders == null) || (i >= VertexShaders.Length)) + { + return null; + } + return VertexShaders[i]; + } + public FxcShader GetPS(int id) + { + int i = id - 1; + if ((i < 0) || (PixelShaders == null) || (i >= PixelShaders.Length)) + { + return null; + } + return PixelShaders[i]; + } + public FxcShader GetCS(int id) + { + int i = id - 1; + if ((i < 0) || (ComputeShaders == null) || (i >= ComputeShaders.Length)) + { + return null; + } + return ComputeShaders[i]; + } + public FxcShader GetDS(int id) + { + int i = id - 1; + if ((i < 0) || (DomainShaders == null) || (i >= DomainShaders.Length)) + { + return null; + } + return DomainShaders[i]; + } + public FxcShader GetGS(int id) + { + int i = id - 1; + if ((i < 0) || (GeometryShaders == null) || (i >= GeometryShaders.Length)) + { + return null; + } + return GeometryShaders[i]; + } + public FxcShader GetHS(int id) + { + int i = id - 1; + if ((i < 0) || (HullShaders == null) || (i >= HullShaders.Length)) + { + return null; + } + return HullShaders[i]; + } + + + + + public static string ReadString(BinaryReader br) + { + byte sl = br.ReadByte(); + if (sl == 0) return string.Empty; + byte[] ba = new byte[sl]; + br.Read(ba, 0, sl); + return (sl > 1) ? ASCIIEncoding.ASCII.GetString(ba, 0, sl - 1) : string.Empty; + } + public static string[] ReadStringArray(BinaryReader br) + { + string[] r = null; + + byte sc = br.ReadByte(); + if (sc > 0) + { + StringBuilder sb = new StringBuilder(); + r = new string[sc]; + for (int i = 0; i < sc; i++) + { + sb.Clear(); + byte sl = br.ReadByte(); + for (int n = 0; n < sl; n++) + { + sb.Append((char)br.ReadByte()); + } + r[i] = sb.ToString().Replace("\0", ""); + } + } + + return r; + } + + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcHeaderExt + { + public string Name { get; set; } + public byte Unk0Byte { get; set; } + public uint Unk1Uint { get; set; } + + public override string ToString() + { + return Name + ": " + Unk0Byte.ToString() + ": " + Unk1Uint.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcHeaderChunk + { + public string Name { get; set; } + public byte Unk1Byte { get; set; } + public byte Unk2Byte { get; set; } + public uint Unk3Uint { get; set; } + public int Gindex { get; set; } //index in the fxc file + public byte ShaderCount { get; set; } //number of shaders in the section + + public void Read(BinaryReader br) + { + Name = FxcFile.ReadString(br); //usually "NULL" + Unk1Byte = br.ReadByte(); + Unk2Byte = br.ReadByte(); + Unk3Uint = br.ReadUInt32(); + } + + public override string ToString() + { + return Name + ": " + Gindex.ToString() + ": " + ShaderCount.ToString() + ": " + Unk1Byte.ToString() + ": " + Unk2Byte.ToString() + ": " + Unk3Uint.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcShader + { + public string Name { get; set; } + public string[] Params { get; set; } + public FxcShaderBufferRef[] Buffers { get; set; }//CBuffers + public byte VersionMajor { get; set; } + public byte VersionMinor { get; set; } + public byte[] ByteCode { get; set; } + public ShaderBytecode ByteCodeObj { get; set; } + public ShaderProfile ShaderProfile { get; set; } + public string Disassembly { get; set; } + public string LastError { get; set; } + + public bool Read(BinaryReader br, bool exbyteflag) + { + Name = FxcFile.ReadString(br); + + if (Name.Length == 0) + { + Name = FxcFile.ReadString(br); //why (seems to be GS only) + exbyteflag = true; + } + + + Params = FxcFile.ReadStringArray(br); + + byte bufferCount = br.ReadByte(); + var buffers = new List(); + for (int e = 0; e < bufferCount; e++) + { + FxcShaderBufferRef ext = new FxcShaderBufferRef(); + ext.Name = FxcFile.ReadString(br); + ext.Unk0Ushort = br.ReadUInt16(); + buffers.Add(ext); + } + Buffers = buffers.ToArray(); + + byte exbyte = 0; + if (exbyteflag) + { + exbyte = br.ReadByte(); //not sure what this is used for... + if ((exbyte != 0)) + { } + } + + + uint datalength = br.ReadUInt32(); + + if (datalength > 0) + { + uint magic_dxbc = br.ReadUInt32(); + if (magic_dxbc != 1128421444) //"DXBC" - directx bytecode header + { + LastError += "Unexpected data found at DXBC header...\r\n"; + return false; //didn't find the DXBC header... abort! + } + br.BaseStream.Position -= 4; //wind back because dx needs that header + + ByteCode = br.ReadBytes((int)datalength); + + + try + { + ByteCodeObj = new ShaderBytecode(ByteCode); + + ShaderProfile = ByteCodeObj.GetVersion(); + + Disassembly = ByteCodeObj.Disassemble(); + + + switch (ShaderProfile.Version) + { + case ShaderVersion.VertexShader: + case ShaderVersion.PixelShader: + case ShaderVersion.GeometryShader: + VersionMajor = br.ReadByte();//4,5 //appears to be shader model version + VersionMinor = br.ReadByte(); //perhaps shader minor version + break; + default: + VersionMajor = (byte)ShaderProfile.Major; + VersionMinor = (byte)ShaderProfile.Minor; + break; + } + + } + catch (Exception ex) + { + LastError += ex.ToString() + "\r\n"; + return false; + } + } + else + { + } + return true; + } + + + + public override string ToString() + { + return Name; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcShaderBufferRef + { + public string Name { get; set; } //Buffer name + public ushort Unk0Ushort { get; set; } + + public override string ToString() + { + return Name + ": " + Unk0Ushort.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcCBuffer + { + public uint u003 { get; set; } + public ushort us001 { get; set; } + public ushort us002 { get; set; } + public ushort us003 { get; set; } + public ushort us004 { get; set; } + public ushort us005 { get; set; } + public ushort us006 { get; set; } + public string Name { get; set; } + + public uint NameHash { get { return JenkHash.GenHash(Name); } } + public List VariablesList; + public FxcVariable[] Variables { get; set; } + + public void Read(BinaryReader br) + { + u003 = br.ReadUInt32(); //176, 16 //256 + us001 = br.ReadUInt16(); //6, 5 + us002 = br.ReadUInt16(); //6, 12 + us003 = br.ReadUInt16(); //6, 5 + us004 = br.ReadUInt16(); //6, 5 + us005 = br.ReadUInt16(); //6, 5 + us006 = br.ReadUInt16(); //6, 5 + Name = FxcFile.ReadString(br); // _locals //"rage_matrices", "misc_globals", "lighting_globals", "more_stuff" + JenkIndex.Ensure(Name); //why not :P + } + + public override string ToString() + { + return Name + ": " + u003 + ", " + us001 + ", " + us002 + ", " + us003 + ", " + us004 + ", " + us005 + ", " + us006; + } + + public void AddVariable(FxcVariable vari) + { + if (VariablesList == null) VariablesList = new List(); + VariablesList.Add(vari); + } + public void ConsolidateVariables() + { + if (VariablesList != null) + { + Variables = VariablesList.ToArray(); + VariablesList = null; + } + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcVariable + { + public byte b0 { get; set; } + public byte b1 { get; set; } + public byte b2 { get; set; } + public byte b3 { get; set; } + public string Name1 { get; set; } + public string Name2 { get; set; } + public byte b4 { get; set; } + public byte b5 { get; set; } + public byte b6 { get; set; } + public byte b7 { get; set; } + public MetaHash CBufferName { get; set; } + public byte ParamCount { get; set; } + public FxcVariableParam[] Params { get; set; } + public byte ValueCount { get; set; } + public float[] Values { get; set; } + + + public void Read(BinaryReader br) + { + b0 = br.ReadByte(); //5 + b1 = br.ReadByte(); //0,1 + b2 = br.ReadByte(); //19 //17 + b3 = br.ReadByte(); //2 //27 + Name1 = FxcFile.ReadString(br); + Name2 = FxcFile.ReadString(br); + b4 = br.ReadByte(); //32 + b5 = br.ReadByte(); // + b6 = br.ReadByte(); // + b7 = br.ReadByte(); // + CBufferName = br.ReadUInt32(); //hash + + + ParamCount = br.ReadByte(); //1 + if (ParamCount > 0) + { + List parms = new List(); + for (int i = 0; i < ParamCount; i++) + { + FxcVariableParam parm = new FxcVariableParam(); + parm.Read(br); + parms.Add(parm); + } + Params = parms.ToArray(); + } + + ValueCount = br.ReadByte(); + if (ValueCount > 0) + { + Values = new float[ValueCount]; + for (int i = 0; i < ValueCount; i++) + { + Values[i] = br.ReadSingle(); //TODO: how to know what types to use? + } + } + + + #region debug validation + + switch (b0) + { + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 11: + case 14: + case 17: + case 20: + break; + case 15: + case 18: + case 19: + case 21: + case 22: + break; + default: + break; + } + + switch (b1) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 8: + case 12: + case 254: + case 255: + break; + case 14: + case 16: + case 24: + case 40: + case 117: + break; + default: + break; + } + + switch (CBufferName) + { + case 2165770756: + case 3458315595: + case 1059338858: + case 3779850771: + case 2988188919: + case 713939274: + case 3369176576: + case 1927486087: + case 4135739982: + case 1032736383: + case 3084860475: + case 3844532749: + case 3635751376: + case 2172777116: + case 4255900365: + case 2725372071: + case 3661207622: + case 4213364555: + case 1519748817: + case 118958736: + case 2397841684: + case 1340365912: + case 2531859994: + case 0: + break; + case 482774302: + case 2300268537: + case 2714887816: + case 2049538169: + case 1316881611: + case 3367312321: + case 4017086211: + case 3743503190: + case 938670440: + case 2782027784: + case 2865440919: + case 2384984532: + case 486482914: + case 3162602184: + case 1834530379: + case 1554708878: + case 1142002603: + case 3049310097: + case 764124013: + case 2526104914: + case 1561144077: + case 970248680: + case 3899781660: + case 1853474951: + case 2224880237: + case 3766848419: + case 2718810031: + case 115655537: + case 4224116138: + case 3572088685: + case 1438660507: + case 4092686193: + case 871214106: + case 2121263542: + case 3502503908: + case 586499600: + case 4046148196: + case 2999112456: + case 2355014976: + case 579364910: + case 2193272593: + case 1641847936: + case 1286180849: + case 3291504934: + case 278397346: + case 3346871633: + case 4091106477: + case 832855465: + case 3616072140: + case 3977262900: + case 2062541604: + case 950211059: + case 2380663322: + case 2783177544: + case 1100625170: + case 1279142172: + case 1004646027: + case 2092585241: + case 4165560568: + case 2651790209: + case 3453406875: + case 488789527: + case 3375019131: + case 519785780: + case 729415208: + case 556501613: + case 2829744882: + case 1778702372: + case 2564407213: + case 3291498326: + case 1275817784: + case 962813362: + case 2020034807: + case 2017746823: + case 1237102223: + case 4029270406: + case 673228990: + case 201854132: + case 1866965008: + case 957783816: + case 2522030664: + case 1910375705: + case 2656344872: + break; + default: + break; + } + + switch (b3) + { + case 0: + case 1: + case 2: + case 3: + case 10: + case 11: + case 17: + case 19: + case 27: + case 34: + break; + case 6: + case 16: + case 26: + case 32: + case 33: + case 35: + case 39: + case 49: + case 51: + break; + default: + break; + } + + + #endregion + + + } + + public override string ToString() + { + return b0.ToString() + ", " + b1.ToString() + ", " + b2.ToString() + ", " + b3.ToString() + ", " + b4.ToString() + ", " + b5.ToString() + ", " + b6.ToString() + ", " + b7.ToString() + ", " + CBufferName.ToString() + ", " + Name1 + ", " + Name2; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcVariableParam + { + public string Name { get; set; } + public byte Type { get; set; } + public object Value { get; set; } + + public void Read(BinaryReader br) + { + Name = FxcFile.ReadString(br); + Type = br.ReadByte(); + switch (Type) + { + case 0: + Value = br.ReadUInt32(); + break; + case 1: + Value = br.ReadSingle(); + break; + case 2: + Value = FxcFile.ReadString(br); + break; + default: + break; + } + } + + public override string ToString() + { + return Name + ": " + Value?.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcTechnique + { + public string Name { get; set; } + public byte PassCount { get; set; } + public FxcPass[] Passes { get; set; } + + public void Read(BinaryReader br) + { + Name = FxcFile.ReadString(br); //"draw", "deferred_draw", etc.. + + PassCount = br.ReadByte();// + if (PassCount > 0) + { + Passes = new FxcPass[PassCount]; + for (int i = 0; i < PassCount; i++) + { + FxcPass p = new FxcPass(); + p.Read(br); + Passes[i] = p; + } + } + + } + + public override string ToString() + { + return Name + " (" + PassCount.ToString() + " pass" + (PassCount != 1 ? "es" : "") + ")"; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcPass + { + public byte VS { get; set; } + public byte PS { get; set; } + public byte CS { get; set; } + public byte DS { get; set; } + public byte GS { get; set; } + public byte HS { get; set; } + public byte ParamCount { get; set; } + public FxcPassParam[] Params { get; set; } + + public void Read(BinaryReader br) + { + VS = br.ReadByte(); + PS = br.ReadByte(); + CS = br.ReadByte(); + DS = br.ReadByte(); + GS = br.ReadByte(); + HS = br.ReadByte(); + + ParamCount = br.ReadByte(); + if (ParamCount > 0) + { + Params = new FxcPassParam[ParamCount]; + for (int i = 0; i < ParamCount; i++) + { + FxcPassParam p = new FxcPassParam(); + p.u0 = br.ReadUInt32(); + p.u1 = br.ReadUInt32(); + Params[i] = p; + } + } + } + + public override string ToString() + { + return VS.ToString() + ", " + PS.ToString() + ", " + CS.ToString() + ", " + DS.ToString() + ", " + GS.ToString() + ", " + HS.ToString(); + } + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FxcPassParam + { + public uint u0 { get; set; } + public uint u1 { get; set; } + + public override string ToString() + { + return u0.ToString() + ", " + u1.ToString(); + } + } + + +} diff --git a/GameFiles/FileTypes/Gxt2File.cs b/GameFiles/FileTypes/Gxt2File.cs new file mode 100644 index 0000000..016f01e --- /dev/null +++ b/GameFiles/FileTypes/Gxt2File.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] public class Gxt2File : PackedFile + { + public string Name { get; set; } + public RpfFileEntry FileEntry { get; set; } + public uint EntryCount { get; set; } + public Gxt2Entry[] TextEntries { get; set; } + //public Dictionary Dict { get; set; } + + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + FileEntry = entry; + //Dict = new Dictionary(); + + using (BinaryReader br = new BinaryReader(new MemoryStream(data))) + { + uint gxt2 = br.ReadUInt32(); //"GXT2" - 1196971058 + if (gxt2 != 1196971058) + { return; } + + EntryCount = br.ReadUInt32(); + TextEntries = new Gxt2Entry[EntryCount]; + for (uint i = 0; i < EntryCount; i++) + { + var e = new Gxt2Entry(); + e.Hash = br.ReadUInt32(); + e.Offset = br.ReadUInt32(); + TextEntries[i] = e; + } + + gxt2 = br.ReadUInt32(); //another "GXT2" + if (gxt2 != 1196971058) + { return; } + + uint endpos = br.ReadUInt32(); + + List buf = new List(); + + for (uint i = 0; i < EntryCount; i++) + { + var e = TextEntries[i]; + br.BaseStream.Position = e.Offset; + + buf.Clear(); + byte b = br.ReadByte(); + while ((b != 0) && (br.BaseStream.Position Index = new Dictionary(); + private static object syncRoot = new object(); + + public static volatile bool FullIndexBuilt = false; + + public static void Clear() + { + lock (syncRoot) + { + Index.Clear(); + } + } + + public static bool Ensure(string str) + { + uint hash = JenkHash.GenHash(str); + if (hash == 0) return true; + lock (syncRoot) + { + if (!Index.ContainsKey(hash)) + { + Index.Add(hash, str); + return false; + } + } + return true; + } + + public static bool Ensure(string str, uint hash) + { + if (hash == 0) return true; + lock (syncRoot) + { + if (!Index.ContainsKey(hash)) + { + Index.Add(hash, str); + return false; + } + } + return true; + } + + public static string GetString(uint hash) + { + string res; + lock (syncRoot) + { + if (!Index.TryGetValue(hash, out res)) + { + res = hash.ToString(); + } + } + return res; + } + public static string TryGetString(uint hash) + { + string res; + lock (syncRoot) + { + if (!Index.TryGetValue(hash, out res)) + { + res = string.Empty; + } + } + return res; + } + + } + + + +} diff --git a/GameFiles/FileTypes/JPsoFile.cs b/GameFiles/FileTypes/JPsoFile.cs new file mode 100644 index 0000000..8062e5f --- /dev/null +++ b/GameFiles/FileTypes/JPsoFile.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class JPsoFile : PackedFile + { + public RpfFileEntry FileEntry { get; set; } + public PsoFile Pso { get; set; } + + + public void Load(byte[] data, RpfFileEntry entry) + { + //MemoryStream ms = new MemoryStream(data); + + FileEntry = entry; + + MemoryStream ms = new MemoryStream(data); + + if (PsoFile.IsPSO(ms)) + { + Pso = new PsoFile(); + Pso.Load(ms); + + //PsoTypes.EnsurePsoTypes(Pso); + + var root = PsoTypes.GetRootEntry(Pso); + if (root != null) + { + } + return; + } + else + { + + } + + + + + } + + } +} diff --git a/GameFiles/FileTypes/RelFile.cs b/GameFiles/FileTypes/RelFile.cs new file mode 100644 index 0000000..89ed584 --- /dev/null +++ b/GameFiles/FileTypes/RelFile.cs @@ -0,0 +1,800 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] + public class RelFile : PackedFile + { + public RpfFileEntry FileEntry { get; set; } + public string Name { get; set; } + + public uint Type { get; set; } + public uint DataLength { get; set; } + public byte[] DataBlock { get; set; } + public uint DataUnkVal { get; set; } + public uint NameTableLength { get; set; } + public uint NameTableCount { get; set; } + public uint[] NameTableOffsets { get; set; } + public string[] NameTable { get; set; } + public uint IndexCount { get; set; } + public uint IndexStringFlags { get; set; } + public RelIndexHash[] IndexHashes { get; set; } + public RelIndexString[] IndexStrings { get; set; } + public uint Unk05Count { get; set; } + public uint[] Unk05Arr { get; set; } + public MetaHash[] Unk05Hashes { get; set; } + public uint Unk06Count { get; set; } + public uint[] Unk06Arr { get; set; } + public MetaHash[] Unk06Hashes { get; set; } + + public RelData[] RelDatas { get; set; } + public RelData[] RelDatasSorted { get; set; } + //testing zone for decoding .rel audio files. + + public RelFile() + { + } + public RelFile(RpfFileEntry entry) + { + FileEntry = entry; + } + + public void Load(byte[] data, RpfFileEntry entry) + { + FileEntry = entry; + Name = entry.Name; + + MemoryStream ms = new MemoryStream(data); + BinaryReader br = new BinaryReader(ms); + StringBuilder sb = new StringBuilder(); + + Type = br.ReadUInt32(); //type/version? + + DataLength = br.ReadUInt32(); //length of data block + DataBlock = br.ReadBytes((int)DataLength); //data block... synth infos? script? + + NameTableLength = br.ReadUInt32(); //length of this nametable block + NameTableCount = br.ReadUInt32(); + if (NameTableCount > 0) + { + uint[] d02 = new uint[NameTableCount]; //string offsets + for (uint i = 0; i < NameTableCount; i++) + { + d02[i] = br.ReadUInt32(); + } + NameTableOffsets = d02; + string[] names = new string[NameTableCount]; + for (uint i = 0; i < NameTableCount; i++) + { + sb.Clear(); + while (true) + { + char c = (char)br.ReadByte(); + if (c != 0) sb.Append(c); + else break; + } + names[i] = sb.ToString(); + } + NameTable = names; + } + + IndexCount = br.ReadUInt32(); //count of index items + if (IndexCount > 0) + { + //checking NameTableLength here doesn't make sense! + if ((Type == 4) && (NameTableLength == 4))//audioconfig.dat4.rel + { + IndexStringFlags = br.ReadUInt32(); //what is this? 2524 + RelIndexString[] indexstrs = new RelIndexString[IndexCount]; + for (uint i = 0; i < IndexCount; i++) + { + byte sl = br.ReadByte(); + sb.Clear(); + for (int j = 0; j < sl; j++) + { + char c = (char)br.ReadByte(); + if (c != 0) sb.Append(c); + } + RelIndexString cunk01 = new RelIndexString(); + cunk01.Name = sb.ToString(); + cunk01.Offset = br.ReadUInt32(); + cunk01.Length = br.ReadUInt32(); + indexstrs[i] = cunk01; + } + IndexStrings = indexstrs; + } + else //for all other .rel files... + { + RelIndexHash[] indexhashes = new RelIndexHash[IndexCount]; + for (uint i = 0; i < IndexCount; i++) + { + RelIndexHash unk01 = new RelIndexHash(); + unk01.Name = new MetaHash(br.ReadUInt32()); + unk01.Offset = br.ReadUInt32(); + unk01.Length = br.ReadUInt32(); + indexhashes[i] = unk01; + } + IndexHashes = indexhashes; + } + } + + + Unk05Count = br.ReadUInt32(); + if (Unk05Count != 0) + { + uint[] d05 = new uint[Unk05Count]; + MetaHash[] d05h = new MetaHash[Unk05Count]; + for (uint i = 0; i < Unk05Count; i++) + { + d05[i] = br.ReadUInt32(); + + var pos = ms.Position; + ms.Position = d05[i]; + d05h[i] = new MetaHash(br.ReadUInt32()); + ms.Position = pos; + } + Unk05Arr = d05; + Unk05Hashes = d05h; + } + + Unk06Count = br.ReadUInt32(); + if (Unk06Count != 0) + { + uint[] d06 = new uint[Unk06Count]; + MetaHash[] d06h = new MetaHash[Unk06Count]; + for (uint i = 0; i < Unk06Count; i++) + { + d06[i] = br.ReadUInt32(); + + var pos = ms.Position; + ms.Position = d06[i]; + d06h[i] = new MetaHash(br.ReadUInt32()); + ms.Position = pos; + } + Unk06Arr = d06; + Unk06Hashes = d06h; + } + + if (ms.Position != ms.Length) + { } + //EOF! + + br.Dispose(); + ms.Dispose(); + + + ParseDataBlock(); + } + + + private void ParseDataBlock() + { + + + + MemoryStream ms = new MemoryStream(DataBlock); + BinaryReader br = new BinaryReader(ms); + + DataUnkVal = br.ReadUInt32(); //3 bytes used... for? ..version? + switch (DataUnkVal) + { + case 5252715: //dlcbusiness_amp.dat10.rel + case 5301323: //dlcbeach_game.dat149.rel + case 5378673: //dlcmpheist_game.dat150.rel + case 5750395: //dlcbeach_game.dat150.rel + case 6353778: //dlcbeach_game.dat151.rel + case 6894089: //dlcpilotschool_game.dat151.rel + case 6978435: //dlcxmas2_amp.dat10.rel + case 7126027: //audioconfig.dat4.rel + case 7314721: //dlcmpheist_amp.dat10.rel + case 7516460: //dlcpd03_game.dat151.rel + case 7917027: //dlcluxe_amp.dat10.rel + case 7921508: //dlcluxe_game.dat151.rel + case 8149475: //dlcluxe2_amp.dat10.rel + case 8751734: //dlcsfx1_game.dat151.rel + case 9028036: //dlchalloween_amp.dat10.rel + case 9037528: //dlclowrider_amp.dat10.rel + case 9458585: //dlcapartment_amp.dat10.rel + case 9486222: //dlcapartment_mix.dat15.rel + case 9806108: //mpvalentines2_amp.dat10.rel + case 9813679: //dlcjanuary2016_amp.dat10.rel + case 10269543://dlclow2_amp.dat10.rel + case 10891463://dlcexec1_amp.dat10.rel + case 11171338://dlcstunt_amp.dat10.rel + case 11918985://dlcbiker_amp.dat10.rel + case 12470522://dlcimportexport_amp.dat10.rel + case 12974726://audioconfig.dat4.rel + case 13117164://dlcspecialraces_amp.dat10.rel + break; + default: + break; + } + + + List reldatas = new List(); + if (IndexHashes != null) + { + foreach (var indexhash in IndexHashes) + { + ms.Position = indexhash.Offset; + RelData d = new RelData(); + d.NameHash = indexhash.Name; + d.Offset = indexhash.Offset; + d.Length = indexhash.Length; + d.Data = br.ReadBytes((int)indexhash.Length); + reldatas.Add(d); + } + } + else if (IndexStrings != null) + { + foreach (var indexstr in IndexStrings) + { + ms.Position = indexstr.Offset; + RelData d = new RelData(); + d.Name = indexstr.Name; + d.Offset = indexstr.Offset; + d.Length = indexstr.Length; + d.Data = br.ReadBytes((int)indexstr.Length); + reldatas.Add(d); + } + } + RelDatas = reldatas.ToArray(); + + reldatas.Sort((d1, d2) => d1.Offset.CompareTo(d2.Offset)); + RelDatasSorted = reldatas.ToArray(); + + + br.Dispose(); + ms.Dispose(); + + + foreach (var d in RelDatas) + { + using (BinaryReader dbr = new BinaryReader(new MemoryStream(d.Data))) + { + switch (Type) + { + case 4: //00000100 //speech.dat4.rel, audioconfig.dat4.rel + ParseData4(d, dbr); + break; + case 10: //00001010 //amp.dat10.rel + ParseData10(d, dbr); + break; + case 15: //00001111 //mix.dat15.rel + ParseData15(d, dbr); + break; + case 16: //00010000 //curves.dat16.rel + ParseData16(d, dbr); + break; + case 22: //00010110 //categories.dat22.rel + ParseData22(d, dbr); + break; + case 54: //00110110 //sounds.dat54.rel + ParseData54(d, dbr); + break; + case 149: //10010101 //game.dat149.rel + ParseData149(d, dbr); + break; + case 150: //10010110 //game.dat150.rel + ParseData150(d, dbr); + break; + case 151: //10010111 //game.dat151.rel + ParseData151(d, dbr); + break; + default: + break; + } + } + } + + + } + + private void ParseData4(RelData d, BinaryReader br) + { + //speech.dat4.rel, audioconfig.dat4.rel + + if (d.Length == 1) + { + byte b = br.ReadByte(); + switch (b) + { + case 0: + case 25: + case 28: + case 34: + case 89: + case 94: + case 178: + break; + default: + break; + } + return; + } + if (d.Length == 2) + { + byte b = br.ReadByte(); + switch (b) + { + case 4: + case 1: + case 15: + case 12: + case 3: + case 2: + case 7: + case 5: + case 158: + case 25: + case 16: + case 64: + case 6: + case 8: + case 14: + case 22: + case 18: + case 20: + case 32: + case 17: + case 30: + case 9: + case 0: + case 47: + case 224: + case 200: + case 136: + case 45: + case 54: + case 28: + case 19: + case 37: + case 61: + case 38: + case 128: + case 24: + case 26: + case 40: + case 13: + case 36: + case 78: + case 34: + case 10: + case 21: + case 192: + case 60: + case 29: + case 33: + case 72: + case 57: + case 133: + case 11: + break; + default: + break; + } + return; + } + if (d.Length == 4) + { + uint h = br.ReadUInt32(); + return; + } + + + byte b00 = br.ReadByte(); + switch (b00) + { + case 4: + case 1: + case 0: + case 6: + case 3: + case 2: + case 5: + case 7: + case 15: + case 10: + case 8: + case 9: + break; + + case 23: + case 12: + case 11: + case 16: + case 13: + case 36: + case 30: + case 31: + case 27: + case 20: + case 19: + case 14: + case 40: + case 46: + case 22: + case 18: + case 21: + case 45: + case 17: + case 48: + case 87: + case 38: + case 28: + case 29: + case 43: + case 69: + case 50: + case 25: + case 32: + case 35: + case 34: + break; + default: + break; + } + } + private void ParseData10(RelData d, BinaryReader br) + { + //amp.dat10.rel + + byte b00 = br.ReadByte(); + switch (b00) + { + case 1: + case 3: + break; + default: + break; + } + } + private void ParseData15(RelData d, BinaryReader br) + { + //mix.dat15.rel + + byte b00 = br.ReadByte(); + switch (b00) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + break; + default: + break; + } + } + private void ParseData16(RelData d, BinaryReader br) + { + //curves.dat16.rel + + byte b00 = br.ReadByte(); + switch (b00) + { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 12: + case 13: + case 15: + break; + default: + break; + } + } + private void ParseData22(RelData d, BinaryReader br) + { + //categories.dat22.rel + + byte b00 = br.ReadByte(); + switch (b00) + { + case 0: + break; + default: + break; + } + } + private void ParseData54(RelData d, BinaryReader br) + { + //sounds.dat54.rel + + byte b00 = br.ReadByte(); + switch (b00) + { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + break; + default: + break; + } + } + private void ParseData149(RelData d, BinaryReader br) + { + //game.dat149.rel + + byte b00 = br.ReadByte(); + switch (b00) + { + case 3: + case 4: + case 17: + case 50: + case 57: + case 62: + case 63: + case 66: + case 76: + case 88: + case 90: + break; + default: + break; + } + } + private void ParseData150(RelData d, BinaryReader br) + { + //game.dat150.rel + + byte b00 = br.ReadByte(); + switch (b00) + { + case 3: + case 4: + case 6: + case 8: + case 17: + case 32: + case 37: + case 38: + case 39: + case 47: + case 50: + case 52: + case 57: + case 62: + case 63: + case 64: + case 65: + case 66: + case 76: + case 88: + case 90: + case 117: + break; + default: + break; + } + } + private void ParseData151(RelData d, BinaryReader br) + { + //game.dat151.rel + + byte b00 = br.ReadByte(); //??? + switch (b00) + { + case 1://new + case 2://new + case 3: + case 4: + case 5://new + case 6: + case 7://new + case 8:// + case 9://new + case 11://new + case 12://new + case 13://new + case 14://new + case 15://new + case 16://new + case 17: + case 18://new + case 22://new + case 23://new + case 24://new + case 25://new + case 26://new + case 27://new + case 28://new + case 29://new + case 30://new + case 31://new + case 32:// + case 33://new + case 35://new + case 36://new + case 37:// + case 38:// + case 39:// + case 40://new + case 41://new + case 42://new + case 44://new + case 45://new + case 46://new + case 47:// + case 48://new + case 49://new + case 50: + case 51://new + case 52:// + case 53://new + case 54://new + case 55://new + case 56://new + case 57: + case 59://new + case 62: + case 63: + case 64: + case 65:// + case 66: + case 67://new + case 68://new + case 69://new + case 70://new + case 71://new + case 72://new + case 73://new + case 74://new + case 75://new + case 76: + case 77://new + case 78://new + case 79://new + case 80://new + case 81://new + case 82://new + case 83://new + case 84://new + case 85://new + case 86://new + case 87://new + case 88: + case 90: + case 91://new + case 92://new + case 93://new + case 94://new + case 95://new + case 96://new + case 98://new + case 99://new + case 100://new + case 101://new + case 102://new + case 103://new + case 104://new + case 105://new + case 106://new + case 107://new + case 108://new + case 109://new + case 110://new + case 111://new + case 112://new + case 113://new + case 114://new + case 115://new + case 116://new + case 117: + case 118://new + case 119://new + case 120://new + case 121://new + break; + default: + break; + } + } + + + + + + public override string ToString() + { + return Name; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public struct RelIndexHash + { + public MetaHash Name { get; set; } + public uint Offset { get; set; } + public uint Length { get; set; } + + public override string ToString() + { + return Name.ToString() + ", " + Offset.ToString() + ", " + Length.ToString(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public struct RelIndexString + { + public string Name { get; set; } + public uint Offset { get; set; } + public uint Length { get; set; } + + public override string ToString() + { + return Name + ", " + Offset.ToString() + ", " + Length.ToString(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class RelData + { + public MetaHash NameHash { get; set; } + public string Name { get; set; } + public uint Offset { get; set; } + public uint Length { get; set; } + public byte[] Data { get; set; } + + public override string ToString() + { + string ol= ", " + Offset.ToString() + ", " + Length.ToString(); + if (!string.IsNullOrEmpty(Name)) return Name + ol; + return NameHash.ToString() + ol; + } + } + +} diff --git a/GameFiles/FileTypes/Stats.cs b/GameFiles/FileTypes/Stats.cs new file mode 100644 index 0000000..09bacf7 --- /dev/null +++ b/GameFiles/FileTypes/Stats.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + public static class StatsNames + { + public static Dictionary Index = new Dictionary(); + private static object syncRoot = new object(); + + public static volatile bool FullIndexBuilt = false; + + public static void Clear() + { + lock (syncRoot) + { + Index.Clear(); + } + } + + public static bool Ensure(string str) + { + uint hash = JenkHash.GenHash(str); + if (hash == 0) return true; + lock (syncRoot) + { + if (!Index.ContainsKey(hash)) + { + Index.Add(hash, str); + return false; + } + } + return true; + } + + public static bool Ensure(string str, uint hash) + { + if (hash == 0) return true; + lock (syncRoot) + { + if (!Index.ContainsKey(hash)) + { + Index.Add(hash, str); + return false; + } + } + return true; + } + + public static string GetString(uint hash) + { + string res; + lock (syncRoot) + { + if (!Index.TryGetValue(hash, out res)) + { + res = hash.ToString(); + } + } + return res; + } + public static string TryGetString(uint hash) + { + string res; + lock (syncRoot) + { + if (!Index.TryGetValue(hash, out res)) + { + res = string.Empty; + } + } + return res; + } + + } + + + +} diff --git a/GameFiles/FileTypes/YbnFile.cs b/GameFiles/FileTypes/YbnFile.cs new file mode 100644 index 0000000..3e86c68 --- /dev/null +++ b/GameFiles/FileTypes/YbnFile.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YbnFile : GameFile, PackedFile + { + public Bounds Bounds { get; set; } + + public YbnFile() : base(null, GameFileType.Ybn) + { + } + public YbnFile(RpfFileEntry entry) : base(entry, GameFileType.Ybn) + { + } + + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + + Bounds = rd.ReadBlock(); + + Bounds.OwnerName = entry.Name; + + Loaded = true; + } + } +} diff --git a/GameFiles/FileTypes/YcdFile.cs b/GameFiles/FileTypes/YcdFile.cs new file mode 100644 index 0000000..fc347c0 --- /dev/null +++ b/GameFiles/FileTypes/YcdFile.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YcdFile : GameFile, PackedFile + { + public ClipDictionary ClipDictionary { get; set; } + + public Dictionary ClipMap { get; set; } + + public YcdFile() : base(null, GameFileType.Ycd) + { + } + public YcdFile(RpfFileEntry entry) : base(entry, GameFileType.Ycd) + { + } + + + public void Load(byte[] data, RpfFileEntry entry) + { + //Name = entry.Name; + //Hash = entry.ShortNameHash; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + + ClipDictionary = rd.ReadBlock(); + + ClipMap = new Dictionary(); + if ((ClipDictionary != null) && (ClipDictionary.Clips != null) && (ClipDictionary.Clips.data_items != null)) + { + foreach (var cme in ClipDictionary.Clips.data_items) + { + if (cme != null) + { + ClipMap[cme.Hash] = cme; + } + } + } + + + } + } +} diff --git a/GameFiles/FileTypes/YddFile.cs b/GameFiles/FileTypes/YddFile.cs new file mode 100644 index 0000000..b532ba1 --- /dev/null +++ b/GameFiles/FileTypes/YddFile.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] public class YddFile : GameFile, PackedFile + { + //public DrawableDictionary DrawableDict { get; set; } + + public Dictionary Dict { get; set; } + public Drawable[] Drawables { get; set; } + + public YddFile() : base(null, GameFileType.Ydd) + { + } + public YddFile(RpfFileEntry entry) : base(entry, GameFileType.Ydd) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + DrawableDictionary DrawableDict = rd.ReadBlock(); + + //MemoryUsage = 0; //uses decompressed filesize now... + //if (DrawableDict != null) + //{ + // MemoryUsage += DrawableDict.MemoryUsage; + //} + + if ((DrawableDict != null) && + (DrawableDict.Drawables != null) && + (DrawableDict.Drawables.data_items != null) && + (DrawableDict.Hashes != null)) + { + Dict = new Dictionary(); + var drawables = DrawableDict.Drawables.data_items; + var hashes = DrawableDict.Hashes; + for (int i = 0; (i < drawables.Length) && (i < hashes.Length); i++) + { + var drawable = drawables[i]; + var hash = hashes[i]; + Dict[hash] = drawable; + drawable.Owner = this; + } + + + for (int i = 0; (i < drawables.Length) && (i < hashes.Length); i++) + { + var drawable = drawables[i]; + var hash = hashes[i]; + if ((drawable.Name == null) || (drawable.Name.EndsWith("#dd"))) + { + string hstr = JenkIndex.TryGetString(hash); + if (!string.IsNullOrEmpty(hstr)) + { + drawable.Name = hstr; + } + else + { } + } + } + + Drawables = Dict.Values.ToArray(); + + } + + Loaded = true; + + } + + } +} diff --git a/GameFiles/FileTypes/YdrFile.cs b/GameFiles/FileTypes/YdrFile.cs new file mode 100644 index 0000000..900646d --- /dev/null +++ b/GameFiles/FileTypes/YdrFile.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YdrFile : GameFile, PackedFile + { + public Drawable Drawable { get; set; } + + public YdrFile() : base(null, GameFileType.Ydr) + { + } + public YdrFile(RpfFileEntry entry) : base(entry, GameFileType.Ydr) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + //MemoryUsage = 0; + + try + { + Drawable = rd.ReadBlock(); + Drawable.Owner = this; + //MemoryUsage += Drawable.MemoryUsage; //uses decompressed filesize now... + } + catch (Exception ex) + { + string err = ex.ToString(); + } + + Loaded = true; + + } + + + } + + + + + +} diff --git a/GameFiles/FileTypes/YftFile.cs b/GameFiles/FileTypes/YftFile.cs new file mode 100644 index 0000000..5c2d01b --- /dev/null +++ b/GameFiles/FileTypes/YftFile.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YftFile : GameFile, PackedFile + { + public FragType Fragment { get; set; } + + public YftFile() : base(null, GameFileType.Yft) + { + } + public YftFile(RpfFileEntry entry) : base(entry, GameFileType.Yft) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + Fragment = rd.ReadBlock(); + + if (Fragment.Drawable != null) + { + Fragment.Drawable.Owner = this; + } + if (Fragment.Unknown_F8h_Data != null) + { + Fragment.Unknown_F8h_Data.Owner = this; + } + + Loaded = true; + } + + + } +} diff --git a/GameFiles/FileTypes/YmapFile.cs b/GameFiles/FileTypes/YmapFile.cs new file mode 100644 index 0000000..02da75d --- /dev/null +++ b/GameFiles/FileTypes/YmapFile.cs @@ -0,0 +1,1359 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapFile : GameFile, PackedFile + { + + public Meta Meta { get; set; } + public PsoFile Pso { get; set; } + public RbfFile Rbf { get; set; } + + public CMapData _CMapData; + + public CMapData CMapData { get { return _CMapData; } set { _CMapData = value; } } + public CEntityDef[] CEntityDefs { get; set; } + public CMloInstanceDef[] CMloInstanceDefs { get; set; } + public CCarGen[] CCarGens { get; set; } + public CTimeCycleModifier[] CTimeCycleModifiers { get; set; } + public MetaHash[] physicsDictionaries { get; set; } + + public Unk_975711773[] CBoxOccluders { get; set; } + public Unk_2741784237[] COccludeModels { get; set; } + + + public string[] Strings { get; set; } + public YmapEntityDef[] AllEntities; + public YmapEntityDef[] RootEntities; + + public YmapFile[] ChildYmaps = null; + public bool MergedWithParent = false; + + public YmapGrassInstanceBatch[] GrassInstanceBatches { get; set; } + public YmapPropInstanceBatch[] PropInstanceBatches { get; set; } + + public YmapDistantLODLights DistantLODLights { get; set; } + + public YmapTimeCycleModifier[] TimeCycleModifiers { get; set; } + + public YmapCarGen[] CarGenerators { get; set; } + + public YmapBoxOccluder[] BoxOccluders { get; set; } + public YmapOccludeModel[] OccludeModels { get; set; } + + + //fields used by the editor: + public bool HasChanged { get; set; } = false; + public List SaveWarnings = null; + + + + + public YmapFile() : base(null, GameFileType.Ymap) + { + } + public YmapFile(RpfFileEntry entry) : base(entry, GameFileType.Ymap) + { + RpfFileEntry = entry; + } + + public void Load(byte[] data) + { + //direct load from a raw, compressed ymap file (openIV-compatible format) + + RpfResourceFileEntry resentry = new RpfResourceFileEntry(); + + //hopefully this format has an RSC7 header... + uint rsc7 = BitConverter.ToUInt32(data, 0); + if (rsc7 == 0x37435352) //RSC7 header present! + { + int version = BitConverter.ToInt32(data, 4); + resentry.SystemFlags = BitConverter.ToUInt32(data, 8); + resentry.GraphicsFlags = BitConverter.ToUInt32(data, 12); + if (data.Length > 16) + { + int newlen = data.Length - 16; //trim the header from the data passed to the next step. + byte[] newdata = new byte[newlen]; + Buffer.BlockCopy(data, 16, newdata, 0, newlen); + data = newdata; + } + else + { + data = null; //shouldn't happen... empty.. + } + } + else + { + //direct load from file without the rpf header.. + //assume it's in resource meta format + resentry.SystemFlags = RpfResourceFileEntry.GetFlagsFromSize(data.Length, 0); + resentry.GraphicsFlags = RpfResourceFileEntry.GetFlagsFromSize(0, 2); //graphics type 2 for ymap + } + + var oldresentry = RpfFileEntry as RpfResourceFileEntry; + if (oldresentry != null) //update the existing entry with the new one + { + oldresentry.SystemFlags = resentry.SystemFlags; + oldresentry.GraphicsFlags = resentry.GraphicsFlags; + resentry.Name = oldresentry.Name; + resentry.NameHash = oldresentry.NameHash; + resentry.NameLower = oldresentry.NameLower; + resentry.ShortNameHash = oldresentry.ShortNameHash; + } + else + { + RpfFileEntry = resentry; //just stick it in there for later... + } + + data = ResourceBuilder.Decompress(data); + + + Load(data, resentry); + + Loaded = true; + } + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + NonMetaLoad(data); + return; + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + Meta = rd.ReadBlock(); + + + + CMapData = MetaTypes.GetTypedData(Meta, MetaName.CMapData); + + + + Strings = MetaTypes.GetStrings(Meta); + if (Strings != null) + { + foreach (string str in Strings) + { + JenkIndex.Ensure(str); //just shove them in there + } + } + + physicsDictionaries = MetaTypes.GetHashArray(Meta, CMapData.physicsDictionaries); + + + EnsureEntities(Meta); //load all the entity data and create the YmapEntityDefs + + EnsureInstances(Meta); + + EnsureLodLights(Meta); + + EnsureDistantLODLights(Meta); + + EnsureTimeCycleModifiers(Meta); + + EnsureCarGens(Meta); + + EnsureBoxOccluders(Meta); + + EnsureOccludeModels(Meta); + + EnsureContainerLods(Meta); + + + #region data block test and old code + + //foreach (var block in Meta.DataBlocks) + //{ + // switch (block.StructureNameHash) + // { + // case MetaName.STRING: + // case MetaName.POINTER: + // case MetaName.HASH: + // case MetaName.UINT: + // case MetaName.VECTOR3: //distant lod lights uses this + // case MetaName.CMapData: + // case MetaName.CEntityDef: + // case MetaName.CTimeCycleModifier: //these sections are handled already + // case MetaName.CCarGen: + // case MetaName.CLightAttrDef: + // case MetaName.CMloInstanceDef: + // case MetaName.CExtensionDefDoor: + // case MetaName.CExtensionDefLightEffect: + // case MetaName.CExtensionDefSpawnPointOverride: + // case MetaName.rage__fwGrassInstanceListDef: //grass instance buffer + // case MetaName.rage__fwGrassInstanceListDef__InstanceData: //grass instance buffer data + // break; + // case MetaName.PhVerletClothCustomBounds: //these sections still todo.. + // case MetaName.SectionUNKNOWN1: + // case MetaName.SectionUNKNOWN5://occlusion vertex data container + // case MetaName.SectionUNKNOWN7://occlusion related? + // break; + // case (MetaName)17: //vertex data - occlusion related - SectionUNKNOWN5 + // break; + // case (MetaName)33: //what is this? maybe lodlights related + // break; + // default: + // break; + // } + //} + + + + //MetaTypes.ParseMetaData(Meta); + + //string shortname = resentry.Name.Substring(0, resentry.Name.LastIndexOf('.')); + //uint namehash = JenkHash.GenHash(shortname); + + + + + + //CLightAttrDefs = MetaTypes.GetTypedDataArray(Meta, MetaName.CLightAttrDef); + //if (CLightAttrDefs != null) + //{ } + + + //var unk5s = MetaTypes.GetTypedDataArray(Meta, MetaName.SectionUNKNOWN5); + //if (unk5s != null) //used in occlusion ymaps + //{ + // foreach (var unk5 in unk5s) + // { + // if ((unk5.verts.Ptr > 0) && (unk5.verts.Ptr <= (ulong)Meta.DataBlocks.Length)) + // { + // var indicesoffset = unk5.Unk_853977995; + // var datablock = Meta.DataBlocks[((int)unk5.verts.Ptr) - 1]; + // if (datablock != null) + // { }//vertex data... occlusion mesh? + // } + // } + //} + + //var unk7s = MetaTypes.GetTypedDataArray(Meta, MetaName.SectionUNKNOWN7); + //if (unk7s != null) + //{ } //used in occlusion ymaps + + //var unk10s = MetaTypes.GetTypedDataArray(Meta, MetaName.SectionUNKNOWN10); + //if (unk10s != null) + //{ } //entity pointer array.. + + //CDoors = MetaTypes.GetTypedDataArray(Meta, MetaName.CExtensionDefDoor); + //if (CDoors != null) + //{ } //needs work - doors can be different types? not enough bytes for one + + //CExtLightEffects = MetaTypes.GetTypedDataArray(Meta, MetaName.CExtensionDefLightEffect); + //if (CExtLightEffects != null) + //{ } + + //CSpawnOverrides = MetaTypes.GetTypedDataArray(Meta, MetaName.CExtensionDefSpawnPointOverride); + //if (CSpawnOverrides != null) + //{ } + + #endregion + } + + + + private void NonMetaLoad(byte[] data) + { + //non meta not supported yet! but see what's in there... + MemoryStream ms = new MemoryStream(data); + if (RbfFile.IsRBF(ms)) + { + var Rbf = new RbfFile(); + Rbf.Load(ms); + } + else if (PsoFile.IsPSO(ms)) + { + var Pso = new PsoFile(); + Pso.Load(ms); + //PsoTypes.EnsurePsoTypes(Pso); + } + else + { + } + + } + + + + private void EnsureEntities(Meta Meta) + { + //CMloInstanceDefs = MetaTypes.ConvertDataArray(Meta, MetaName.CMloInstanceDef, CMapData.entities); + CMloInstanceDefs = MetaTypes.GetTypedDataArray(Meta, MetaName.CMloInstanceDef); + if (CMloInstanceDefs != null) + { } + + var eptrs = MetaTypes.GetPointerArray(Meta, CMapData.entities); + //CEntityDefs = MetaTypes.ConvertDataArray(Meta, MetaName.CEntityDef, CMapData.entities); + CEntityDefs = MetaTypes.GetTypedDataArray(Meta, MetaName.CEntityDef); + if (CEntityDefs != null) + { } + + + + + int instcount = 0; + if (CEntityDefs != null) instcount += CEntityDefs.Length; + if (CMloInstanceDefs != null) instcount += CMloInstanceDefs.Length; + + if (instcount > 0) + { + + //build the entity hierarchy. + List roots = new List(instcount); + List alldefs = new List(instcount); + + if (CEntityDefs != null) + { + for (int i = 0; i < CEntityDefs.Length; i++) + { + YmapEntityDef d = new YmapEntityDef(this, i, ref CEntityDefs[i]); + alldefs.Add(d); + } + } + if (CMloInstanceDefs != null) + { + for (int i = 0; i < CMloInstanceDefs.Length; i++) + { + YmapEntityDef d = new YmapEntityDef(this, i, ref CMloInstanceDefs[i]); + alldefs.Add(d); + } + } + + + for (int i = 0; i < alldefs.Count; i++) + { + YmapEntityDef d = alldefs[i]; + int pind = d.CEntityDef.parentIndex; + bool isroot = false; + if ((pind < 0) || (pind >= alldefs.Count) || (pind >= i)) //index check? might be a problem + { + isroot = true; + } + else + { + YmapEntityDef p = alldefs[pind]; + if ((p.CEntityDef.lodLevel <= d.CEntityDef.lodLevel) || + ((p.CEntityDef.lodLevel == Unk_1264241711.LODTYPES_DEPTH_ORPHANHD) && + (d.CEntityDef.lodLevel != Unk_1264241711.LODTYPES_DEPTH_ORPHANHD))) + { + isroot = true; + p = null; + } + } + + if (isroot) + { + roots.Add(d); + } + else + { + YmapEntityDef p = alldefs[pind]; + p.AddChild(d); + } + } + for (int i = 0; i < alldefs.Count; i++) + { + alldefs[i].ChildListToArray(); + } + + AllEntities = alldefs.ToArray(); + RootEntities = roots.ToArray(); + + + foreach (var ent in AllEntities) + { + ent.Extensions = MetaTypes.GetExtensions(Meta, ent.CEntityDef.extensions); + } + } + + } + + private void EnsureInstances(Meta Meta) + { + if (CMapData.instancedData.GrassInstanceList.Count1 != 0) + { + rage__fwGrassInstanceListDef[] batches = MetaTypes.ConvertDataArray(Meta, MetaName.rage__fwGrassInstanceListDef, CMapData.instancedData.GrassInstanceList); + YmapGrassInstanceBatch[] gbatches = new YmapGrassInstanceBatch[batches.Length]; + for (int i = 0; i < batches.Length; i++) + { + var batch = batches[i]; + rage__fwGrassInstanceListDef__InstanceData[] instdatas = MetaTypes.ConvertDataArray(Meta, MetaName.rage__fwGrassInstanceListDef__InstanceData, batch.InstanceList); + YmapGrassInstanceBatch gbatch = new YmapGrassInstanceBatch(); + gbatch.Ymap = this; + gbatch.Batch = batch; + gbatch.Instances = instdatas; + gbatch.Position = (batch.BatchAABB.min.XYZ() + batch.BatchAABB.max.XYZ()) * 0.5f; + gbatch.Radius = (batch.BatchAABB.max.XYZ() - gbatch.Position).Length(); + gbatch.AABBMin = (batch.BatchAABB.min.XYZ()); + gbatch.AABBMax = (batch.BatchAABB.max.XYZ()); + gbatches[i] = gbatch; + } + GrassInstanceBatches = gbatches; + } + if (CMapData.instancedData.PropInstanceList.Count1 != 0) + { + } + } + + private void EnsureLodLights(Meta Meta) + { + //TODO! + if (CMapData.LODLightsSOA.direction.Count1 != 0) + { + } + } + + private void EnsureDistantLODLights(Meta Meta) + { + if (CMapData.DistantLODLightsSOA.position.Count1 != 0) + { + DistantLODLights = new YmapDistantLODLights(); + DistantLODLights.Ymap = this; + DistantLODLights.CDistantLODLight = CMapData.DistantLODLightsSOA; + DistantLODLights.colours = MetaTypes.GetUintArray(Meta, CMapData.DistantLODLightsSOA.RGBI); + DistantLODLights.positions = MetaTypes.ConvertDataArray(Meta, MetaName.VECTOR3, CMapData.DistantLODLightsSOA.position); + DistantLODLights.CalcBB(); + } + } + + private void EnsureTimeCycleModifiers(Meta Meta) + { + CTimeCycleModifiers = MetaTypes.ConvertDataArray(Meta, MetaName.CTimeCycleModifier, CMapData.timeCycleModifiers); + if (CTimeCycleModifiers != null) + { + TimeCycleModifiers = new YmapTimeCycleModifier[CTimeCycleModifiers.Length]; + for (int i = 0; i < CTimeCycleModifiers.Length; i++) + { + YmapTimeCycleModifier tcm = new YmapTimeCycleModifier(); + tcm.Ymap = this; + tcm.CTimeCycleModifier = CTimeCycleModifiers[i]; + tcm.BBMin = tcm.CTimeCycleModifier.minExtents; + tcm.BBMax = tcm.CTimeCycleModifier.maxExtents; + TimeCycleModifiers[i] = tcm; + } + } + } + + private void EnsureCarGens(Meta Meta) + { + + CCarGens = MetaTypes.ConvertDataArray(Meta, MetaName.CCarGen, CMapData.carGenerators); + if (CCarGens != null) + { + //string str = MetaTypes.GetTypesInitString(resentry, Meta); //to generate structinfos and enuminfos + CarGenerators = new YmapCarGen[CCarGens.Length]; + for (int i = 0; i < CCarGens.Length; i++) + { + CarGenerators[i] = new YmapCarGen(this, CCarGens[i]); + } + } + } + + private void EnsureBoxOccluders(Meta meta) + { + CBoxOccluders = MetaTypes.ConvertDataArray(Meta, (MetaName)975711773, CMapData.boxOccluders); + if (CBoxOccluders != null) + { + BoxOccluders = new YmapBoxOccluder[CBoxOccluders.Length]; + for (int i = 0; i < CBoxOccluders.Length; i++) + { + BoxOccluders[i] = new YmapBoxOccluder(this, CBoxOccluders[i]); + } + } + } + + private void EnsureOccludeModels(Meta meta) + { + COccludeModels = MetaTypes.ConvertDataArray(Meta, (MetaName)2741784237, CMapData.occludeModels); + if (COccludeModels != null) + { + OccludeModels = new YmapOccludeModel[COccludeModels.Length]; + for (int i = 0; i < COccludeModels.Length; i++) + { + OccludeModels[i] = new YmapOccludeModel(this, COccludeModels[i]); + } + } + } + + private void EnsureContainerLods(Meta meta) + { + + //TODO: containerLods + if (CMapData.containerLods.Count1 > 0) + { + //string str = MetaTypes.GetTypesInitString(Meta); //to generate structinfos and enuminfos + + + } + + } + + + public void BuildCEntityDefs() + { + //recreates the CEntityDefs array from AllEntities. + if (AllEntities == null) + { + CEntityDefs = null; + return; + } + + int count = AllEntities.Length; + CEntityDefs = new CEntityDef[count]; + for (int i = 0; i < count; i++) + { + CEntityDefs[i] = AllEntities[i].CEntityDef; + } + + //TODO: MloInstanceDefs! + + } + public void BuildCCarGens() + { + //recreates the CCarGens array from CarGenerators. + if (CarGenerators == null) + { + CCarGens = null; + return; + } + + int count = CarGenerators.Length; + CCarGens = new CCarGen[count]; + for (int i = 0; i < count; i++) + { + CCarGens[i] = CarGenerators[i].CCarGen; + } + } + + public byte[] Save() + { + //direct save to a raw, compressed ymap file (openIV-compatible format) + + + //since Ymap object contents have been modified, need to recreate the arrays which are what is saved. + BuildCEntityDefs(); + BuildCCarGens(); + + + //TODO: + //BuildInstances(); + //BuildLodLights(); + //BuildDistantLodLights(); + //BuildTimecycleModifiers(); //already being saved - update them.. + //BuildBoxOccluders(); + //BuildOccludeModels(); + //BuildContainerLods(); + + + + MetaBuilder mb = new MetaBuilder(); + + + var mdb = mb.EnsureBlock(MetaName.CMapData); + + CMapData mapdata = CMapData; + + + if (CEntityDefs != null) + { + for (int i = 0; i < CEntityDefs.Length; i++) + { + var yent = AllEntities[i]; //save the extensions.. + CEntityDefs[i].extensions = mb.AddWrapperArrayPtr(yent.Extensions); + } + } + + mapdata.entities = mb.AddItemPointerArrayPtr(MetaName.CEntityDef, CEntityDefs); + + mapdata.timeCycleModifiers = mb.AddItemArrayPtr(MetaName.CTimeCycleModifier, CTimeCycleModifiers); + + mapdata.physicsDictionaries = mb.AddHashArrayPtr(physicsDictionaries); + + mapdata.carGenerators = mb.AddItemArrayPtr(MetaName.CCarGen, CCarGens); + + if (CMloInstanceDefs != null) + { + LogSaveWarning("CMloInstanceDefs were present, may not save properly. (TODO!)"); + } + + //clear everything out for now - TODO: fix + if (mapdata.containerLods.Count1 != 0) LogSaveWarning("containerLods were not saved. (TODO!)"); + if (mapdata.occludeModels.Count1 != 0) LogSaveWarning("occludeModels were not saved. (TODO!)"); + if (mapdata.boxOccluders.Count1 != 0) LogSaveWarning("boxOccluders were not saved. (TODO!)"); + if (mapdata.instancedData.GrassInstanceList.Count1 != 0) LogSaveWarning("instancedData.GrassInstanceList was not saved. (TODO!)"); + if (mapdata.instancedData.PropInstanceList.Count1 != 0) LogSaveWarning("instancedData.PropInstanceList was not saved. (TODO!)"); + if (mapdata.LODLightsSOA.direction.Count1 != 0) LogSaveWarning("LODLightsSOA was not saved. (TODO!)"); + if (mapdata.DistantLODLightsSOA.position.Count1 != 0) LogSaveWarning("DistantLODLightsSOA was not saved. (TODO!)"); + mapdata.containerLods = new Array_Structure(); + mapdata.occludeModels = new Array_Structure(); + mapdata.boxOccluders = new Array_Structure(); + mapdata.instancedData = new rage__fwInstancedMapData(); + mapdata.LODLightsSOA = new CLODLight(); + mapdata.DistantLODLightsSOA = new CDistantLODLight(); + + + + var block = new CBlockDesc(); + block.name = mb.AddStringPtr(Path.GetFileNameWithoutExtension(Name)); + block.exportedBy = mb.AddStringPtr("CodeWalker"); + block.time = mb.AddStringPtr(DateTime.UtcNow.ToString("dd MMMM yyyy HH:mm")); + + mapdata.block = block; + + + string name = Path.GetFileNameWithoutExtension(Name); + uint nameHash = JenkHash.GenHash(name); + mapdata.name = new MetaHash(nameHash);//make sure name is upto date... + + + mb.AddItem(MetaName.CMapData, mapdata); + + + + //make sure all the relevant structure and enum infos are present. + mb.AddStructureInfo(MetaName.rage__fwInstancedMapData); + mb.AddStructureInfo(MetaName.CLODLight); + mb.AddStructureInfo(MetaName.CDistantLODLight); + mb.AddStructureInfo(MetaName.CBlockDesc); + mb.AddStructureInfo(MetaName.CMapData); + mb.AddStructureInfo(MetaName.CEntityDef); + mb.AddStructureInfo(MetaName.CTimeCycleModifier); + if ((CCarGens != null) && (CCarGens.Length > 0)) + { + mb.AddStructureInfo(MetaName.CCarGen); + } + + mb.AddEnumInfo((MetaName)1264241711); //LODTYPES_ + mb.AddEnumInfo((MetaName)648413703); //PRI_ + + + Meta meta = mb.GetMeta(); + + byte[] data = ResourceBuilder.Build(meta, 2); //ymap is version 2... + + + return data; + } + + private void LogSaveWarning(string w) + { + if (SaveWarnings == null) SaveWarnings = new List(); + SaveWarnings.Add(w); + } + + + + + public void EnsureChildYmaps(GameFileCache gfc) + { + if (ChildYmaps == null) + { + //no children here... look for child ymap.... + var node = gfc.GetMapNode(RpfFileEntry.ShortNameHash); + if ((node != null) && (node.Children != null) && (node.Children.Length > 0)) + { + ChildYmaps = new YmapFile[node.Children.Length]; + for (int i = 0; i < ChildYmaps.Length; i++) + { + var chash = node.Children[i].Name; + ChildYmaps[i] = gfc.GetYmap(chash); + if (ChildYmaps[i] == null) + { + //couldn't find child ymap.. + } + } + } + } + + + bool needupd = false; + if (ChildYmaps != null) + { + for (int i = 0; i < ChildYmaps.Length; i++) + { + var cmap = ChildYmaps[i]; + if (cmap == null) continue; //nothing here.. + if (!cmap.Loaded) + { + //ChildYmaps[i] = gfc.GetYmap(cmap.Hash); //incase no load was requested. + cmap = gfc.GetYmap(cmap.Key.Hash); + ChildYmaps[i] = cmap; + } + if ((cmap.Loaded) && (!cmap.MergedWithParent)) + { + needupd = true; + } + } + } + + if ((ChildYmaps != null) && needupd) + { + List newroots = new List(RootEntities); + for (int i = 0; i < ChildYmaps.Length; i++) + { + var cmap = ChildYmaps[i]; + if (cmap == null) continue; //nothing here.. + //cmap.EnsureChildYmaps(); + if ((cmap.Loaded) && (!cmap.MergedWithParent)) + { + cmap.MergedWithParent = true; + if (cmap.RootEntities != null) + { + foreach (var rcent in cmap.RootEntities) + { + int pind = rcent.CEntityDef.parentIndex; + if (pind < 0) + { + if (rcent.CEntityDef.lodLevel != Unk_1264241711.LODTYPES_DEPTH_ORPHANHD) + { + } + //pind = 0; + } + if ((pind >= 0) && (pind < AllEntities.Length)) + { + var pentity = AllEntities[pind]; + pentity.AddChild(rcent); + } + else + { + //TODO: fix this!! + //newroots.Add(rcent); //not sure this is the right approach. + //////rcent.Owner = this; + } + } + } + } + } + if (AllEntities != null) + { + for (int i = 0; i < AllEntities.Length; i++) + { + AllEntities[i].ChildListToMergedArray(); + } + } + + RootEntities = newroots.ToArray(); + } + + + } + + + + + public void AddEntity(YmapEntityDef ent) + { + //used by the editor to add to the ymap. + + List allents = new List(); + if (AllEntities != null) allents.AddRange(AllEntities); + ent.Index = allents.Count; + ent.Ymap = this; + allents.Add(ent); + AllEntities = allents.ToArray(); + + + if ((ent.Parent == null) || (ent.Parent.Ymap != this)) + { + //root entity, add to roots. + + List rootents = new List(); + if (RootEntities != null) rootents.AddRange(RootEntities); + rootents.Add(ent); + RootEntities = rootents.ToArray(); + } + + HasChanged = true; + } + + public bool RemoveEntity(YmapEntityDef ent) + { + //used by the editor to remove from the ymap. + if (ent == null) return false; + + var res = true; + + int idx = ent.Index; + List newAllEntities = new List(); + List newRootEntities = new List(); + + for (int i = 0; i < AllEntities.Length; i++) + { + var oent = AllEntities[i]; + oent.Index = newAllEntities.Count; + if (oent != ent) newAllEntities.Add(oent); + else if (i != idx) + { + res = false; //indexes didn't match.. this shouldn't happen! + } + } + for (int i = 0; i < RootEntities.Length; i++) + { + var oent = RootEntities[i]; + if (oent != ent) newRootEntities.Add(oent); + } + + if ((AllEntities.Length == newAllEntities.Count) || (RootEntities.Length == newRootEntities.Count)) + { + res = false; + } + + AllEntities = newAllEntities.ToArray(); + RootEntities = newRootEntities.ToArray(); + + HasChanged = true; + + return res; + } + + + public void AddCarGen(YmapCarGen cargen) + { + List cargens = new List(); + if (CarGenerators != null) cargens.AddRange(CarGenerators); + cargen.Ymap = this; + cargens.Add(cargen); + CarGenerators = cargens.ToArray(); + + HasChanged = true; + } + + public bool RemoveCarGen(YmapCarGen cargen) + { + if (cargen == null) return false; + + List newcargens = new List(); + + if (CarGenerators != null) + { + for (int i = 0; i < CarGenerators.Length; i++) + { + var cg = CarGenerators[i]; + if (cg != cargen) + { + newcargens.Add(cg); + } + } + if (newcargens.Count == CarGenerators.Length) + { + return false; //nothing removed... wasn't present? + } + } + + + CarGenerators = newcargens.ToArray(); + + HasChanged = true; + + return true; + } + + + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapEntityDef + { + public Archetype Archetype { get; set; } //cached by GameFileCache on loading... + public Vector3 BBMin;//oriented archetype AABBmin + public Vector3 BBMax;//oriented archetype AABBmax + public Vector3 BSCenter; //oriented archetype BS center + public float BSRadius;//cached from archetype + + public CEntityDef _CEntityDef; + public CEntityDef CEntityDef { get { return _CEntityDef; } set { _CEntityDef = value; } } + private List ChildList { get; set; } + public YmapEntityDef[] Children { get; set; } + public YmapEntityDef[] ChildrenMerged;// { get; set; } + public Vector3 Position { get; set; } + public Quaternion Orientation { get; set; } + public Vector3 Scale { get; set; } + public bool IsMlo { get; set; } + public MloEntityData MloData { get; set; } + public YmapEntityDef MloParent { get; set; } + public MetaWrapper[] Extensions { get; set; } + + public bool ChildrenRendered; //used when rendering ymap mode to reduce LOD flashing... + + public int Index { get; set; } + public Vector3 CamRel; //used for rendering... + public float Distance; //used for rendering + public bool IsVisible; //used for rendering + public bool Rendered; //used for rendering + public bool ChildRendered; //used for rendering + public bool ChildrenVisible; //used for rendering + public bool ChildrenLoading; //used for rendering + public float LargestChildLodDist; //used for rendering + public YmapEntityDef Parent { get; set; } //used for rendering + public uint ParentGuid { get; set; } //used for rendering + public MetaHash ParentName { get; set; } //used for rendering + + public YmapFile Ymap { get; set; } + + public Vector3 PivotPosition = Vector3.Zero; + public Quaternion PivotOrientation = Quaternion.Identity; + public Vector3 WidgetPosition = Vector3.Zero; + public Quaternion WidgetOrientation = Quaternion.Identity; + + + public string Name + { + get + { + return _CEntityDef.archetypeName.ToString(); + } + } + + + public YmapEntityDef(YmapFile ymap, int index, ref CEntityDef def) + { + Ymap = ymap; + Index = index; + CEntityDef = def; + Scale = new Vector3(new Vector2(CEntityDef.scaleXY), CEntityDef.scaleZ); + Position = CEntityDef.position; + Orientation = new Quaternion(CEntityDef.rotation); + if (Orientation != Quaternion.Identity) + { + Orientation = Quaternion.Invert(Orientation); + } + IsMlo = false; + + UpdateWidgetPosition(); + UpdateWidgetOrientation(); + } + + public YmapEntityDef(YmapFile ymap, int index, ref CMloInstanceDef mlo) + { + Ymap = ymap; + Index = index; + CEntityDef = mlo.CEntityDef; + Scale = new Vector3(new Vector2(CEntityDef.scaleXY), CEntityDef.scaleZ); + Position = CEntityDef.position; + Orientation = new Quaternion(CEntityDef.rotation); + //if (Orientation != Quaternion.Identity) + //{ + // Orientation = Quaternion.Invert(Orientation); + //} + IsMlo = true; + + UpdateWidgetPosition(); + UpdateWidgetOrientation(); + } + + + public void SetArchetype(Archetype arch) + { + Archetype = arch; + if (Archetype != null) + { + float smax = Math.Max(Scale.X, Scale.Z); + BSRadius = Archetype.BSRadius * smax; + BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale; + if (Orientation == Quaternion.Identity) + { + BBMin = (Archetype.BBMin * Scale) + Position; + BBMax = (Archetype.BBMax * Scale) + Position; + } + else + { + BBMin = Position - BSRadius; + BBMax = Position + BSRadius; + ////not ideal: should transform all 8 corners! + } + + if (Archetype.IsMloArchetype) + { + //transform interior entities into world space... + var mlod = Archetype.MloData; + MloData = new MloEntityData(); + MloData.CreateYmapEntities(this, mlod); + + if (BSRadius == 0.0f) + { + BSRadius = CEntityDef.lodDist;//need something so it doesn't get culled... + } + } + + } + + } + + public void SetPosition(Vector3 pos) + { + if (MloParent != null) + { + //TODO: SetPosition for interior entities! + Position = pos; + } + else + { + Position = pos; + _CEntityDef.position = pos; + + if (Archetype != null) + { + BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale; + } + if ((Archetype != null) && (Orientation == Quaternion.Identity)) + { + BBMin = (Archetype.BBMin * Scale) + Position; + BBMax = (Archetype.BBMax * Scale) + Position; + } + else + { + BBMin = Position - (BSRadius); + BBMax = Position + (BSRadius); + ////not ideal: should transform all 8 corners! + } + + + + UpdateWidgetPosition(); + } + } + + public void SetOrientation(Quaternion ori) + { + Orientation = ori; + Quaternion qinv = Quaternion.Normalize(Quaternion.Invert(ori)); + _CEntityDef.rotation = new Vector4(qinv.X, qinv.Y, qinv.Z, qinv.W); + + if (Archetype != null) + { + BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale; + } + + UpdateWidgetPosition(); + UpdateWidgetOrientation(); + } + public void SetOrientationInv(Quaternion inv) + { + _CEntityDef.rotation = new Vector4(inv.X, inv.Y, inv.Z, inv.W); + Orientation = Quaternion.Normalize(Quaternion.Invert(inv)); + + if (Archetype != null) + { + BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale; + } + + UpdateWidgetPosition(); + UpdateWidgetOrientation(); + } + + public void SetScale(Vector3 s) + { + Scale = new Vector3(s.X, s.X, s.Z); + _CEntityDef.scaleXY = s.X; + _CEntityDef.scaleZ = s.Z; + if (Archetype != null) + { + float smax = Math.Max(Scale.X, Scale.Z); + BSRadius = Archetype.BSRadius * smax; + } + SetPosition(Position);//update the BB + } + + + + public void SetPivotPosition(Vector3 pos) + { + PivotPosition = pos; + + UpdateWidgetPosition(); + } + + public void SetPivotOrientation(Quaternion ori) + { + PivotOrientation = ori; + + UpdateWidgetOrientation(); + } + + + public void SetPositionFromWidget(Vector3 pos) + { + SetPosition(pos - Orientation.Multiply(PivotPosition)); + } + public void SetOrientationFromWidget(Quaternion ori) + { + var newori = Quaternion.Normalize(Quaternion.Multiply(ori, Quaternion.Invert(PivotOrientation))); + var newpos = WidgetPosition - newori.Multiply(PivotPosition); + SetOrientation(newori); + SetPosition(newpos); + } + public void SetPivotPositionFromWidget(Vector3 pos) + { + var orinv = Quaternion.Invert(Orientation); + SetPivotPosition(orinv.Multiply(pos - Position)); + } + public void SetPivotOrientationFromWidget(Quaternion ori) + { + var orinv = Quaternion.Invert(Orientation); + SetPivotOrientation(Quaternion.Multiply(orinv, ori)); + } + + + public void UpdateWidgetPosition() + { + WidgetPosition = Position + Orientation.Multiply(PivotPosition); + } + public void UpdateWidgetOrientation() + { + WidgetOrientation = Quaternion.Multiply(Orientation, PivotOrientation); + } + + + public void AddChild(YmapEntityDef c) + { + if (ChildList == null) + { + ChildList = new List(); + } + c.Parent = this; + c.ParentGuid = CEntityDef.guid; + c.ParentName = CEntityDef.archetypeName; + + ChildList.Add(c); + } + + public void ChildListToArray() + { + if (ChildList == null) return; + //if (Children == null) + //{ + Children = ChildList.ToArray(); + ChildrenMerged = Children;//include these by default in merged array + //} + //else + //{ + // List newc = new List(Children.Length + ChildList.Count); + // newc.AddRange(Children); + // newc.AddRange(ChildList); + // Children = newc.ToArray(); + //} + ChildList.Clear(); + ChildList = null; + } + public void ChildListToMergedArray() + { + if (ChildList == null) return; + if (ChildrenMerged == null) + { + ChildrenMerged = ChildList.ToArray(); + } + else + { + List newc = new List(ChildrenMerged.Length + ChildList.Count); + newc.AddRange(ChildrenMerged); + newc.AddRange(ChildList); + ChildrenMerged = newc.ToArray(); + } + ChildList.Clear(); + ChildList = null; + } + + public override string ToString() + { + return CEntityDef.ToString() + ((ChildList != null) ? (" (" + ChildList.Count.ToString() + " children) ") : " ") + CEntityDef.lodLevel.ToString(); + } + + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapGrassInstanceBatch + { + public Archetype Archetype { get; set; } //cached by GameFileCache on loading... + public rage__fwGrassInstanceListDef Batch { get; set; } + public rage__fwGrassInstanceListDef__InstanceData[] Instances { get; set; } + public Vector3 Position { get; set; } //calculated from AABB + public float Radius { get; set; } //calculated from AABB + public Vector3 AABBMin { get; set; } + public Vector3 AABBMax { get; set; } + public Vector3 CamRel; //used for rendering... + public float Distance; //used for rendering + public YmapFile Ymap { get; set; } + + public override string ToString() + { + return Batch.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapPropInstanceBatch + { + public YmapFile Ymap { get; set; } + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapDistantLODLights + { + public CDistantLODLight CDistantLODLight { get; set; } + public uint[] colours { get; set; } + public MetaVECTOR3[] positions { get; set; } + + public Vector3 BBMin { get; set; } + public Vector3 BBMax { get; set; } + public YmapFile Ymap { get; set; } + + public void CalcBB() + { + if (positions != null) + { + Vector3 min = new Vector3(float.MaxValue); + Vector3 max = new Vector3(float.MinValue); + for (int i = 0; i < positions.Length; i++) + { + var p = positions[i]; + Vector3 pv = p.ToVector3(); + min = Vector3.Min(min, pv); + max = Vector3.Max(max, pv); + } + BBMin = min; + BBMax = max; + } + + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapTimeCycleModifier + { + public CTimeCycleModifier CTimeCycleModifier { get; set; } + public World.TimecycleMod TimeCycleModData { get; set; } + + public Vector3 BBMin { get; set; } + public Vector3 BBMax { get; set; } + + public YmapFile Ymap { get; set; } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapCarGen + { + public CCarGen _CCarGen; + public CCarGen CCarGen { get { return _CCarGen; } set { _CCarGen = value; } } + + public Vector3 Position { get; set; } + public Quaternion Orientation { get; set; } + public Vector3 BBMin { get; set; } + public Vector3 BBMax { get; set; } + + public YmapFile Ymap { get; set; } + + + public YmapCarGen(YmapFile ymap, CCarGen cargen) + { + float hlen = cargen.perpendicularLength * 0.5f; + Ymap = ymap; + CCarGen = cargen; + Position = cargen.position; + CalcOrientation(); + BBMin = new Vector3(-hlen); + BBMax = new Vector3(hlen); + } + + + public void CalcOrientation() + { + float angl = (float)Math.Atan2(_CCarGen.orientY, _CCarGen.orientX); + Orientation = Quaternion.RotationYawPitchRoll(0.0f, 0.0f, angl); + } + + public void SetPosition(Vector3 pos) + { + Position = pos; + _CCarGen.position = pos; + } + public void SetOrientation(Quaternion ori) + { + Orientation = ori; + + float len = Math.Max(_CCarGen.perpendicularLength * 1.5f, 5.0f); + Vector3 v = new Vector3(len, 0, 0); + Vector3 t = ori.Multiply(v); + + _CCarGen.orientX = t.X; + _CCarGen.orientY = t.Y; + } + public void SetScale(Vector3 scale) + { + float s = scale.X; + float hlen = s * 0.5f; + _CCarGen.perpendicularLength = s; + + BBMin = new Vector3(-hlen); + BBMax = new Vector3(hlen); + } + + public void SetLength(float length) + { + _CCarGen.perpendicularLength = length; + float hlen = length * 0.5f; + + BBMin = new Vector3(-hlen); + BBMax = new Vector3(hlen); + } + + public override string ToString() + { + return _CCarGen.carModel.ToString() + ", " + Position.ToString() + ", " + _CCarGen.popGroup.ToString() + ", " + _CCarGen.livery.ToString(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapOccludeModel + { + public Unk_2741784237 _OccludeModel; + public Unk_2741784237 OccludeModel { get { return _OccludeModel; } set { _OccludeModel = value; } } + + public YmapFile Ymap { get; set; } + + + public YmapOccludeModel(YmapFile ymap, Unk_2741784237 model) + { + Ymap = ymap; + _OccludeModel = model; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YmapBoxOccluder + { + public Unk_975711773 _Box; + public Unk_975711773 Box { get { return _Box; } set { _Box = value; } } + + public YmapFile Ymap { get; set; } + + public YmapBoxOccluder(YmapFile ymap, Unk_975711773 box) + { + Ymap = ymap; + _Box = box; + } + + } + +} diff --git a/GameFiles/FileTypes/YmfFile.cs b/GameFiles/FileTypes/YmfFile.cs new file mode 100644 index 0000000..1083bd7 --- /dev/null +++ b/GameFiles/FileTypes/YmfFile.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YmfFile : PackedFile + { + public RpfFileEntry FileEntry { get; set; } + + public Meta Meta { get; set; } + public PsoFile Pso { get; set; } + public RbfFile Rbf { get; set; } + + public YmfMapDataGroup[] MapDataGroups { get; set; } + public CImapDependency[] imapDependencies { get; set; } + public YmfImapDependency2[] imapDependencies2 { get; set; } + public YmfItypDependency2[] itypDependencies2 { get; set; } + public CHDTxdAssetBinding[] HDTxdAssetBindings { get; set; } + public YmfInterior[] Interiors { get; set; } + + public void Load(byte[] data, RpfFileEntry entry) + { + FileEntry = entry; + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + MemoryStream ms = new MemoryStream(data); + if (RbfFile.IsRBF(ms)) + { + Rbf = new RbfFile(); + Rbf.Load(ms); + + //x64j.rpf\\levels\\gta5\\_citye\\indust_01\\id1_props.rpf\\_manifest.ymf + //x64j.rpf\\levels\\gta5\\_citye\\indust_02\\id2_props.rpf\\_manifest.ymf + //x64q.rpf\\levels\\gta5\\_hills\\country_01\\cs1_railwyc.rpf\\_manifest.ymf + //all just HDTxd bindings + + return; + } + if (PsoFile.IsPSO(ms)) + { + Pso = new PsoFile(); + Pso.Load(ms); + + //PsoTypes.EnsurePsoTypes(Pso); + + ProcessPSO(); + + return; + } + else + { + + } + return; + } + + + + + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + Meta = rd.ReadBlock(); + + + + + + } + + + private void ProcessPSO() + { + + //See x64m.rpf\levels\gta5\_cityw\venice_01\venice_metadata.rpf\_manifest.ymf + //for TIMED YMAP stuff!!!! + //check CMapDataGroup.HoursOnOff + + + var d = PsoTypes.GetRootItem(Pso); + + MapDataGroups = PsoTypes.GetObjectArray(Pso, d.MapDataGroups); + + imapDependencies = PsoTypes.GetItemArray(Pso, d.imapDependencies); + + imapDependencies2 = PsoTypes.GetObjectArray(Pso, d.imapDependencies_2); + + itypDependencies2 = PsoTypes.GetObjectArray(Pso, d.itypDependencies_2); + + HDTxdAssetBindings = PsoTypes.GetItemArray(Pso, d.HDTxdBindingArray); + + Interiors = PsoTypes.GetObjectArray(Pso, d.Interiors); + + + } + + + public override string ToString() + { + return (FileEntry != null) ? FileEntry.Path : string.Empty; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YmfMapDataGroup : PsoClass + { + public CMapDataGroup DataGroup { get; set; } //ymap name + public MetaHash[] Bounds { get; set; } + public MetaHash[] WeatherTypes { get; set; } + public MetaHash Name { get; set; } + public ushort Flags { get; set; } + public uint HoursOnOff { get; set; } + + public override string ToString() + { + return DataGroup.ToString(); + } + + public override void Init(PsoFile pso, ref CMapDataGroup v) + { + DataGroup = v; + Bounds = PsoTypes.GetHashArray(pso, v.Bounds); + WeatherTypes = PsoTypes.GetHashArray(pso, v.WeatherTypes); + Name = v.Name; + Flags = v.Flags; + HoursOnOff = v.HoursOnOff; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YmfImapDependency2 : PsoClass + { + public CImapDependencies Dep { get; set; } + public MetaHash[] itypDepArray { get; set; }//ybn hashes? + + public override void Init(PsoFile pso, ref CImapDependencies v) + { + Dep = v; + itypDepArray = PsoTypes.GetHashArray(pso, v.itypDepArray); + } + + public override string ToString() + { + return Dep.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YmfItypDependency2 : PsoClass + { + public CItypDependencies Dep { get; set; } + public MetaHash[] itypDepArray { get; set; }//ytyp hashes? + + public override void Init(PsoFile pso, ref CItypDependencies v) + { + Dep = v; + itypDepArray = PsoTypes.GetHashArray(pso, v.itypDepArray); + } + + public override string ToString() + { + return Dep.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YmfInterior : PsoClass + { + public Unk_741495440 Interior { get; set; } + public MetaHash[] Bounds { get; set; }//ybn hashes? + + public override string ToString() + { + return Interior.ToString(); + } + + public override void Init(PsoFile pso, ref Unk_741495440 v) + { + Interior = v; + Bounds = PsoTypes.GetHashArray(pso, v.Bounds); + } + } + +} diff --git a/GameFiles/FileTypes/YmtFile.cs b/GameFiles/FileTypes/YmtFile.cs new file mode 100644 index 0000000..20e51c0 --- /dev/null +++ b/GameFiles/FileTypes/YmtFile.cs @@ -0,0 +1,372 @@ +using CodeWalker.World; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] public class YmtFile : GameFile, PackedFile + { + + public Meta Meta { get; set; } + public PsoFile Pso { get; set; } + public RbfFile Rbf { get; set; } + + public YmtFileFormat FileFormat { get; set; } = YmtFileFormat.Unknown; + public YmtFileContentType ContentType { get; set; } = YmtFileContentType.None; + + + public Dictionary CMapParentTxds { get; set; } + + public YmtScenarioPointManifest CScenarioPointManifest { get; set; } + + public MCScenarioPointRegion CScenarioPointRegion { get; set; } + public ScenarioRegion ScenarioRegion { get; set; } + + + + + //fields used by the editor: + public bool HasChanged { get; set; } = false; + public List SaveWarnings = null; + + public YmtFile() : base(null, GameFileType.Ymt) + { + } + public YmtFile(RpfFileEntry entry) : base(entry, GameFileType.Ymt) + { + } + + + + public void LoadRSC(byte[] data) + { + //direct load from a raw, compressed ymt resource file (openIV-compatible format) + + RpfResourceFileEntry resentry = new RpfResourceFileEntry(); + + //hopefully this format has an RSC7 header... + uint rsc7 = BitConverter.ToUInt32(data, 0); + if (rsc7 == 0x37435352) //RSC7 header present! + { + int version = BitConverter.ToInt32(data, 4); + resentry.SystemFlags = BitConverter.ToUInt32(data, 8); + resentry.GraphicsFlags = BitConverter.ToUInt32(data, 12); + if (data.Length > 16) + { + int newlen = data.Length - 16; //trim the header from the data passed to the next step. + byte[] newdata = new byte[newlen]; + Buffer.BlockCopy(data, 16, newdata, 0, newlen); + data = newdata; + } + else + { + data = null; //shouldn't happen... empty.. + } + } + else + { + //direct load from file without the rpf header.. + //assume it's in resource meta format + resentry.SystemFlags = RpfResourceFileEntry.GetFlagsFromSize(data.Length, 0); + resentry.GraphicsFlags = RpfResourceFileEntry.GetFlagsFromSize(0, 2); //graphics type 2 for ymt/meta + } + + var oldresentry = RpfFileEntry as RpfResourceFileEntry; + if (oldresentry != null) //update the existing entry with the new one + { + oldresentry.SystemFlags = resentry.SystemFlags; + oldresentry.GraphicsFlags = resentry.GraphicsFlags; + resentry.Name = oldresentry.Name; + resentry.NameHash = oldresentry.NameHash; + resentry.NameLower = oldresentry.NameLower; + resentry.ShortNameHash = oldresentry.ShortNameHash; + } + else + { + RpfFileEntry = resentry; //just stick it in there for later... + } + + data = ResourceBuilder.Decompress(data); + + + Load(data, resentry); + + //Loaded = true; + } + + + public void Load(byte[] data, RpfFileEntry entry) + { + RpfFileEntry = entry; + Name = entry.Name; + FilePath = Name; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry != null) + { + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + Meta = rd.ReadBlock(); + + var rootblock = Meta.GetRootBlock(); + if (rootblock != null) + { + if (rootblock.StructureNameHash == MetaName.CScenarioPointRegion) + { + LoadScenarioPointRegion(Meta, rootblock); + } + } + + Loaded = true; + return; + } + + + MemoryStream ms = new MemoryStream(data); + + if (RbfFile.IsRBF(ms)) + { + Rbf = new RbfFile(); + var rbfstruct = Rbf.Load(ms); + + if (rbfstruct.Name == "CMapParentTxds") + { + LoadMapParentTxds(rbfstruct); + } + + + + Loaded = true; + return; + } + if (PsoFile.IsPSO(ms)) + { + Pso = new PsoFile(); + Pso.Load(ms); + + //PsoTypes.EnsurePsoTypes(Pso); + + var root = PsoTypes.GetRootEntry(Pso); + if (root != null) + { + if (root.NameHash == MetaName.CScenarioPointManifest) + { + LoadScenarioPointManifest(Pso); + } + } + + + Loaded = true; + return; + } + else + { + + } + + + + + } + + + private void LoadMapParentTxds(RbfStructure rbfstruct) + { + FileFormat = YmtFileFormat.RBF; + ContentType = YmtFileContentType.MapParentTxds; + + CMapParentTxds = new Dictionary(); + //StringBuilder sblist = new StringBuilder(); + foreach(var child in rbfstruct.Children) + { + var childstruct = child as RbfStructure; + if ((childstruct != null) && (childstruct.Name == "txdRelationships")) + { + foreach (var txdrel in childstruct.Children) + { + var txdrelstruct = txdrel as RbfStructure; + if ((txdrelstruct != null) && (txdrelstruct.Name == "item")) + { + string parentstr = string.Empty; + string childstr = string.Empty; + foreach(var item in txdrelstruct.Children) + { + var itemstruct = item as RbfStructure; + if ((itemstruct != null)) + { + var strbytes = itemstruct.Children[0] as RbfBytes; + string thisstr = string.Empty; + if (strbytes != null) + { + thisstr = Encoding.ASCII.GetString(strbytes.Value).Replace("\0", ""); + } + switch (item.Name) + { + case "parent": + parentstr = thisstr; + break; + case "child": + childstr = thisstr; + break; + } + } + + } + if((!string.IsNullOrEmpty(parentstr)) && (!string.IsNullOrEmpty(childstr))) + { + if (!CMapParentTxds.ContainsKey(childstr)) + { + CMapParentTxds.Add(childstr, parentstr); + } + else + { + } + //sblist.AppendLine(childstr + ": " + parentstr); + } + } + } + } + } + //string alltxdmap = sblist.ToString(); + //if (!string.IsNullOrEmpty(alltxdmap)) + //{ + //} + + } + + private void LoadScenarioPointManifest(PsoFile pso) + { + FileFormat = YmtFileFormat.PSO; + ContentType = YmtFileContentType.ScenarioPointManifest; + + CScenarioPointManifest = new YmtScenarioPointManifest(); + CScenarioPointManifest.Load(pso); + + } + + private void LoadScenarioPointRegion(Meta meta, MetaDataBlock rootblock) + { + FileFormat = YmtFileFormat.RSC; + ContentType = YmtFileContentType.ScenarioPointRegion; + + var cdata = MetaTypes.ConvertData(rootblock.Data); + + CScenarioPointRegion = new MCScenarioPointRegion(); + CScenarioPointRegion.Ymt = this; + CScenarioPointRegion.Load(meta, cdata); + + + ScenarioRegion = new ScenarioRegion(); + ScenarioRegion.Load(this); + + //string stypes = MetaTypes.GetTypesInitString(meta); + //if (!string.IsNullOrEmpty(stypes)) + //{ } + } + + + + + public byte[] Save() + { + + switch (ContentType) + { + case YmtFileContentType.MapParentTxds: return SaveMapParentTxds(); + case YmtFileContentType.ScenarioPointManifest: return SaveScenarioPointManifest(); + case YmtFileContentType.ScenarioPointRegion: return SaveScenarioPointRegion(); + } + + return null; + } + + + private byte[] SaveMapParentTxds() + { + return null; + } + + private byte[] SaveScenarioPointManifest() + { + return null; + } + + private byte[] SaveScenarioPointRegion() + { + if (ScenarioRegion != null) + { + return ScenarioRegion.Save(); + } + return null; + } + + + + + + + + + private void LogSaveWarning(string w) + { + if (SaveWarnings == null) SaveWarnings = new List(); + SaveWarnings.Add(w); + } + + + + + + + public override string ToString() + { + return RpfFileEntry.ToString(); + } + } + + + public enum YmtFileFormat + { + Unknown = 0, + RSC = 1, + PSO = 2, + RBF = 3, + } + public enum YmtFileContentType + { + None = 0, + MapParentTxds = 1, + ScenarioPointManifest = 2, + ScenarioPointRegion = 3, + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YmtScenarioPointManifest + { + public CScenarioPointManifest _Data; + public CScenarioPointManifest Data { get { return _Data; } set { _Data = value; } } + + public CScenarioPointRegionDef[] RegionDefs { get; set; } + public CScenarioPointGroup[] Groups { get; set; } + public MetaHash[] InteriorNames { get; set; } + + + public void Load(PsoFile pso) + { + Data = PsoTypes.GetRootItem(pso); + RegionDefs = PsoTypes.ConvertDataArray(pso, _Data.RegionDefs); + Groups = PsoTypes.ConvertDataArray(pso, _Data.Groups); + InteriorNames = PsoTypes.GetHashArray(pso, _Data.InteriorNames); + } + + } + + +} diff --git a/GameFiles/FileTypes/YndFile.cs b/GameFiles/FileTypes/YndFile.cs new file mode 100644 index 0000000..7d28c9c --- /dev/null +++ b/GameFiles/FileTypes/YndFile.cs @@ -0,0 +1,1349 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] public class YndFile : GameFile, PackedFile, BasePathData + { + + public NodeDictionary NodeDictionary { get; set; } + + public YndNode[] Nodes { get; set; } + public YndLink[] Links { get; set; } + public YndJunction[] Junctions { get; set; } + + public VertexTypePC[] LinkedVerts { get; set; }//populated by the space (needs to use grid of all ynd's!) + public VertexTypePC[] TriangleVerts { get; set; } //used for junctions display + public Vector4[] NodePositions { get; set; } + + public Vector3 BBMin { get; set; } + public Vector3 BBMax { get; set; } + public int CellX { get; set; } + public int CellY { get; set; } + public int AreaID + { + get + { + return CellY * 32 + CellX; + } + set + { + CellX = value % 32; + CellY = value / 32; + UpdateBoundingBox(); + } + } + + public PathBVH BVH { get; set; } + + + + //fields used by the editor: + public bool HasChanged { get; set; } = false; + public List SaveWarnings = null; + + + + public YndFile() : base(null, GameFileType.Ynd) + { + } + public YndFile(RpfFileEntry entry) : base(entry, GameFileType.Ynd) + { + } + + + + public void Load(byte[] data) + { + //direct load from a raw, compressed ynd file (openIV-compatible format) + + RpfResourceFileEntry resentry = new RpfResourceFileEntry(); + + //hopefully this format has an RSC7 header... + uint rsc7 = BitConverter.ToUInt32(data, 0); + if (rsc7 == 0x37435352) //RSC7 header present! + { + int version = BitConverter.ToInt32(data, 4); + resentry.SystemFlags = BitConverter.ToUInt32(data, 8); + resentry.GraphicsFlags = BitConverter.ToUInt32(data, 12); + if (data.Length > 16) + { + int newlen = data.Length - 16; //trim the header from the data passed to the next step. + byte[] newdata = new byte[newlen]; + Buffer.BlockCopy(data, 16, newdata, 0, newlen); + data = newdata; + } + else + { + data = null; //shouldn't happen... empty.. + } + } + else + { + //direct load from file without the rpf header.. + //assume it's in resource meta format + resentry.SystemFlags = RpfResourceFileEntry.GetFlagsFromSize(data.Length, 0); + resentry.GraphicsFlags = RpfResourceFileEntry.GetFlagsFromSize(0, 2); //graphics type 2 for ymap + } + + var oldresentry = RpfFileEntry as RpfResourceFileEntry; + if (oldresentry != null) //update the existing entry with the new one + { + oldresentry.SystemFlags = resentry.SystemFlags; + oldresentry.GraphicsFlags = resentry.GraphicsFlags; + resentry.Name = oldresentry.Name; + resentry.NameHash = oldresentry.NameHash; + resentry.NameLower = oldresentry.NameLower; + resentry.ShortNameHash = oldresentry.ShortNameHash; + } + else + { + RpfFileEntry = resentry; //just stick it in there for later... + } + + data = ResourceBuilder.Decompress(data); + + + Load(data, resentry); + + Loaded = true; + LoadQueued = true; + } + + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + + NodeDictionary = rd.ReadBlock(); + + if (NodeDictionary != null) + { + if (NodeDictionary.Nodes != null) + { + var nodes = NodeDictionary.Nodes; + Nodes = new YndNode[nodes.Length]; + for (int i = 0; i < nodes.Length; i++) + { + var n = new YndNode(); + n.Init(this, nodes[i]); + Nodes[i] = n; + if (n.NodeID != i) + { } //never hit here - nodeid's have to match the index! + } + } + if ((NodeDictionary.JunctionRefs != null) && (NodeDictionary.Junctions != null)) + { + var juncrefs = NodeDictionary.JunctionRefs; + var juncs = NodeDictionary.Junctions; + Junctions = new YndJunction[juncrefs.Length]; + for (int i = 0; i < juncrefs.Length; i++) + { + var juncref = NodeDictionary.JunctionRefs[i]; + if (juncref.JunctionID >= juncs.Length) + { continue; } + + var j = new YndJunction(); + j.Init(this, juncs[juncref.JunctionID], juncref); + j.Heightmap = new YndJunctionHeightmap(NodeDictionary.JunctionHeightmapBytes, j); + Junctions[i] = j; + } + } + } + + UpdateAllNodePositions(); + + //links will be populated by the space... maybe move that code here? + + + + string areaidstr = Name.ToLower().Replace("nodes", "").Replace(".ynd", ""); + int areaid = 0; + int.TryParse(areaidstr, out areaid); + AreaID = areaid; + + UpdateBoundingBox(); + + + BuildBVH(); + + + Loaded = true; + LoadQueued = true; + } + + + public byte[] Save() + { + + BuildStructs(); + + byte[] data = ResourceBuilder.Build(NodeDictionary, 1); //ynd is version 1... + + + return data; + + } + + public void BuildStructs() + { + + List newlinks = new List(); + List newjuncs = new List(); + List newjuncrefs = new List(); + List newjuncheightmaps = new List(); + + if (Nodes != null) + { + int count = Nodes.Length; + var nodes = new Node[count]; + for (int i = 0; i < count; i++) + { + var node = Nodes[i]; + if (node.Links != null) + { + node.LinkCount = node.Links.Length; + node.LinkID = (ushort)newlinks.Count; + for (int l = 0; l < node.Links.Length; l++) + { + var nlink = node.Links[l]; + var rlink = nlink.RawData; + if (nlink.Node2 != null) + { + rlink.AreaID = nlink.Node2.AreaID; + rlink.NodeID = nlink.Node2.NodeID; + } + newlinks.Add(rlink); + } + } + else + { + node.LinkCount = 0; + } + + //LinkCount = node.LinkCountFlags.Value >> 3; + //LinkCountUnk = node.LinkCountFlags.Value & 7; + byte lcflags = (byte)((node.LinkCount << 3) + (node.LinkCountUnk & 7)); + node._RawData.LinkCountFlags = lcflags; + + nodes[i] = node.RawData; + + if ((node.HasJunction) && (node.Junction != null)) + { + var nj = node.Junction; + var heightmapoff = newjuncheightmaps.Count; + var heightmap = nj.Heightmap.GetBytes(); + nj._RawData.HeightmapPtr = (ushort)heightmapoff; + var jref = nj.RefData; + jref.AreaID = node.AreaID; + jref.NodeID = node.NodeID; + jref.JunctionID = (ushort)newjuncs.Count; + //jref.Unk0 = 0;//always 0? + nj.RefData = jref;//move this somewhere else..?? + newjuncs.Add(nj.RawData); + newjuncrefs.Add(jref); + newjuncheightmaps.AddRange(heightmap); + } + } + NodeDictionary.Nodes = nodes; + NodeDictionary.NodesCount = (uint)count; + NodeDictionary.Links = newlinks.ToArray(); + NodeDictionary.LinksCount = (uint)newlinks.Count; + NodeDictionary.Junctions = newjuncs.ToArray(); + NodeDictionary.JunctionsCount = (uint)newjuncs.Count; + NodeDictionary.JunctionRefs = newjuncrefs.ToArray(); + NodeDictionary.JunctionRefsCount0 = (ushort)newjuncrefs.Count; + NodeDictionary.JunctionRefsCount1 = (ushort)newjuncrefs.Count; + NodeDictionary.JunctionHeightmapBytes = newjuncheightmaps.ToArray(); + NodeDictionary.JunctionHeightmapBytesCount = (uint)newjuncheightmaps.Count; + } + else + { + NodeDictionary.Nodes = null; + NodeDictionary.NodesCount = 0; + NodeDictionary.Links = null; + NodeDictionary.LinksCount = 0; + NodeDictionary.Junctions = null; + NodeDictionary.JunctionsCount = 0; + NodeDictionary.JunctionRefs = null; + NodeDictionary.JunctionRefsCount0 = 0; + NodeDictionary.JunctionRefsCount1 = 0; + NodeDictionary.JunctionHeightmapBytes = null; + NodeDictionary.JunctionHeightmapBytesCount = 0; + } + } + + + + public YndNode AddNode() + { + int cnt = Nodes?.Length ?? 0; + YndNode yn = new YndNode(); + Node n = new Node(); + n.AreaID = (ushort)AreaID; + n.NodeID = (ushort)cnt; + yn.Init(this, n); + + int ncnt = cnt + 1; + YndNode[] nnodes = new YndNode[ncnt]; + for (int i = 0; i < cnt; i++) + { + nnodes[i] = Nodes[i]; + } + nnodes[cnt] = yn; + Nodes = nnodes; + NodeDictionary.NodesCount = (uint)ncnt; + + return yn; + } + + public bool RemoveNode(YndNode node) + { + List newnodes = new List(); + int cnt = Nodes?.Length ?? 0; + bool r = false; + int ri = -1; + for (int i = 0; i < cnt; i++) + { + var tn = Nodes[i]; + if (tn != node) + { + newnodes.Add(tn); + } + else + { + r = true; + ri = i; + } + } + Nodes = newnodes.ToArray(); + NodeDictionary.NodesCount = (uint)newnodes.Count; + NodeDictionary.NodesCountVehicle = Math.Min(NodeDictionary.NodesCountVehicle, NodeDictionary.NodesCount); + NodeDictionary.NodesCountPed = Math.Min(NodeDictionary.NodesCountPed, NodeDictionary.NodesCount); + + //remap node ID's... + List remlinks = new List(); + if (ri >= 0) + { + for (int i = 0; i < Nodes.Length; i++) + { + var n = Nodes[i]; + if (n.NodeID != i) + { + n.NodeID = (ushort)i; + + + //update nodeid's in links... + for (int j = 0; j < Nodes.Length; j++) + { + var tn = Nodes[j]; + if ((tn != null) && (tn.Links != null)) + { + for (int bl = 0; bl < tn.Links.Length; bl++) + { + var backlink = tn.Links[bl]; + if (backlink.Node2 == n) + { + backlink._RawData.NodeID = (ushort)i; + } + } + } + } + } + + //remove any links referencing the node. + remlinks.Clear(); + if (n.Links != null) + { + for (int l = 0; l < n.Links.Length; l++) + { + var nlink = n.Links[l]; + if (nlink.Node2 == node) + { + remlinks.Add(nlink); + } + } + for (int l = 0; l < remlinks.Count; l++) + { + n.RemoveLink(remlinks[l]); + } + } + + } + + } + + UpdateAllNodePositions(); + + return r; + } + + + + + + public void UpdateBoundingBox() + { + Vector3 corner = new Vector3(-8192, -8192, -2048); + Vector3 cellsize = new Vector3(512, 512, 4096); + + BBMin = corner + (cellsize * new Vector3(CellX, CellY, 0)); + BBMax = BBMin + cellsize; + } + + public void UpdateAllNodePositions() + { + int cnt = Nodes?.Length ?? 0; + if (cnt <= 0) + { + NodePositions = null; + return; + } + var np = new Vector4[cnt]; + for (int i = 0; i < cnt; i++) + { + np[i] = new Vector4(Nodes[i].Position, 1.0f); + } + NodePositions = np; + } + + public void UpdateTriangleVertices() + { + //note: called from space.BuildYndVerts() + + UpdateLinkTriangleVertices(); + + //UpdateJunctionTriangleVertices(); + } + + private void UpdateLinkTriangleVertices() + { + //build triangles for the path links display + + + int vc = 0; + if (Links != null) + { + vc = Links.Length * 6; + } + + List verts = new List(vc); + VertexTypePC v0 = new VertexTypePC(); + VertexTypePC v1 = new VertexTypePC(); + VertexTypePC v2 = new VertexTypePC(); + VertexTypePC v3 = new VertexTypePC(); + if ((Links != null) && (Nodes != null)) + { + foreach (var node in Nodes) + { + foreach (var link in node.Links) + { + var p0 = link.Node1?.Position ?? Vector3.Zero; + var p1 = link.Node2?.Position ?? Vector3.Zero; + var diff = p1 - p0; + var dir = Vector3.Normalize(diff); + var ax = Vector3.Cross(dir, Vector3.UnitZ); + + + float lanestot = link.LaneCountForward + link.LaneCountBackward; + //float backfrac = Math.Min(Math.Max(link.LaneCountBackward / lanestot, 0.1f), 0.9f); + //float lanewidth = 7.0f; + //float inner = totwidth*(backfrac-0.5f); + //float outer = totwidth*0.5f; + + float lanewidth = node.IsPedNode ? 0.5f : 5.5f; + float inner = link.LaneOffset * lanewidth;// 0.0f; + float outer = inner + Math.Max(lanewidth * link.LaneCountForward, 0.5f); + + float totwidth = lanestot * lanewidth; + float halfwidth = totwidth * 0.5f; + if (link.LaneCountBackward == 0) + { + inner -= halfwidth; + outer -= halfwidth; + } + if (link.LaneCountForward == 0) + { + inner += halfwidth; + outer += halfwidth; + } + + + v0.Position = p1 + ax * inner; + v1.Position = p0 + ax * inner; + v2.Position = p1 + ax * outer; + v3.Position = p0 + ax * outer; + var c = (uint)link.GetColour().ToRgba(); + v0.Colour = c; + v1.Colour = c; + v2.Colour = c; + v3.Colour = c; + verts.Add(v0); + verts.Add(v1); + verts.Add(v2); + verts.Add(v2); + verts.Add(v1); + verts.Add(v3); + } + } + } + + + if (verts.Count > 0) + { + TriangleVerts = verts.ToArray(); + } + else + { + TriangleVerts = null; + } + } + + private void UpdateJunctionTriangleVertices() + { + //build triangles for the junctions bytes display.... + + int vc = 0; + if (Junctions != null) + { + foreach (var j in Junctions) + { + var d = j.Heightmap; + if (d == null) continue; + vc += d.CountX * d.CountY * 6; + } + } + + List verts = new List(vc); + VertexTypePC v0 = new VertexTypePC(); + VertexTypePC v1 = new VertexTypePC(); + VertexTypePC v2 = new VertexTypePC(); + VertexTypePC v3 = new VertexTypePC(); + if (Nodes != null) + { + foreach (var node in Nodes) + { + if (node.Junction == null) continue; + var j = node.Junction; + var d = j.Heightmap; + if (d == null) continue; + + float maxz = j.MaxZ / 32.0f; + float minz = j.MinZ / 32.0f; + float rngz = maxz - minz; + float posx = j.PositionX / 4.0f; + float posy = j.PositionY / 4.0f; + + Vector3 pos = new Vector3(posx, posy, 0.0f); + Vector3 siz = new Vector3(d.CountX, d.CountY, 0.0f) * 2.0f; + //Vector3 siz = new Vector3(jx, jy, 0.0f); + Vector3 cnr = pos;// - siz * 0.5f; + //Vector3 inc = new Vector3(1.0f/jx) + + cnr.Z = minz;// + 2.0f; + + for (int y = 1; y < d.CountY; y++) //rows progress up the Y axis. + { + var row0 = d.Rows[y - 1]; + var row1 = d.Rows[y]; + float offy = y * 2.0f; + + for (int x = 1; x < d.CountX; x++) //values progress along the X axis. + { + var val0 = row0.Values[x - 1] / 255.0f; + var val1 = row0.Values[x] / 255.0f; + var val2 = row1.Values[x - 1] / 255.0f; + var val3 = row1.Values[x] / 255.0f; + float offx = x * 2.0f; + v0.Position = cnr + new Vector3(offx - 2.0f, offy - 2.0f, val0 * rngz); + v1.Position = cnr + new Vector3(offx + 0.0f, offy - 2.0f, val1 * rngz); + v2.Position = cnr + new Vector3(offx - 2.0f, offy + 0.0f, val2 * rngz); + v3.Position = cnr + new Vector3(offx + 0.0f, offy + 0.0f, val3 * rngz); + v0.Colour = (uint)new Color4(val0, 1.0f - val0, 0.0f, 1.0f).ToRgba(); + v1.Colour = (uint)new Color4(val1, 1.0f - val1, 0.0f, 1.0f).ToRgba(); + v2.Colour = (uint)new Color4(val2, 1.0f - val2, 0.0f, 1.0f).ToRgba(); + v3.Colour = (uint)new Color4(val3, 1.0f - val3, 0.0f, 1.0f).ToRgba(); + verts.Add(v0); + verts.Add(v1); + verts.Add(v2); + verts.Add(v2); + verts.Add(v1); + verts.Add(v3); + } + } + + + } + } + + if (verts.Count > 0) + { + TriangleVerts = verts.ToArray(); + } + else + { + TriangleVerts = null; + } + + + } + + + public void UpdateBvhForNode(YndNode node) + { + //this needs to be called when a node's position changes... + //if it changes a lot, need to recalc the BVH for mouse intersection optimisation purposes. + + //if (BVH == null) return; + //BVH.UpdateForNode(node); + + BuildBVH(); + + //also updates the NodePositions for the visible vertex + if (Nodes != null) + { + for (int i = 0; i < Nodes.Length; i++) + { + if (Nodes[i] == node) + { + NodePositions[i] = new Vector4(node.Position, 1.0f); + break; + } + } + } + + } + + public void BuildBVH() + { + BVH = new PathBVH(Nodes, 10); + } + + + + + public VertexTypePC[] GetPathVertices() + { + return LinkedVerts; + } + public VertexTypePC[] GetTriangleVertices() + { + return TriangleVerts; + } + public Vector4[] GetNodePositions() + { + return NodePositions; + } + + + + public override string ToString() + { + return RpfFileEntry?.ToString() ?? string.Empty; + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YndNode : BasePathNode + { + public Node _RawData; + + public YndFile Ynd { get; set; } + public Node RawData { get { return _RawData; } set { _RawData = value; } } + public Vector3 Position { get; set; } + public int LinkCount { get; set; } + public int LinkCountUnk { get; set; } + public YndLink[] Links { get; set; } + + public ushort AreaID { get { return _RawData.AreaID; } set { _RawData.AreaID = value; } } + public ushort NodeID { get { return _RawData.NodeID; } set { _RawData.NodeID = value; } } + public ushort LinkID { get { return _RawData.LinkID; } set { _RawData.LinkID = value; } } + public FlagsByte Flags0 { get { return _RawData.Flags0; } set { _RawData.Flags0 = value; } } + public FlagsByte Flags1 { get { return _RawData.Flags1; } set { _RawData.Flags1 = value; } } + public FlagsByte Flags2 { get { return _RawData.Flags2; } set { _RawData.Flags2 = value; } } + public FlagsByte Flags3 { get { return _RawData.Flags3; } set { _RawData.Flags3 = value; } } + public FlagsByte Flags4 { get { return _RawData.Flags4; } set { _RawData.Flags4 = value; } } + public TextHash StreetName { get { return _RawData.StreetName; } set { _RawData.StreetName = value; } } + + public Color4 Colour { get; set; } + + public YndJunction Junction { get; set; } + public bool HasJunction; + + + public bool IsPedNode + { + get + { + return false;// ((Flags4.Value >> 4) & 7) == 7; + } + } + + + + + public void Init(YndFile ynd, Node node) + { + Ynd = ynd; + RawData = node; + Vector3 p = new Vector3(); + p.X = node.PositionX / 4.0f; + p.Y = node.PositionY / 4.0f; + p.Z = node.PositionZ / 32.0f; + Position = p; + + LinkCount = node.LinkCountFlags.Value >> 3; + LinkCountUnk = node.LinkCountFlags.Value & 7; + + Colour = GetColour(); + + } + + public Color4 GetColour() + { + Color4 c = new Color4(LinkCountUnk / 7.0f, Flags0.Value / 255.0f, Flags1.Value / 255.0f, 1.0f); + //Color4 c = new Color4(0.0f, 0.0f, 0.0f, 1.0f); + + //c.Red = (LinkCountUnk >> 1) / 3.0f; + //c.Red = (Flags3.Value >> 1) / 127.0f; + //c.Red = ((Flags4.Value >> 1) & 7) / 7.0f; //density value? + //c.Green = 1.0f - c.Red; + + + //if ((Flags0.Value & 1) > 0) c.Red += 1.0f; //script activated? N Yankton only + small piece in self storage + //if ((Flags0.Value & 2) > 0) c.Red += 1.0f; //car can use / gps? + //if ((Flags0.Value & 4) > 0) c.Red += 1.0f; //***not used + //if ((Flags0.Value & 8) > 0) c.Red += 1.0f; //gravel surface? country roads mostly + //if ((Flags0.Value & 16) > 0) c.Red += 1.0f; //***not used + //if ((Flags0.Value & 32) > 0) c.Red += 1.0f; //slow speed? hills roads, prison boundary, carparks, airport roads etc + //if ((Flags0.Value & 64) > 0) c.Red += 1.0f; //intersection entry 1 (has priority)? + //if ((Flags0.Value & 128) > 0) c.Green += 1.0f; //intersection entry 2 unk? + + //if ((Flags1.Value & 1) > 0) c.Red += 1.0f; //left turn lane? + //if ((Flags1.Value & 2) > 0) c.Red += 1.0f; //left turn node of no return + //if ((Flags1.Value & 4) > 0) c.Red += 1.0f; //right turn node of no return + //if ((Flags1.Value & 8) > 0) c.Red += 1.0f; //entry for traffic lights / boom gates etc + //if ((Flags1.Value & 16) > 0) c.Red += 1.0f; //entry for traffic lights / boom gates etc + peds crossing + //if ((Flags1.Value & 32) > 0) c.Red += 1.0f; //intersection entry 3 unk? + //if ((Flags1.Value & 64) > 0) c.Red += 1.0f; //entry for traffic lights / boom gates etc + peds crossing + //if ((Flags1.Value & 128) > 0) c.Red += 1.0f; //intersection minor/stop, T? + + ////[16 bits pos Z here] + + //if ((Flags2.Value & 1) > 0) c.Red += 1.0f; //slow traffic? peds? carparks? military? GPS disable routing?? + //if ((Flags2.Value & 2) > 0) c.Red += 1.0f; //***not used + //if ((Flags2.Value & 4) > 0) c.Red += 1.0f; //intersection decision? + //if ((Flags2.Value & 8) > 0) c.Red += 1.0f; //***not used + //if ((Flags2.Value & 16) > 0) c.Red += 1.0f; //slower traffic? + //if ((Flags2.Value & 32) > 0) c.Red += 1.0f; //water/boat + //if ((Flags2.Value & 64) > 0) c.Red += 1.0f; //freeways /peds? + //if ((Flags2.Value & 128) > 0) c.Red += 1.0f; //not a main road...? + + //if ((LinkCountUnk & 1) > 0) c.Red += 1.0f; //has junction heightmap + //if ((LinkCountUnk & 2) > 0) c.Red += 1.0f; //speed/density/type related? not runways, not freeways + //if ((LinkCountUnk & 4) > 0) c.Red += 1.0f; //higher speed? eg freeway + ////[5 bits LinkCount here] + + //if ((Flags3.Value & 1) > 0) c.Red += 1.0f; //is in an interior + //if ((Flags3.Value & 2) > 0) c.Red += 1.0f; //heuristic val? + //if ((Flags3.Value & 4) > 0) c.Red += 1.0f; //heuristic val? + //if ((Flags3.Value & 8) > 0) c.Red += 1.0f; //heuristic val? + //if ((Flags3.Value & 16) > 0) c.Red += 1.0f; //heuristic val? + //if ((Flags3.Value & 32) > 0) c.Red += 1.0f; //heuristic val? + //if ((Flags3.Value & 64) > 0) c.Red += 1.0f; //heuristic val? + //if ((Flags3.Value & 128) > 0) c.Red += 1.0f; //heuristic val? + + //if ((Flags4.Value & 1) > 0) c.Red += 1.0f; //slow traffic? + //if ((Flags4.Value & 2) > 0) c.Red += 1.0f; //density/popgroup value..? + //if ((Flags4.Value & 4) > 0) c.Green += 1.0f; //density/popgroup value..? + //if ((Flags4.Value & 8) > 0) c.Blue += 1.0f; //density/popgroup value..? + //if ((Flags4.Value & 16) > 0) c.Red += 1.0f; //special/peds path? + //if ((Flags4.Value & 32) > 0) c.Green += 1.0f; //special/peds path? + //if ((Flags4.Value & 64) > 0) c.Blue += 1.0f; //special/peds path? + //if ((Flags4.Value & 128) > 0) c.Blue += 1.0f; //intersection entry left turn? + + + + + + + ////regarding paths.xml: + ////rubidium - Today at 8:37 AM + //also, quick glimpse over the xml for attributes: + ////> grep - i "attribute name" paths.xml | awk - F'^"' ' { print $2 }' | sort - u + //Block If No Lanes + //Cannot Go Left + //Cannot Go Right + //Density + //Disabled + //Dont Use For Navigation + //GpsBothWays + //Highway + //Indicate Keep Left + //Indicate Keep Right + //Lanes In + //Lanes Out + //Left Turns Only + //Narrowroad + //No Big Vehicles + //NoGps + //Off Road + //Shortcut + //Slip Lane + //Special + //Speed + //Streetname + //Tunnel + //Water + //Width + + + + + return c; + } + + + public void SetPosition(Vector3 pos) + { + _RawData.PositionX = (short)(pos.X * 4.0f); + _RawData.PositionY = (short)(pos.Y * 4.0f); + _RawData.PositionZ = (short)(pos.Z * 32.0f); + + Vector3 newpos = pos; + newpos.X = _RawData.PositionX / 4.0f; + newpos.Y = _RawData.PositionY / 4.0f; + newpos.Z = _RawData.PositionZ / 32.0f; + Position = newpos; + + UpdateLinkLengths(); + } + + + public void UpdateLinkLengths() + { + if (Links == null) return; + for (int i = 0; i < Links.Length; i++) + { + var link = Links[i]; + link.UpdateLength(); //update this node's links + + var n2 = link.Node2; + if ((n2 == null) || (n2.Links == null)) continue; + + for (int j = 0; j < n2.Links.Length; j++) + { + var n2l = n2.Links[j]; + if (n2l.Node2 == this) + { + n2l.UpdateLength(); //update back links + } + } + } + } + + + public YndLink AddLink(YndNode tonode = null) + { + YndLink l = new YndLink(); + l._RawData.AreaID = AreaID; + l.Node1 = this; + if (tonode != null) + { + l.Node2 = tonode; + l._RawData.AreaID = tonode.AreaID; + l._RawData.NodeID = tonode.NodeID; + } + else if ((Ynd.Nodes != null) && (Ynd.Nodes.Length > 0)) + { + l.Node2 = Ynd.Nodes[0]; + } + else + { + l.Node2 = this; + l._RawData.NodeID = NodeID; + } + l.UpdateLength(); + + int cnt = Links?.Length ?? 0; + int ncnt = cnt + 1; + YndLink[] nlinks = new YndLink[ncnt]; + for (int i = 0; i < cnt; i++) + { + nlinks[i] = Links[i]; + } + nlinks[cnt] = l; + Links = nlinks; + LinkCount = ncnt; + + return l; + } + + public bool RemoveLink(YndLink l) + { + List newlinks = new List(); + int cnt = Links?.Length ?? 0; + bool r = false; + for (int i = 0; i < cnt; i++) + { + var tl = Links[i]; + if (tl != l) + { + newlinks.Add(tl); + } + else + { + r = true; + } + } + Links = newlinks.ToArray(); + LinkCount = newlinks.Count; + return r; + } + + + public override string ToString() + { + //return AreaID.ToString() + "." + NodeID.ToString(); + return StreetName.ToString() + ", " + Position.X.ToString() + ", " + Position.Y.ToString() + ", " + Position.Z.ToString() + ", " + NodeID.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YndLink + { + public YndFile Ynd { get; set; } + public YndNode Node1 { get; set; } + public YndNode Node2 { get; set; } + public NodeLink _RawData; + public NodeLink RawData { get { return _RawData; } set { _RawData = value; } } + public FlagsByte Flags0 { get { return _RawData.Flags0; } set { _RawData.Flags0 = value; } } + public FlagsByte Flags1 { get { return _RawData.Flags1; } set { _RawData.Flags1 = value; } } + public FlagsByte Flags2 { get { return _RawData.Flags2; } set { _RawData.Flags2 = value; } } + public FlagsByte LinkLength { get { return _RawData.LinkLength; } set { _RawData.LinkLength = value; } } + + public int LaneCountForward { get { return (Flags2.Value >> 5) & 7; } } + public int LaneCountBackward { get { return (Flags2.Value >> 2) & 7; } } + + public int OffsetValue { get { return (Flags1.Value >> 4) & 7; } } + public bool NegativeOffset { get { return (Flags1.Value >> 7) > 0; } } + public float LaneOffset { get { return (OffsetValue / 7.0f) * (NegativeOffset ? -0.5f : 0.5f); } } + + + public void Init(YndFile ynd, YndNode node1, YndNode node2, NodeLink link) + { + Ynd = ynd; + Node1 = node1; + Node2 = node2; + RawData = link; + } + + + public void UpdateLength() + { + if (Node1 == null) return; + if (Node2 == null) return; + + LinkLength = (byte)Math.Min(255, (Node2.Position - Node1.Position).Length()); + } + + + public void CopyFlags(YndLink link) + { + if (link == null) return; + Flags0 = link.Flags0; + Flags1 = link.Flags1; + Flags2 = link.Flags2; + } + + + + public Color4 GetColour() + { + + + //float f0 = Flags0.Value / 255.0f; + //float f1 = Flags1.Value / 255.0f; + //float f2 = Flags2.Value / 255.0f; + //var c = new Color4(f0, f1, f2, 1.0f); + + var c = new Color4(0.0f, 0.0f, 0.0f, 0.5f); + c.Green = LaneCountForward / 7.0f; + c.Red = LaneCountBackward / 7.0f; + + + //if ((Flags0.Value & 1) > 0) c.Red = 1.0f; //? some small pieces in city, roads at docks, and mall at beach + //if ((Flags0.Value & 2) > 0) c.Red = 1.0f; //3x segments joining east canal paths to roads, also josh's driveway - scripted? + //if ((Flags0.Value & 4) > 0) c.Red = 1.0f; //? looks fairly random, 0 for water, alternating - slope related? + //if ((Flags0.Value & 8) > 0) c.Red = 1.0f; //? like above + //if ((Flags0.Value & 16) > 0) c.Red = 1.0f; //? similar to above, but less + //if ((Flags0.Value & 32) > 0) c.Red = 1.0f; //? like above + //if ((Flags0.Value & 64) > 0) c.Red = 1.0f; //? slightly less random + //if ((Flags0.Value & 128) > 0) c.Red = 1.0f; //? still looks random... + + //if ((Flags1.Value & 1) > 0) c.Red = 1.0f; //***not used? + //if ((Flags1.Value & 2) > 0) c.Red = 1.0f; //?possibly width/type bit + //if ((Flags1.Value & 4) > 0) c.Red = 1.0f; //avoid routing? no through road / no other exit? + //if ((Flags1.Value & 8) > 0) c.Red = 1.0f; //prefer routing? exit from dead end? + //if ((Flags1.Value & 16) > 0) c.Red = 1.0f; //offset value. mostly single lane, carpark access, golf course, alleyways, driveways, beach area etc + //if ((Flags1.Value & 32) > 0) c.Green = 1.0f; //offset value. similar to above + //if ((Flags1.Value & 64) > 0) c.Green = 1.0f; //offset value. similar to above + //if ((Flags1.Value & 128) > 0) c.Red = 1.0f; //offset value. (sign) similar to above (all paired with their back links!) + + //if ((Flags2.Value & 1) > 0) c.Red = 1.0f; //angled link - merge? enter/exit divided road section, most big junctions, always paired + //if ((Flags2.Value & 2) > 0) c.Red = 1.0f; //lane change/u-turn link? always paired + //if ((Flags2.Value & 4) > 0) c.Red = 1.0f; //lane count back dir + //if ((Flags2.Value & 8) > 0) c.Red = 1.0f; //lane count back dir + //if ((Flags2.Value & 16) > 0) c.Red = 1.0f; //lane count back dir + //if ((Flags2.Value & 32) > 0) c.Green = 1.0f; //lane count forward dir + //if ((Flags2.Value & 64) > 0) c.Green = 1.0f; //lane count forward dir + //if ((Flags2.Value & 128) > 0) c.Green = 1.0f; //lane count forward dir + + ////var lanesfwd = (Flags2.Value >> 5) & 7; + ////var lanesbck = (Flags2.Value >> 2) & 7; + //////if ((lanesfwd > 0) && (lanesbck > 0) && (lanesfwd != lanesbck)) + //////{ } + + + + //var t = (Flags1.Value >> 4)&1; + //c.Red = t / 1.0f; + //c.Green = 1.0f - c.Red; + ////if (((Flags1.Value & 128) > 0))// && ((Flags1.Value & 64) == 0)) + ////{ c.Red += 1.0f; } + + + + return c; + } + + + + public override string ToString() + { + return Node2._RawData.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YndJunction + { + public YndFile Ynd { get; set; } + public NodeJunction _RawData; + public NodeJunction RawData { get { return _RawData; } set { _RawData = value; } } + public NodeJunctionRef RefData { get; set; } + public YndJunctionHeightmap Heightmap { get; set; } + public short MaxZ { get; set; } + public short MinZ { get; set; } + public short PositionX { get; set; } + public short PositionY { get; set; } + + public void Init(YndFile ynd, NodeJunction junc, NodeJunctionRef reff) + { + Ynd = ynd; + RawData = junc; + RefData = reff; + MaxZ = junc.MaxZ; + MinZ = junc.MinZ; + PositionX = junc.PositionX; + PositionY = junc.PositionY; + } + + + public void ResizeHeightmap() + { + Heightmap.Resize(_RawData.HeightmapDimX, _RawData.HeightmapDimY); + } + + public void SetHeightmap(string text) + { + Heightmap.SetData(text); + } + + + public override string ToString() + { + return RefData.ToString(); + } + + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YndJunctionHeightmap + { + public YndJunctionHeightmapRow[] Rows { get; set; } + public int CountX { get; set; } + public int CountY { get; set; } + + public YndJunctionHeightmap(byte[] data, YndJunction junc) + { + if (data == null) + { return; } + + var d = junc.RawData; + int s = d.HeightmapPtr; + CountX = d.HeightmapDimX; + CountY = d.HeightmapDimY; + + if ((s + CountX * CountY) > data.Length) + { return; } + + Rows = new YndJunctionHeightmapRow[CountY]; + + + for (int y = 0; y < CountY; y++) + { + int o = s + y * CountX; + byte[] vals = new byte[CountX]; + Buffer.BlockCopy(data, o, vals, 0, CountX); + Rows[y] = new YndJunctionHeightmapRow(vals); + } + } + + + public byte[] GetBytes() + { + int cnt = CountX * CountY; + var bytes = new byte[cnt]; + for (int y = 0; y < CountY; y++) + { + int o = y * CountX; + var rowvals = Rows[y].Values; + Buffer.BlockCopy(rowvals, 0, bytes, o, CountX); + } + return bytes; + } + + + public void Resize(int cx, int cy) + { + var nrows = new YndJunctionHeightmapRow[cy]; + for (int y = 0; y < cy; y++) + { + byte[] nvals = new byte[cx]; + int minx = Math.Min(cx, CountX); + if ((Rows != null) && (y < Rows.Length)) + { + Buffer.BlockCopy(Rows[y].Values, 0, nvals, 0, minx); + } + nrows[y] = new YndJunctionHeightmapRow(nvals); + } + Rows = nrows; + + CountX = cx; + CountY = cy; + } + + public void SetData(string text) + { + var rsplit = new[] { '\n' }; + var csplit = new[] { ' ' }; + string[] rowstrs = text.Split(rsplit, StringSplitOptions.RemoveEmptyEntries); + for (int y = 0; y < rowstrs.Length; y++) + { + string[] colstrs = rowstrs[y].Trim().Split(csplit, StringSplitOptions.RemoveEmptyEntries); + int cx = colstrs.Length; + byte[] vals = new byte[cx]; + for (int x = 0; x < cx; x++) + { + byte.TryParse(colstrs[x], out vals[x]); + } + int minx = Math.Min(cx, CountX); + if ((Rows != null) && (y < Rows.Length)) + { + var nrow = new byte[CountX]; + Buffer.BlockCopy(vals, 0, nrow, 0, minx); + Rows[y].Values = nrow; + } + } + } + + public string GetDataString() + { + StringBuilder sb = new StringBuilder(); + if (Rows != null) + { + foreach (var row in Rows) + { + sb.AppendLine(row.ToString()); + } + } + return sb.ToString(); + } + + public override string ToString() + { + return CountX.ToString() + " x " + CountY.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class YndJunctionHeightmapRow + { + public byte[] Values { get; set; } + + public YndJunctionHeightmapRow(byte[] vals) + { + Values = vals; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < Values.Length; i++) + { + if (i > 0) sb.Append(" "); + sb.Append(Values[i].ToString().PadLeft(3, '0')); + //sb.Append(Convert.ToString(Values[i], 16).ToUpper().PadLeft(2, '0')); + } + return sb.ToString(); + } + } + + + + + public class PathBVHNode + { + public int Threshold; + public List Nodes; + public BoundingBox Box; + public BoundingSphere Sphere; + public PathBVHNode Node1; + public PathBVHNode Node2; + + + public void CalcBounds() + { + if ((Nodes == null) || (Nodes.Count <= 0)) return; + + Box.Minimum = new Vector3(float.MaxValue); + Box.Maximum = new Vector3(float.MinValue); + foreach (var node in Nodes) + { + Box.Minimum = Vector3.Min(Box.Minimum, node.Position); + Box.Maximum = Vector3.Max(Box.Maximum, node.Position); + } + Sphere.Center = (Box.Minimum + Box.Maximum) * 0.5f; + Sphere.Radius = (Box.Maximum - Box.Minimum).Length() * 0.5f; + } + + + public void Build() + { + if ((Nodes == null) || (Nodes.Count <= Threshold)) return; + + Vector3 avgsum = Vector3.Zero; + foreach (var node in Nodes) + { + avgsum += node.Position; + } + Vector3 avg = avgsum * (1.0f / Nodes.Count); + + int countx = 0, county = 0, countz = 0; + foreach (var node in Nodes) + { + if (node.Position.X < avg.X) countx++; + if (node.Position.Y < avg.Y) county++; + if (node.Position.Z < avg.Z) countz++; + } + + int target = Nodes.Count / 2; + int dx = Math.Abs(target - countx); + int dy = Math.Abs(target - county); + int dz = Math.Abs(target - countz); + + int axis = -1; + if ((dx <= dy) && (dx <= dz)) axis = 0; //x seems best + else if (dy <= dz) axis = 1; //y seems best + else axis = 2; //z seems best + + + List l1 = new List(); + List l2 = new List(); + foreach (var node in Nodes) + { + bool s = false; + switch (axis) + { + default: + case 0: s = (node.Position.X > avg.X); break; + case 1: s = (node.Position.Y > avg.Y); break; + case 2: s = (node.Position.Z > avg.Z); break; + } + if (s) l1.Add(node); + else l2.Add(node); + } + + + Node1 = new PathBVHNode(); + Node1.Threshold = Threshold; + Node1.Nodes = new List(l1); + Node1.CalcBounds(); + Node1.Build(); + + Node2 = new PathBVHNode(); + Node2.Threshold = Threshold; + Node2.Nodes = new List(l2); + Node2.CalcBounds(); + Node2.Build(); + } + + + public void UpdateForNode(BasePathNode node) + { + if (!Nodes.Contains(node)) return; + Box.Minimum = Vector3.Min(Box.Minimum, node.Position); + Box.Maximum = Vector3.Max(Box.Maximum, node.Position); + + if (Node1 != null) Node1.UpdateForNode(node); + if (Node2 != null) Node2.UpdateForNode(node); + } + + } + + public class PathBVH : PathBVHNode + { + + public PathBVH(IEnumerable nodes, int threshold) + { + Threshold = threshold; + Nodes = (nodes != null) ? new List(nodes) : new List(); + CalcBounds(); + Build(); + } + + } + + + + + public interface BasePathNode + { + Vector3 Position { get; set; } + } + + public interface BasePathData + { + //reuse this interface for file types that need to get paths rendered... + + VertexTypePC[] GetPathVertices(); + VertexTypePC[] GetTriangleVertices(); + Vector4[] GetNodePositions(); + } + + + +} diff --git a/GameFiles/FileTypes/YnvFile.cs b/GameFiles/FileTypes/YnvFile.cs new file mode 100644 index 0000000..3f30c8b --- /dev/null +++ b/GameFiles/FileTypes/YnvFile.cs @@ -0,0 +1,405 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] public class YnvFile : GameFile, PackedFile, BasePathData + { + public NavMesh Nav { get; set; } + + public List Vertices { get; set; } + public List Indices { get; set; } + public List Polys { get; set; } + + + public VertexTypePC[] TriangleVerts { get; set; } + public Vector4[] NodePositions { get; set; } + + + //fields used by the editor: + public bool HasChanged { get; set; } = false; + public List SaveWarnings = null; + + + + public int AreaID + { + get + { + return (int)(Nav?.AreaID ?? 0); + } + } + + + + + public YnvFile() : base(null, GameFileType.Ynv) + { + } + public YnvFile(RpfFileEntry entry) : base(entry, GameFileType.Ynv) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + + Nav = rd.ReadBlock(); + + + if ((Nav != null) && (Nav.SectorTree != null)) + { + if (Nav.Vertices != null) + { + Vector3 posoffset = Nav.SectorTree.AABBMin.XYZ(); + Vector3 aabbsize = Nav.AABBSize; + + var verts = Nav.Vertices.GetFullList(); + Vertices = new List(verts.Count); + for (int i = 0; i < verts.Count; i++) + { + var ov = verts[i].ToVector3(); + Vertices.Add(posoffset + ov * aabbsize); + } + } + if (Nav.Indices != null) + { + Indices = Nav.Indices.GetFullList(); + } + if (Nav.Polys != null) + { + var polys = Nav.Polys.GetFullList(); + Polys = new List(polys.Count); + for (int i = 0; i < polys.Count; i++) + { + YnvPoly poly = new YnvPoly(); + poly.Init(this, polys[i]); + poly.Index = i; + Polys.Add(poly); + + + //calc poly center. + if ((Indices == null) || (Vertices == null)) + { continue; } + var vc = Vertices.Count; + var ic = poly._RawData.IndexCount; + var startid = poly._RawData.IndexID; + var endid = startid + ic; + if (startid >= Indices.Count) + { continue; } + if (endid > Indices.Count) + { continue; } + Vector3 pcenter = Vector3.Zero; + float pcount = 0.0f; + for (int id = startid; id < endid; id++) + { + var ind = Indices[id]; + if(ind>=vc) + { continue; } + + pcenter += Vertices[ind]; + pcount += 1.0f; + } + poly.Position = pcenter * (1.0f / pcount); + + + } + } + + } + + + + UpdateAllNodePositions(); + + UpdateTriangleVertices(); + + + Loaded = true; + LoadQueued = true; + } + + + + + + + + + + public bool RemovePoly(YnvPoly poly) + { + return false; + } + + + + + + public void UpdateAllNodePositions() + { + if (Nav == null) return; + if (Nav.Portals == null) return; + + int cnt = Nav.Portals?.Length ?? 0; + if (cnt <= 0) + { + NodePositions = null; + return; + } + + Vector3 posoffset = Nav.SectorTree.AABBMin.XYZ(); + Vector3 aabbsize = Nav.AABBSize; + + var np = new Vector4[cnt]; + for (int i = 0; i < cnt; i++) + { + var portal = Nav.Portals[i]; + var pv = portal.Position1.ToVector3(); + //var pv = portal.Position2.ToVector3(); + np[i] = new Vector4(posoffset + pv * aabbsize, 1.0f); + } + NodePositions = np; + } + + public void UpdateTriangleVertices() + { + if (Nav == null) return; + if (Nav.Polys == null) return; + if (Nav.Vertices == null) return; + + //need position and colour for each vertex. + //render as a triangle list... (no indices needed) + + //go through the nav mesh polys and generate verts to render... + + if ((Vertices == null) || (Vertices.Count == 0)) return; + if ((Indices == null) || (Indices.Count == 0)) return; + if ((Polys == null) || (Polys.Count == 0)) return; + + + int vc = Vertices.Count; + + List rverts = new List(); + foreach (var ypoly in Polys) + { + var poly = ypoly.RawData; + var colour = ypoly.GetColour(); + var colourval = (uint)colour.ToRgba(); + + var ic = poly.IndexCount; + var startid = poly.IndexID; + var endid = startid + ic; + if (startid >= Indices.Count) + { continue; } + if (endid > Indices.Count) + { continue; } + + + if(ic<3) + { continue; }//not enough verts to make a triangle... + + if (ic > 15) + { } + + + VertexTypePC p0 = new VertexTypePC(); + VertexTypePC p1 = new VertexTypePC(); + VertexTypePC p2 = new VertexTypePC(); + p0.Colour = colourval; + p1.Colour = colourval; + p2.Colour = colourval; + + var startind = Indices[startid]; + if (startind >= vc) + { continue; } + + p0.Position = Vertices[startind]; + + //build triangles for the poly. + int tricount = ic - 2; + for (int t = 0; t < tricount; t++) + { + int tid = startid + t; + int ind1 = Indices[tid + 1]; + int ind2 = Indices[tid + 2]; + if ((ind1 >= vc) || (ind2 >= vc)) + { continue; } + + p1.Position = Vertices[ind1]; + p2.Position = Vertices[ind2]; + + rverts.Add(p0); + rverts.Add(p1); + rverts.Add(p2); + } + + } + + TriangleVerts = rverts.ToArray(); + + } + + + + public VertexTypePC[] GetPathVertices() + { + return null; + } + public VertexTypePC[] GetTriangleVertices() + { + return TriangleVerts; + } + public Vector4[] GetNodePositions() + { + return NodePositions; + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoly + { + public NavMeshPoly _RawData; + + public YnvFile Ynv { get; set; } + public NavMeshPoly RawData { get { return _RawData; } set { _RawData = value; } } + + public ushort AreaID { get { return _RawData.AreaID; } } + public bool B00_AvoidUnk { get { return (_RawData.Unknown_00h & 1) > 0; } } + public bool B01_AvoidUnk { get { return (_RawData.Unknown_00h & 2) > 0; } } + public bool B02_IsFootpath { get { return (_RawData.Unknown_00h & 4) > 0; } } + public bool B03_IsUnderground { get { return (_RawData.Unknown_00h & 8) > 0; } } + //public bool B04_Unused { get { return (_RawData.Unknown_00h & 16) > 0; } } + //public bool B05_Unused { get { return (_RawData.Unknown_00h & 32) > 0; } } + public bool B06_SteepSlope { get { return (_RawData.Unknown_00h & 64) > 0; } } + public bool B07_IsWater { get { return (_RawData.Unknown_00h & 128) > 0; } } + public bool B08_UndergroundUnk1 { get { return (_RawData.Unknown_24h.Value & 1) > 0; } } + public bool B09_UndergroundUnk2 { get { return (_RawData.Unknown_24h.Value & 2) > 0; } } + public bool B10_UndergroundUnk3 { get { return (_RawData.Unknown_24h.Value & 4) > 0; } } + public bool B11_UndergroundUnk4 { get { return (_RawData.Unknown_24h.Value & 8) > 0; } } + //public bool B12_Unused { get { return (_RawData.Unknown_24h.Value & 16) > 0; } } + public bool B13_HasPathNode { get { return (_RawData.Unknown_24h.Value & 32) > 0; } } + public bool B14_IsInterior { get { return (_RawData.Unknown_24h.Value & 64) > 0; } } + public bool B15_InteractionUnk { get { return (_RawData.Unknown_24h.Value & 128) > 0; } } + //public bool B16_Unused { get { return (_RawData.Unknown_24h.Value & 256) > 0; } } + public bool B17_IsFlatGround { get { return (_RawData.Unknown_24h.Value & 512) > 0; } } + public bool B18_IsRoad { get { return (_RawData.Unknown_24h.Value & 1024) > 0; } } + public bool B19_IsCellEdge { get { return (_RawData.Unknown_24h.Value & 2048) > 0; } } + public bool B20_IsTrainTrack { get { return (_RawData.Unknown_24h.Value & 4096) > 0; } } + public bool B21_IsShallowWater { get { return (_RawData.Unknown_24h.Value & 8192) > 0; } } + public bool B22_FootpathUnk1 { get { return (_RawData.Unknown_24h.Value & 16384) > 0; } } + public bool B23_FootpathUnk2 { get { return (_RawData.Unknown_24h.Value & 32768) > 0; } } + public bool B24_FootpathMall { get { return (_RawData.Unknown_24h.Value & 65536) > 0; } } + public bool B25_SlopeSouth { get { return (_RawData.Unknown_28h.Value & 65536) > 0; } } + public bool B26_SlopeSouthEast { get { return (_RawData.Unknown_28h.Value & 131072) > 0; } } + public bool B27_SlopeEast { get { return (_RawData.Unknown_28h.Value & 262144) > 0; } } + public bool B28_SlopeNorthEast { get { return (_RawData.Unknown_28h.Value & 524288) > 0; } } + public bool B29_SlopeNorth { get { return (_RawData.Unknown_28h.Value & 1048576) > 0; } } + public bool B30_SlopeNorthWest { get { return (_RawData.Unknown_28h.Value & 2097152) > 0; } } + public bool B31_SlopeWest { get { return (_RawData.Unknown_28h.Value & 4194304) > 0; } } + public bool B32_SlopeSouthWest { get { return (_RawData.Unknown_28h.Value & 8388608) > 0; } } + public bool B33_PortalUnk1 { get { return (_RawData.PartUnk2 & 1) > 0; } } + public bool B34_PortalUnk2 { get { return (_RawData.PartUnk2 & 2) > 0; } } + public bool B35_PortalUnk3 { get { return (_RawData.PartUnk2 & 4) > 0; } } + public bool B36_PortalUnk4 { get { return (_RawData.PartUnk2 & 8) > 0; } } + public byte HeuristicXUnk { get { return (byte)_RawData.Unknown_28h_8a; } } + public byte HeuristicYUnk { get { return (byte)_RawData.Unknown_28h_8b; } } + + + public Vector3 Position { get; set; } + public int Index { get; set; } + + + public void Init(YnvFile ynv, NavMeshPoly poly) + { + Ynv = ynv; + RawData = poly; + + } + + + public Color4 GetColour() + { + var colour = new Color4(); + var u0 = _RawData.Unknown_00h; + if ((u0 & 1) > 0) colour.Red += 0.01f;//avoid? loiter? + if ((u0 & 2) > 0) colour.Red += 0.01f; //avoid? + if ((u0 & 4) > 0) colour.Green += 0.25f; //ped/footpath + if ((u0 & 8) > 0) colour.Green += 0.02f; //underground? + ////if ((u0 & 16) > 0) colour.Red += 1.0f; //not used? + ////if ((u0 & 32) > 0) colour.Green += 1.0f;//not used? + if ((u0 & 64) > 0) colour.Red += 0.25f; //steep slope + if ((u0 & 128) > 0) colour.Blue += 0.25f; //water + + var u2 = _RawData.Unknown_24h.Value; + //colour.Green = (u2 & 15) / 15.0f; //maybe underground amount..? + //if ((u2 & 1) > 0) colour.Blue += 1.0f; //peds interact with something? underground? + //if ((u2 & 2) > 0) colour.Green += 1.0f;//underneath something? + //if ((u2 & 4) > 0) colour.Red += 0.5f;//peds interact with something..? underground? + //if ((u2 & 8) > 0) colour.Red += 0.5f; //underground? + //if ((u2 & 16) > 0) colour.Red += 1.0f; //not used.. + //if ((u2 & 32) > 0) colour.Green += 1.0f;//use path node? + if ((u2 & 64) > 0) colour.Blue += 0.1f; //is interior? + //if ((u2 & 128) > 0) colour.Red += 1.0f; //interacting areas? veg branches, roofs, vents, worker areas? + //if ((u2 & 256) > 0) colour.Green += 1.0f; //not used? + if ((u2 & 512) > 0) colour.Green += 0.1f;//is flat ground? ped-navigable? + if ((u2 & 1024) > 0) colour.Blue += 0.03f;//is a road + //if ((u2 & 2048) > 0) colour.Green += 1.0f; //poly is on a cell edge + if ((u2 & 4096) > 0) colour.Green += 0.75f; //is a train track + if ((u2 & 8192) > 0) colour.Blue += 0.75f;//shallow water/moving water + if ((u2 & 16384) > 0) colour.Red += 0.2f; //footpaths/beach - peds walking? + if ((u2 & 32768) > 0) colour.Blue += 0.2f; //footpaths - special? + if ((u2 & 65536) > 0) colour.Green = 0.2f;//footpaths - mall areas? eg mall, vinewood blvd + //if (u2 >= 131072) { }//other bits unused + + var u5 = _RawData.Unknown_28h.Value; //32 bits + //colour.Red = poly.Unknown_28h_8a / 255.0f; //heuristic vals..? + //colour.Green = poly.Unknown_28h_8b / 255.0f; //heuristic vals..? + //if ((u5 & 65536) > 0) colour.Red += 1.0f; //slope facing -Y (south) + //if ((u5 & 131072) > 0) colour.Blue += 1.0f; //slope facing +X,-Y (southeast) + //if ((u5 & 262144) > 0) colour.Green += 1.0f; //slope facing +X (east) + //if ((u5 & 524288) > 0) colour.Red += 1.0f; //slope facing +X,+Y (northeast) + //if ((u5 & 1048576) > 0) colour.Green += 1.0f; //slope facing +Y (north) + //if ((u5 & 2097152) > 0) colour.Blue += 1.0f; //slope facing -X,+Y (northwest) + //if ((u5 & 4194304) > 0) colour.Green += 1.0f; //slope facing -X (west) + //if ((u5 & 8388608) > 0) colour.Red += 1.0f; //slope facing -X,-Y (southwest) + //if (u5 >= 16777216) { } //other bits unused + + var u1 = _RawData.PartUnk2; + //if ((u1 & 1) > 0) colour.Red += 1.0f; //portal - don't interact? + //if ((u1 & 2) > 0) colour.Green += 1.0f; //portal - ladder/fence interaction? + //if ((u1 & 4) > 0) colour.Blue += 1.0f; //portal - fence interaction / go away from? + //if ((u1 & 8) > 0) colour.Red += 1.0f;//something file-specific? portal index related? + + + + colour.Alpha = 0.75f; + + return colour; + } + + + public override string ToString() + { + return AreaID.ToString() + ", " + Index.ToString(); + } + } + + +} diff --git a/GameFiles/FileTypes/YptFile.cs b/GameFiles/FileTypes/YptFile.cs new file mode 100644 index 0000000..3a6530c --- /dev/null +++ b/GameFiles/FileTypes/YptFile.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YptFile : GameFile, PackedFile + { + public ParticleEffectsList PtfxList { get; set; } + + public Dictionary DrawableDict { get; set; } + + public string ErrorMessage { get; set; } + + + public YptFile() : base(null, GameFileType.Ypt) + { + } + public YptFile(RpfFileEntry entry) : base(entry, GameFileType.Ypt) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + //MemoryUsage = 0; + + try + { + PtfxList = rd.ReadBlock(); + //Drawable.Owner = this; + //MemoryUsage += Drawable.MemoryUsage; //uses decompressed filesize now... + } + catch (Exception ex) + { + ErrorMessage = ex.ToString(); + } + + + var dDict = PtfxList?.DrawableDictionary; + + if ((dDict != null) && + (dDict.Drawables != null) && + (dDict.Drawables.data_items != null) && + (dDict.Hashes != null)) + { + DrawableDict = new Dictionary(); + var drawables = dDict.Drawables.data_items; + var hashes = dDict.Hashes; + for (int i = 0; (i < drawables.Length) && (i < hashes.Length); i++) + { + var drawable = drawables[i]; + var hash = hashes[i]; + DrawableDict[hash] = drawable; + drawable.Owner = this; + } + + for (int i = 0; (i < drawables.Length) && (i < hashes.Length); i++) + { + var drawable = drawables[i]; + var hash = hashes[i]; + if ((drawable.Name == null) || (drawable.Name.EndsWith("#dd"))) + { + string hstr = JenkIndex.TryGetString(hash); + if (!string.IsNullOrEmpty(hstr)) + { + drawable.Name = hstr; + } + else + { + drawable.Name = "0x" + hash.ToString("X").PadLeft(8, '0'); + } + } + } + + } + + + + + + Loaded = true; + + } + + + } + + + + + +} diff --git a/GameFiles/FileTypes/YtdFile.cs b/GameFiles/FileTypes/YtdFile.cs new file mode 100644 index 0000000..5915e5f --- /dev/null +++ b/GameFiles/FileTypes/YtdFile.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YtdFile : GameFile, PackedFile + { + public TextureDictionary TextureDict { get; set; } + + + public YtdFile() : base(null, GameFileType.Ytd) + { + } + public YtdFile(RpfFileEntry entry) : base(entry, GameFileType.Ytd) + { + } + + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + + TextureDict = rd.ReadBlock(); + + //MemoryUsage = 0; //uses decompressed file size now.. + //if (TextureDict != null) + //{ + // MemoryUsage += TextureDict.MemoryUsage; + //} + + } + + + } +} diff --git a/GameFiles/FileTypes/YtypFile.cs b/GameFiles/FileTypes/YtypFile.cs new file mode 100644 index 0000000..dd0dc36 --- /dev/null +++ b/GameFiles/FileTypes/YtypFile.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] + public class YtypFile : PackedFile + { + + public RpfFileEntry FileEntry { get; set; } + + public Meta Meta { get; set; } + public PsoFile Pso { get; set; } + public RbfFile Rbf { get; set; } + + public CMapTypes CMapTypes { get; set; } + //public CBaseArchetypeDef[] CBaseArchetypeDefs { get; set; } + //public CTimeArchetypeDef[] CTimeArchetypeDefs { get; set; } + //public CMloArchetypeDef[] CMloArchetypeDefs { get; set; } + + public CExtensionDefAudioEmitter[] AudioEmitters { get; set; } + + //public CEntityDef[] CEntityDefs { get; set; } + + public CCompositeEntityType[] CompositeEntityTypes { get; set; } + + public uint NameHash { get; set; } + public string[] Strings { get; set; } + + + + public Archetype[] AllArchetypes { get; set; } + + public MetaWrapper[] Extensions { get; set; } + + + public override string ToString() + { + return (FileEntry != null) ? FileEntry.Name : string.Empty; + } + + public void Load(byte[] data, RpfFileEntry entry) + { + FileEntry = entry; + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + MemoryStream ms = new MemoryStream(data); + if (RbfFile.IsRBF(ms)) + { + Rbf = new RbfFile(); + Rbf.Load(ms); + } + else if (PsoFile.IsPSO(ms)) + { + Pso = new PsoFile(); + Pso.Load(ms); + //PsoTypes.EnsurePsoTypes(Pso); + } + else + { + } + return; + } + + + + + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + Meta = rd.ReadBlock(); + + + CMapTypes = MetaTypes.GetTypedData(Meta, MetaName.CMapTypes); + + + List allarchs = new List(); + + var ptrs = MetaTypes.GetPointerArray(Meta, CMapTypes.archetypes); + if (ptrs != null) + { + for (int i = 0; i < ptrs.Length; i++) + { + var ptr = ptrs[i]; + int blocki = ptr.BlockID - 1; + int offset = ptr.ItemOffset * 16;//block data size... + if (blocki >= Meta.DataBlocks.Count) + { continue; } + var block = Meta.DataBlocks[blocki]; + if ((offset < 0) || (block.Data == null) || (offset >= block.Data.Length)) + { continue; } + + var ba = new Archetype(); + switch (block.StructureNameHash) + { + case MetaName.CBaseArchetypeDef: + var basearch = PsoTypes.ConvertDataRaw(block.Data, offset); + ba.Init(this, basearch); + ba.Extensions = MetaTypes.GetExtensions(Meta, basearch.extensions); + break; + case MetaName.CTimeArchetypeDef: + var timearch = PsoTypes.ConvertDataRaw(block.Data, offset); + ba.Init(this, timearch); + ba.Extensions = MetaTypes.GetExtensions(Meta, timearch.CBaseArchetypeDef.extensions); + break; + case MetaName.CMloArchetypeDef: + var mloarch = PsoTypes.ConvertDataRaw(block.Data, offset); + ba.Init(this, mloarch); + ba.Extensions = MetaTypes.GetExtensions(Meta, mloarch.CBaseArchetypeDef.extensions); + + MloArchetypeData mlod = new MloArchetypeData(); + mlod.entities = MetaTypes.ConvertDataArray(Meta, MetaName.CEntityDef, mloarch.entities); + mlod.rooms = MetaTypes.ConvertDataArray(Meta, MetaName.CMloRoomDef, mloarch.rooms); + mlod.portals = MetaTypes.ConvertDataArray(Meta, MetaName.CMloPortalDef, mloarch.portals); + mlod.entitySets = MetaTypes.ConvertDataArray(Meta, MetaName.CMloEntitySet, mloarch.entitySets); + mlod.timeCycleModifiers = MetaTypes.ConvertDataArray(Meta, MetaName.CMloTimeCycleModifier, mloarch.timeCycleModifiers); + ba.MloData = mlod; + + //if (mlod.entities != null) + //{ + // for (int e = 0; e < mlod.entities.Length; e++) + // { + // EnsureEntityExtensions(Meta, ref mlod.entities[e]); + // } + //} + + break; + default: + continue; + } + + + allarchs.Add(ba); + } + } + AllArchetypes = allarchs.ToArray(); + + + Extensions = MetaTypes.GetExtensions(Meta, CMapTypes.extensions); + if (Extensions != null) + { } + + + AudioEmitters = MetaTypes.GetTypedDataArray(Meta, MetaName.CExtensionDefAudioEmitter); + if (AudioEmitters != null) + { } + + //CEntityDefs = MetaTypes.GetTypedDataArray(Meta, MetaName.CEntityDef); + + CompositeEntityTypes = MetaTypes.ConvertDataArray(Meta, MetaName.CCompositeEntityType, CMapTypes.compositeEntityTypes); + if (CompositeEntityTypes != null) + { } + + NameHash = CMapTypes.name; + if (NameHash == 0) + { + int ind = entry.NameLower.LastIndexOf('.'); + if (ind > 0) + { + NameHash = JenkHash.GenHash(entry.NameLower.Substring(0, ind)); + } + else + { + NameHash = JenkHash.GenHash(entry.NameLower); + } + } + + Strings = MetaTypes.GetStrings(Meta); + if (Strings != null) + { + foreach (string str in Strings) + { + JenkIndex.Ensure(str); //just shove them in there + } + } + + + foreach (var block in Meta.DataBlocks) + { + switch(block.StructureNameHash) + { + case MetaName.CMapTypes: + case MetaName.CTimeArchetypeDef: + case MetaName.CBaseArchetypeDef: + case MetaName.CMloArchetypeDef: + case MetaName.CMloTimeCycleModifier: + case MetaName.CMloRoomDef: + case MetaName.CMloPortalDef: + case MetaName.CMloEntitySet: + case MetaName.CEntityDef: + case MetaName.CExtensionDefParticleEffect: + case MetaName.CExtensionDefAudioCollisionSettings: + case MetaName.CExtensionDefSpawnPoint: + case MetaName.CExtensionDefSpawnPointOverride: + case MetaName.CExtensionDefExplosionEffect: + case MetaName.CExtensionDefAudioEmitter: + case MetaName.CExtensionDefLadder: + case MetaName.CExtensionDefBuoyancy: + case MetaName.CExtensionDefExpression: + case MetaName.CExtensionDefLightShaft: + case MetaName.CExtensionDefLightEffect: + case MetaName.CExtensionDefDoor: + case MetaName.CExtensionDefWindDisturbance: + case MetaName.CExtensionDefProcObject: + case MetaName.CLightAttrDef: + case MetaName.STRING: + //case MetaName.SectionUNKNOWN2: + //case MetaName.SectionUNKNOWN3: + //case MetaName.SectionUNKNOWN8: + case MetaName.POINTER: + case MetaName.UINT: + case MetaName.VECTOR4: + break; + default: + break; + } + } + + + + + //MetaTypes.ParseMetaData(Meta); + + + + + + + + + + + + + //RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + //if (resentry == null) + //{ + // throw new Exception("File entry wasn't a resource! (is it binary data?)"); + //} + + //ResourceDataReader rd = new ResourceDataReader(resentry, data); + + //Meta = rd.ReadBlock(); + + //MetaTypes.EnsureMetaTypes(Meta); + + //MetaTypes.ParseMetaData(Meta); + + } + + + } + + + + + + +} diff --git a/GameFiles/FileTypes/YvrFile.cs b/GameFiles/FileTypes/YvrFile.cs new file mode 100644 index 0000000..6c93216 --- /dev/null +++ b/GameFiles/FileTypes/YvrFile.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YvrFile : GameFile, PackedFile + { + public VehicleRecordList Records { get; set; } + + public YvrFile() : base(null, GameFileType.Yvr) + { + } + public YvrFile(RpfFileEntry entry) : base(entry, GameFileType.Yvr) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + //MemoryUsage = 0; + + try + { + Records = rd.ReadBlock(); + + } + catch (Exception ex) + { + string err = ex.ToString(); + } + + + + Loaded = true; + + } + + + } +} diff --git a/GameFiles/FileTypes/YwrFile.cs b/GameFiles/FileTypes/YwrFile.cs new file mode 100644 index 0000000..cace6fb --- /dev/null +++ b/GameFiles/FileTypes/YwrFile.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class YwrFile : GameFile, PackedFile + { + public WaypointRecordList Waypoints { get; set; } + + public YwrFile() : base(null, GameFileType.Ywr) + { + } + public YwrFile(RpfFileEntry entry) : base(entry, GameFileType.Ywr) + { + } + + public void Load(byte[] data, RpfFileEntry entry) + { + Name = entry.Name; + RpfFileEntry = entry; + + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + if (resentry == null) + { + throw new Exception("File entry wasn't a resource! (is it binary data?)"); + } + + ResourceDataReader rd = new ResourceDataReader(resentry, data); + + //MemoryUsage = 0; + + try + { + Waypoints = rd.ReadBlock(); + + } + catch (Exception ex) + { + string err = ex.ToString(); + } + + + + Loaded = true; + + } + + + } +} diff --git a/GameFiles/GameFile.cs b/GameFiles/GameFile.cs new file mode 100644 index 0000000..146edf3 --- /dev/null +++ b/GameFiles/GameFile.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public abstract class GameFile : Cacheable + { + public volatile bool Loaded = false; + public volatile bool LoadQueued = false; + public RpfFileEntry RpfFileEntry { get; set; } + public string Name { get; set; } + public string FilePath { get; set; } //used by the project form. + public GameFileType Type { get; set; } + + + + public GameFile(RpfFileEntry entry, GameFileType type) + { + RpfFileEntry = entry; + Type = type; + MemoryUsage = (entry != null) ? entry.FileSize : 0; + if (entry is RpfResourceFileEntry) + { + var resent = entry as RpfResourceFileEntry; + var newuse = resent.SystemSize + resent.GraphicsSize; + MemoryUsage = newuse; + } + else if (entry is RpfBinaryFileEntry) + { + var binent = entry as RpfBinaryFileEntry; + var newuse = binent.FileUncompressedSize; + if (newuse > MemoryUsage) + { + MemoryUsage = newuse; + } + } + else + { + } + } + + public override string ToString() + { + return (string.IsNullOrEmpty(Name)) ? JenkIndex.GetString(Key.Hash) : Name; + } + + + } + + + public enum GameFileType : int + { + Ydd = 0, + Ydr = 1, + Yft = 2, + Ymap = 3, + Ymf = 4, + Ymt = 5, + Ytd = 6, + Ytyp = 7, + Ybn = 8, + Ycd = 9, + Ypt = 10, + Ynd = 11, + Ynv = 12, + Rel = 13, + Ywr = 14, + Yvr = 15, + } + +} diff --git a/GameFiles/GameFileCache.cs b/GameFiles/GameFileCache.cs new file mode 100644 index 0000000..a7f3f32 --- /dev/null +++ b/GameFiles/GameFileCache.cs @@ -0,0 +1,2537 @@ +using CodeWalker.Properties; +using SharpDX; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.GameFiles +{ + public class GameFileCache + { + public RpfManager RpfMan; + private Action UpdateStatus; + private Action ErrorLog; + public long CurrentMemoryUsage = 0; + public int MaxItemsPerLoop = 1; //to keep things flowing... + public bool ItemsStillPending = false; //whether or not we need another content thread loop + + private ConcurrentStack requestQueue = new ConcurrentStack(); + + ////dynamic cache + private Cache mainCache = new Cache(Settings.Default.CacheSize, Settings.Default.CacheTime);//2GB + public volatile bool IsInited = false; + + private volatile bool archetypesLoaded = false; + private Dictionary archetypeDict = new Dictionary(); + private Dictionary textureLookup = new Dictionary(); + private Dictionary textureParents; + + private object updateSyncRoot = new object(); + private object requestSyncRoot = new object(); + private object textureSyncRoot = new object(); //for the texture lookup. + + + + + + + //static indexes + public Dictionary YdrDict { get; private set; } + public Dictionary YddDict { get; private set; } + public Dictionary YtdDict { get; private set; } + public Dictionary YmapDict { get; private set; } + public Dictionary YftDict { get; private set; } + public Dictionary YbnDict { get; private set; } + public Dictionary YcdDict { get; private set; } + public Dictionary YnvDict { get; private set; } + + + public Dictionary AllYmapsDict { get; private set; } + + + //static cached data loaded at init + public Dictionary YtypDict { get; set; } + + public List AllCacheFiles { get; set; } + public Dictionary YmapHierarchyDict { get; set; } + + public List AllManifests { get; set; } + + + public bool EnableDlc { get; set; } = false;//true;// + public bool EnableMods { get; set; } = false; + + public List DlcPaths { get; set; } = new List(); + public List DlcActiveRpfs { get; set; } = new List(); + public List DlcSetupFiles { get; set; } = new List(); + public List DlcExtraFolderMounts { get; set; } = new List(); + public Dictionary DlcPatchedPaths { get; set; } = new Dictionary(); + public List DlcCacheFileList { get; set; } = new List(); + public List DlcNameList { get; set; } = new List(); + public string SelectedDlc { get; set; } = string.Empty; + + public Dictionary ActiveMapRpfFiles { get; set; } = new Dictionary(); + + public Dictionary TimeCycleModsDict = new Dictionary(); + + public List BaseRpfs { get; private set; } + public List AllRpfs { get; private set; } + public List DlcRpfs { get; private set; } + + public bool DoFullStringIndex = false; + + private bool PreloadedMode = false; + + + + public void Clear() + { + IsInited = false; + + mainCache.Clear(); + + textureLookup.Clear(); + GameFile queueclear; + while (requestQueue.TryPop(out queueclear)) + { } //empty the old queue out... + } + + public void Init(Action updateStatus, Action errorLog) + { + UpdateStatus = updateStatus; + ErrorLog = errorLog; + + Clear(); + + + if (RpfMan == null) + { + + + SelectedDlc = Settings.Default.DLC; + EnableDlc = !string.IsNullOrEmpty(SelectedDlc); + EnableMods = Settings.Default.EnableMods; + + + + RpfMan = new RpfManager(); + RpfMan.ExcludePaths = GetExcludePaths(); + RpfMan.EnableMods = EnableMods; + RpfMan.Init(Settings.Default.GTAFolder, UpdateStatus, ErrorLog);//, true); + + //RE test area! + //DecodeRelFiles(); + + + InitGlobal(); + + InitDlc(); + + + //TestYmaps(); + //TestPlacements(); + //TestDrawables(); + //GetArchetypeTimesList(); + //string typestr = PsoTypes.GetTypesString(); + } + else + { + GC.Collect(); //try free up some of the previously used memory.. + } + + UpdateStatus("Scan complete"); + + + IsInited = true; + } + public void Init(Action updateStatus, Action errorLog, List allRpfs) + { + UpdateStatus = updateStatus; + ErrorLog = errorLog; + + Clear(); + + PreloadedMode = true; + EnableDlc = false; + EnableMods = false; + RpfMan = new RpfManager(); //try not to use this in this mode... + RpfMan.Init(allRpfs); + + AllRpfs = allRpfs; + BaseRpfs = allRpfs; + DlcRpfs = new List(); + + InitGlobalDicts(); + + InitGtxds(); + + InitArchetypeDicts(); + + IsInited = true; + } + + private void InitGlobal() + { + BaseRpfs = GetModdedRpfList(RpfMan.BaseRpfs); + AllRpfs = GetModdedRpfList(RpfMan.AllRpfs); + DlcRpfs = GetModdedRpfList(RpfMan.DlcRpfs); + + UpdateStatus("Building global dictionaries..."); + InitGlobalDicts(); + } + + private void InitDlc() + { + + UpdateStatus("Building DLC List..."); + InitDlcList(); + + UpdateStatus("Building active RPF dictionary..."); + InitActiveMapRpfFiles(); + + UpdateStatus("Building map dictionaries..."); + InitMapDicts(); + + UpdateStatus("Loading manifests..."); + InitManifestDicts(); + + UpdateStatus("Loading global texture list..."); + InitGtxds(); + + UpdateStatus("Loading cache..."); + InitMapCaches(); + + UpdateStatus("Loading archetypes..."); + InitArchetypeDicts(); + + UpdateStatus("Loading strings..."); + InitStringDicts(); + } + + private void InitDlcList() + { + //if (!EnableDlc) return; + + string dlclistpath = "update\\update.rpf\\common\\data\\dlclist.xml"; + //if (!EnableDlc) + //{ + // dlclistpath = "common.rpf\\data\\dlclist.xml"; + //} + var dlclistxml = RpfMan.GetFileXml(dlclistpath); + + DlcPaths.Clear(); + if (dlclistxml == null) + { + ErrorLog("InitDlcList: Couldn't load " + dlclistpath + "."); + } + else + { + foreach (XmlNode pathsnode in dlclistxml.DocumentElement) + { + foreach (XmlNode itemnode in pathsnode.ChildNodes) + { + DlcPaths.Add(itemnode.InnerText.ToLower().Replace('\\', '/').Replace("platform:", "x64")); + } + } + } + + + //get dlc path names in the appropriate format for reference by the dlclist paths + Dictionary dlcDict = new Dictionary(); + Dictionary dlcDict2 = new Dictionary(); + foreach (RpfFile dlcrpf in DlcRpfs) + { + if (dlcrpf == null) continue; + if (dlcrpf.NameLower == "dlc.rpf") + { + string path = GetDlcRpfVirtualPath(dlcrpf.Path); + string name = GetDlcNameFromPath(dlcrpf.Path); + dlcDict[path] = dlcrpf; + dlcDict2[name] = dlcrpf; + } + } + + + + + //find all the paths for patched files in update.rpf and build the dict + DlcPatchedPaths.Clear(); + string updrpfpath = "update\\update.rpf"; + var updrpffile = RpfMan.FindRpfFile(updrpfpath); + + if (updrpffile != null) + { + XmlDocument updsetupdoc = RpfMan.GetFileXml(updrpfpath + "\\setup2.xml"); + DlcSetupFile updsetupfile = new DlcSetupFile(); + updsetupfile.Load(updsetupdoc); + + XmlDocument updcontentdoc = RpfMan.GetFileXml(updrpfpath + "\\" + updsetupfile.datFile); + DlcContentFile updcontentfile = new DlcContentFile(); + updcontentfile.Load(updcontentdoc); + + updsetupfile.DlcFile = updrpffile; + updsetupfile.ContentFile = updcontentfile; + updcontentfile.DlcFile = updrpffile; + + updsetupfile.deviceName = "update"; + updcontentfile.LoadDicts(updsetupfile, RpfMan, this); + + if (updcontentfile.ExtraTitleUpdates != null) + { + foreach (var tumount in updcontentfile.ExtraTitleUpdates.Mounts) + { + var lpath = tumount.path.ToLower(); + var relpath = lpath.Replace('/', '\\').Replace("update:\\", ""); + var dlcname = GetDlcNameFromPath(relpath); + RpfFile dlcfile; + dlcDict2.TryGetValue(dlcname, out dlcfile); + if (dlcfile == null) + { continue; } + var dlcpath = dlcfile.Path + "\\"; + var files = updrpffile.GetFiles(relpath, true); + foreach (var file in files) + { + if (file == null) continue; + var fpath = file.Path; + var frelpath = fpath.Replace(updrpfpath, "update:").Replace('\\', '/').Replace(lpath, dlcpath).Replace('/', '\\'); + if (frelpath.StartsWith("mods\\")) + { + frelpath = frelpath.Substring(5); + } + DlcPatchedPaths[frelpath] = fpath; + } + } + } + } + else + { + ErrorLog("InitDlcList: update.rpf not found!"); + } + + + + + DlcSetupFiles.Clear(); + DlcExtraFolderMounts.Clear(); + + foreach (string path in DlcPaths) + { + RpfFile dlcfile; + if (dlcDict.TryGetValue(path, out dlcfile)) + { + try + { + string setuppath = GetDlcPatchedPath(dlcfile.Path + "\\setup2.xml"); + XmlDocument setupdoc = RpfMan.GetFileXml(setuppath); + DlcSetupFile setupfile = new DlcSetupFile(); + setupfile.Load(setupdoc); + + string contentpath = GetDlcPatchedPath(dlcfile.Path + "\\" + setupfile.datFile); + XmlDocument contentdoc = RpfMan.GetFileXml(contentpath); + DlcContentFile contentfile = new DlcContentFile(); + contentfile.Load(contentdoc); + + setupfile.DlcFile = dlcfile; + setupfile.ContentFile = contentfile; + contentfile.DlcFile = dlcfile; + + contentfile.LoadDicts(setupfile, RpfMan, this); + foreach (var extramount in contentfile.ExtraMounts.Values) + { + DlcExtraFolderMounts.Add(extramount); + } + + DlcSetupFiles.Add(setupfile); + + } + catch (Exception ex) + { + ErrorLog("InitDlcList: Error processing DLC " + path + "\n" + ex.ToString()); + } + } + } + + //load the DLC in the correct order.... + DlcSetupFiles = DlcSetupFiles.OrderBy(o => o.order).ToList(); + + + DlcNameList.Clear(); + foreach (var sfile in DlcSetupFiles) + { + if ((sfile == null) || (sfile.DlcFile == null)) continue; + DlcNameList.Add(GetDlcNameFromPath(sfile.DlcFile.Path)); + } + } + + private void InitImagesMetas() + { + //currently not used.. + + ////parse images.meta + //string imagesmetapath = "common.rpf\\data\\levels\\gta5\\images.meta"; + //if (EnableDlc) + //{ + // imagesmetapath = "update\\update.rpf\\common\\data\\levels\\gta5\\images.meta"; + //} + //var imagesmetaxml = RpfMan.GetFileXml(imagesmetapath); + //var imagesnodes = imagesmetaxml.DocumentElement.ChildNodes; + //List imagedatafilelist = new List(); + //Dictionary imagedatafiles = new Dictionary(); + //foreach (XmlNode node in imagesnodes) + //{ + // DlcContentDataFile datafile = new DlcContentDataFile(node); + // string fname = datafile.filename.ToLower(); + // fname = fname.Replace('\\', '/'); + // imagedatafiles[fname] = datafile; + // imagedatafilelist.Add(datafile); + //} + + + //filter ActiveMapFiles based on images.meta? + + //DlcContentDataFile imagesdata; + //if (imagedatafiles.TryGetValue(path, out imagesdata)) + //{ + // ActiveMapRpfFiles[path] = baserpf; + //} + } + + private void InitActiveMapRpfFiles() + { + ActiveMapRpfFiles.Clear(); + + foreach (RpfFile baserpf in BaseRpfs) //start with all the base rpf's (eg x64a.rpf) + { + string path = baserpf.Path.Replace('\\', '/'); + if (path == "common.rpf") + { + ActiveMapRpfFiles["common"] = baserpf; + } + else + { + int bsind = path.IndexOf('/'); + if ((bsind > 0) && (bsind < path.Length)) + { + path = "x64" + path.Substring(bsind); + + //if (ActiveMapRpfFiles.ContainsKey(path)) + //{ } //x64d.rpf\levels\gta5\generic\cutsobjects.rpf // x64g.rpf\levels\gta5\generic\cutsobjects.rpf - identical? + + ActiveMapRpfFiles[path] = baserpf; + } + else + { + //do we need to include root rpf files? generally don't seem to contain map data? + //ActiveMapRpfFiles[path] = baserpf; + } + } + } + + if (!EnableDlc) return; //don't continue for base title only + + + DlcActiveRpfs.Clear(); + DlcCacheFileList.Clear(); + + //int maxdlcorder = 10000000; + + Dictionary> overlays = new Dictionary>(); + + foreach(var setupfile in DlcSetupFiles) + { + if(setupfile.DlcFile!=null) + { + //if (setupfile.order > maxdlcorder) + // break; + + var contentfile = setupfile.ContentFile; + var dlcfile = setupfile.DlcFile; + + DlcActiveRpfs.Add(dlcfile); + + string dlcname = GetDlcNameFromPath(dlcfile.Path); + + + + foreach (var rpfkvp in contentfile.RpfDataFiles) + { + string umpath = GetDlcUnmountedPath(rpfkvp.Value.filename); + string phpath = GetDlcRpfPhysicalPath(umpath, setupfile); + + //if (rpfkvp.Value.overlay) + AddDlcOverlayRpf(rpfkvp.Key, umpath, setupfile, overlays); + + AddDlcActiveMapRpfFile(rpfkvp.Key, phpath); + } + + + + + DlcExtraFolderMountFile extramount; + DlcContentDataFile rpfdatafile; + + + foreach (var changeset in contentfile.contentChangeSets) + { + if (changeset.useCacheLoader) + { + uint cachehash = JenkHash.GenHash(changeset.changeSetName.ToLower()); + string cachefilename = dlcname + "_" + cachehash.ToString() + "_cache_y.dat"; + string cachefilepath = dlcfile.Path + "\\x64\\data\\cacheloaderdata_dlc\\" + cachefilename; + string cachefilepathpatched = GetDlcPatchedPath(cachefilepath); + DlcCacheFileList.Add(cachefilepathpatched); + + //if ((changeset.mapChangeSetData != null) && (changeset.mapChangeSetData.Count > 0)) + //{ } + //else + //{ } + } + else + { + //if ((changeset.mapChangeSetData != null) && (changeset.mapChangeSetData.Count > 0)) + //{ } + //if (changeset.executionConditions != null) + //{ } + } + //if (changeset.filesToInvalidate != null) + //{ }//not used + //if (changeset.filesToDisable != null) + //{ }//not used + if (changeset.filesToEnable != null) + { + foreach (string file in changeset.filesToEnable) + { + string dfn = GetDlcPlatformPath(file).ToLower(); + if (contentfile.ExtraMounts.TryGetValue(dfn, out extramount)) + { + //foreach (var rpfkvp in contentfile.RpfDataFiles) + //{ + // string umpath = GetDlcUnmountedPath(rpfkvp.Value.filename); + // string phpath = GetDlcRpfPhysicalPath(umpath, setupfile); + // //if (rpfkvp.Value.overlay) + // AddDlcOverlayRpf(rpfkvp.Key, umpath, setupfile, overlays); + // AddDlcActiveMapRpfFile(rpfkvp.Key, phpath); + //} + } + else if (contentfile.RpfDataFiles.TryGetValue(dfn, out rpfdatafile)) + { + string phpath = GetDlcRpfPhysicalPath(rpfdatafile.filename, setupfile); + + //if (rpfdatafile.overlay) + AddDlcOverlayRpf(dfn, rpfdatafile.filename, setupfile, overlays); + + AddDlcActiveMapRpfFile(dfn, phpath); + } + else + { + if (dfn.EndsWith(".rpf")) + { } + } + } + } + if (changeset.executionConditions != null) + { } + + if (changeset.mapChangeSetData != null) + { + foreach (var mapcs in changeset.mapChangeSetData) + { + //if (mapcs.mapChangeSetData != null) + //{ }//not used + if (mapcs.filesToInvalidate != null) + { + foreach (string file in mapcs.filesToInvalidate) + { + string upath = GetDlcMountedPath(file); + string fpath = GetDlcPlatformPath(upath); + if (fpath.EndsWith(".rpf")) + { + RemoveDlcActiveMapRpfFile(fpath, overlays); + } + else + { } //how to deal with individual files? milo_.interior + } + } + if (mapcs.filesToDisable != null) + { } + if (mapcs.filesToEnable != null) + { + foreach (string file in mapcs.filesToEnable) + { + string fpath = GetDlcPlatformPath(file); + string umpath = GetDlcUnmountedPath(fpath); + string phpath = GetDlcRpfPhysicalPath(umpath, setupfile); + + if (fpath != umpath) + { } + + AddDlcOverlayRpf(fpath, umpath, setupfile, overlays); + + AddDlcActiveMapRpfFile(fpath, phpath); + } + } + } + } + } + + + + + if (dlcname == SelectedDlc) + { + break; //everything's loaded up to the selected DLC. + } + + } + } + } + + private void AddDlcActiveMapRpfFile(string vpath, string phpath) + { + vpath = vpath.ToLower(); + phpath = phpath.ToLower(); + if (phpath.EndsWith(".rpf")) + { + RpfFile rpffile = RpfMan.FindRpfFile(phpath); + if (rpffile != null) + { + ActiveMapRpfFiles[vpath] = rpffile; + } + else + { } + } + else + { } //how to handle individual files? eg interiorProxies.meta + } + private void AddDlcOverlayRpf(string path, string umpath, DlcSetupFile setupfile, Dictionary> overlays) + { + string opath = GetDlcOverlayPath(umpath, setupfile); + if (opath == path) return; + List overlayList; + if (!overlays.TryGetValue(opath, out overlayList)) + { + overlayList = new List(); + overlays[opath] = overlayList; + } + overlayList.Add(path); + } + private void RemoveDlcActiveMapRpfFile(string vpath, Dictionary> overlays) + { + List overlayList; + if (overlays.TryGetValue(vpath, out overlayList)) + { + foreach (string overlayPath in overlayList) + { + if (ActiveMapRpfFiles.ContainsKey(overlayPath)) + { + ActiveMapRpfFiles.Remove(overlayPath); + } + else + { } + } + overlays.Remove(vpath); + } + + if (ActiveMapRpfFiles.ContainsKey(vpath)) + { + ActiveMapRpfFiles.Remove(vpath); + } + else + { } //nothing to remove? + } + private string GetDlcRpfPhysicalPath(string path, DlcSetupFile setupfile) + { + string devname = setupfile.deviceName.ToLower(); + string fpath = GetDlcPlatformPath(path).ToLower(); + string kpath = fpath.Replace(devname + ":\\", ""); + string dlcpath = setupfile.DlcFile.Path; + fpath = fpath.Replace(devname + ":", dlcpath); + fpath = fpath.Replace("x64:", dlcpath + "\\x64").Replace('/', '\\'); + return GetDlcPatchedPath(fpath); + } + private string GetDlcOverlayPath(string path, DlcSetupFile setupfile) + { + string devname = setupfile.deviceName.ToLower(); + string fpath = path.Replace("%PLATFORM%", "x64").Replace('\\', '/').ToLower(); + string opath = fpath.Replace(devname + ":/", ""); + return opath; + } + private string GetDlcRpfVirtualPath(string path) + { + path = path.Replace('\\', '/'); + if (path.StartsWith("mods/")) + { + path = path.Substring(5); + } + if (path.Length > 7) + { + path = path.Substring(0, path.Length - 7);//trim off "dlc.rpf" + } + if (path.StartsWith("x64")) + { + int bsind = path.IndexOf('/'); //replace x64*.rpf + if ((bsind > 0) && (bsind < path.Length)) + { + path = "x64" + path.Substring(bsind); + } + else + { } //no hits here + } + else if (path.StartsWith("update/x64/dlcpacks")) + { + path = path.Replace("update/x64/dlcpacks", "dlcpacks:"); + } + else + { } //no hits here + + return path; + } + private string GetDlcNameFromPath(string path) + { + string[] parts = path.ToLower().Split('\\'); + if (parts.Length > 1) + { + return parts[parts.Length - 2].ToLower(); + } + return path; + } + public static string GetDlcPlatformPath(string path) + { + return path.Replace("%PLATFORM%", "x64").Replace('\\', '/').Replace("platform:", "x64").ToLower(); + } + private string GetDlcMountedPath(string path) + { + foreach (var efm in DlcExtraFolderMounts) + { + foreach (var fm in efm.FolderMounts) + { + if ((fm.platform == null) || (fm.platform == "x64")) + { + if (path.StartsWith(fm.path)) + { + path = path.Replace(fm.path, fm.mountAs); + } + } + } + } + return path; + } + private string GetDlcUnmountedPath(string path) + { + foreach (var efm in DlcExtraFolderMounts) + { + foreach (var fm in efm.FolderMounts) + { + if ((fm.platform == null) || (fm.platform == "x64")) + { + if (path.StartsWith(fm.mountAs)) + { + path = path.Replace(fm.mountAs, fm.path); + } + } + } + } + return path; + } + public string GetDlcPatchedPath(string path) + { + string p; + if (DlcPatchedPaths.TryGetValue(path, out p)) + { + return p; + } + return path; + } + + private List GetModdedRpfList(List list) + { + //if (!EnableMods) return new List(list); + List rlist = new List(); + RpfFile f; + if (!EnableMods) + { + foreach (var file in list) + { + if (!file.Path.StartsWith("mods")) + { + rlist.Add(file); + } + } + } + else + { + foreach (var file in list) + { + if (RpfMan.ModRpfDict.TryGetValue(file.Path, out f)) + { + rlist.Add(f); + } + else + { + if (file.Path.StartsWith("mods")) + { + var basepath = file.Path.Substring(5); + if (!RpfMan.RpfDict.ContainsKey(basepath)) //this file isn't overriding anything + { + rlist.Add(file); + } + } + else + { + rlist.Add(file); + } + } + } + } + return rlist; + } + + + private void InitGlobalDicts() + { + YdrDict = new Dictionary(); + YddDict = new Dictionary(); + YtdDict = new Dictionary(); + YftDict = new Dictionary(); + YcdDict = new Dictionary(); + foreach (var rpffile in AllRpfs) + { + if (rpffile.AllEntries == null) continue; + foreach (var entry in rpffile.AllEntries) + { + if (entry is RpfFileEntry) + { + RpfFileEntry fentry = entry as RpfFileEntry; + if (entry.NameLower.EndsWith(".ydr")) + { + YdrDict[entry.NameHash] = fentry; //replaces any existing entries... + YdrDict[entry.ShortNameHash] = fentry; + } + else if (entry.NameLower.EndsWith(".ydd")) + { + YddDict[entry.NameHash] = fentry; //replaces any existing entries... + YddDict[entry.ShortNameHash] = fentry; + } + else if (entry.NameLower.EndsWith(".ytd")) + { + YtdDict[entry.NameHash] = fentry; //replaces any existing entries... + YtdDict[entry.ShortNameHash] = fentry; + } + else if (entry.NameLower.EndsWith(".yft")) + { + YftDict[entry.NameHash] = fentry; + YftDict[entry.ShortNameHash] = fentry; + } + else if (entry.NameLower.EndsWith(".ycd")) + { + YcdDict[entry.NameHash] = fentry; + YcdDict[entry.ShortNameHash] = fentry; + } + } + } + } + + } + + private void InitMapDicts() + { + YmapDict = new Dictionary(); + YbnDict = new Dictionary(); + YnvDict = new Dictionary(); + foreach (var rpffile in ActiveMapRpfFiles.Values) //RpfMan.BaseRpfs) + { + if (rpffile.AllEntries == null) continue; + foreach (var entry in rpffile.AllEntries) + { + if (entry is RpfFileEntry) + { + RpfFileEntry fentry = entry as RpfFileEntry; + if (entry.NameLower.EndsWith(".ymap")) + { + //YmapDict[entry.NameHash] = fentry; + YmapDict[entry.ShortNameHash] = fentry; + } + else if (entry.NameLower.EndsWith(".ybn")) + { + //YbnDict[entry.NameHash] = fentry; + YbnDict[entry.ShortNameHash] = fentry; + } + else if (entry.NameLower.EndsWith(".ynv")) + { + YnvDict[entry.ShortNameHash] = fentry; + } + } + } + } + + AllYmapsDict = new Dictionary(); + foreach (var rpffile in AllRpfs) + { + if (rpffile.AllEntries == null) continue; + foreach (var entry in rpffile.AllEntries) + { + if (entry is RpfFileEntry) + { + RpfFileEntry fentry = entry as RpfFileEntry; + if (entry.NameLower.EndsWith(".ymap")) + { + AllYmapsDict[entry.ShortNameHash] = fentry; + } + } + } + } + + } + + private void InitManifestDicts() + { + AllManifests = new List(); + foreach (RpfFile file in ActiveMapRpfFiles.Values) //RpfMan.BaseRpfs) + { + if (file.AllEntries == null) continue; + //manifest and meta parsing.. + foreach (RpfEntry entry in file.AllEntries) + { + //sp_manifest.ymt + //if (entry.NameLower.EndsWith("zonebind.ymt")/* || entry.Name.EndsWith("vinewood.ymt")*/) + //{ + // YmtFile ymt = GetFile(entry); + //} + if (entry.Name.EndsWith(".ymf"))// || entry.Name.EndsWith(".ymt")) + { + UpdateStatus(string.Format(entry.Path)); + YmfFile ymffile = RpfMan.GetFile(entry); + if (ymffile != null) + { + AllManifests.Add(ymffile); + + if (ymffile.Pso != null) + { } + else if (ymffile.Rbf != null) + { } + else if (ymffile.Meta != null) + { } + else + { } + } + } + + } + + } + } + + private void InitGtxds() + { + + Dictionary parentTxds = new Dictionary(); + + IEnumerable rpfs = PreloadedMode ? AllRpfs : (IEnumerable)ActiveMapRpfFiles.Values; + + foreach (RpfFile file in rpfs) + { + if (file.AllEntries == null) continue; + foreach (RpfEntry entry in file.AllEntries) + { + try + { + if (entry.NameLower == "gtxd.ymt") + { + YmtFile ymt = RpfMan.GetFile(entry); + if (ymt.CMapParentTxds != null) + { + foreach (var kvp in ymt.CMapParentTxds) + { + uint chash = JenkHash.GenHash(kvp.Key.ToLower()); + uint phash = JenkHash.GenHash(kvp.Value.ToLower()); + if (!parentTxds.ContainsKey(chash)) + { + parentTxds.Add(chash, phash); + } + else + { + } + } + } + } + else if (entry.NameLower == "gtxd.meta") //these still need to be handled! + { + } + } + catch (Exception ex) + { + string errstr = entry.Path + "\n" + ex.ToString(); + ErrorLog(errstr); + } + } + } + + if (EnableDlc) + { + //foreach (var dlcfile in DlcActiveRpfs) + //{ + // foreach (RpfEntry entry in dlcfile.AllEntries) + // { + // try + // { + // if (entry.NameLower == "gtxd.meta") //these still need to be handled! + // { + // //update\x64\dlcpacks\mpheist\dlc.rpf + // //update\x64\dlcpacks\mpluxe\dlc.rpf + // } + // } + // catch (Exception ex) + // { + // string errstr = entry.Path + "\n" + ex.ToString(); + // ErrorLog(errstr); + // } + // } + //} + } + + + textureParents = parentTxds; + + + + + //ensure global texture dicts: + YtdFile ytd1 = new YtdFile(GetYtdEntry(JenkHash.GenHash("mapdetail"))); + LoadFile(ytd1); + AddTextureLookups(ytd1); + + YtdFile ytd2 = new YtdFile(GetYtdEntry(JenkHash.GenHash("vehshare"))); + LoadFile(ytd2); + AddTextureLookups(ytd2); + + YtdFile ytd3 = new YtdFile(GetYtdEntry(JenkHash.GenHash("vehshare_worn"))); + LoadFile(ytd3); + AddTextureLookups(ytd3); + + YtdFile ytd4 = new YtdFile(GetYtdEntry(JenkHash.GenHash("vehshare_army"))); + LoadFile(ytd4); + AddTextureLookups(ytd4); + + YtdFile ytd5 = new YtdFile(GetYtdEntry(JenkHash.GenHash("vehshare_truck"))); + LoadFile(ytd5); + AddTextureLookups(ytd5); + + + } + + private void InitMapCaches() + { + AllCacheFiles = new List(); + YmapHierarchyDict = new Dictionary(); + + string cachefilepath = "common.rpf\\data\\gta5_cache_y.dat"; + if (EnableDlc) + { + cachefilepath = "update\\update.rpf\\common\\data\\gta5_cache_y.dat"; + } + + try + { + var maincache = RpfMan.GetFile(cachefilepath); + if (maincache != null) + { + AllCacheFiles.Add(maincache); + foreach (var node in maincache.AllMapNodes) + { + if (YmapDict.ContainsKey(node.Name)) + { + YmapHierarchyDict[node.Name] = node; + } + else + { } //ymap not found... + } + } + else + { + ErrorLog(cachefilepath + ": cache not loaded! Possibly an unsupported GTAV installation version."); + } + } + catch (Exception ex) + { + ErrorLog(cachefilepath + ": " + ex.ToString()); + } + + + if (EnableDlc) + { + foreach (string dlccachefile in DlcCacheFileList) + { + try + { + var dat = RpfMan.GetFile(dlccachefile); + if (dat == null) + { continue; } //update\\x64\\dlcpacks\\mpspecialraces\\dlc.rpf\\x64\\data\\cacheloaderdata_dlc\\mpspecialraces_3336915258_cache_y.dat + AllCacheFiles.Add(dat); + foreach (var node in dat.AllMapNodes) + { + if (YmapDict.ContainsKey(node.Name)) + { + YmapHierarchyDict[node.Name] = node; + } + else + { } //ymap not found... + } + } + catch (Exception ex) + { + string errstr = dlccachefile + "\n" + ex.ToString(); + ErrorLog(errstr); + } + + } + + //foreach (var dlcfile in DlcActiveRpfs) + //{ + // foreach (RpfEntry entry in dlcfile.AllEntries) + // { + // try + // { + // if (entry.NameLower.EndsWith("_cache_y.dat")) + // { + // var dat = RpfMan.GetFile(entry); + // AllCacheFiles.Add(dat); + // foreach (var node in dat.AllMapNodes) + // { + // if (YmapDict.ContainsKey(node.Name)) + // { + // YmapHierarchyDict[node.Name] = node; + // } + // else + // { } //ymap not found... + // } + // } + // } + // catch (Exception ex) + // { + // string errstr = entry.Path + "\n" + ex.ToString(); + // ErrorLog(errstr); + // } + // } + //} + } + + + + + + //foreach (RpfFile file in RpfMan.BaseRpfs) + //{ + // if (file.AllEntries == null) continue; + // foreach (RpfEntry entry in file.AllEntries) + // { + // try + // { + // //if (entry.Name.EndsWith("_manifest.ymf")) + // //{ + // // var ymf = GetFile(entry); + // //} + // //else + // if (entry.NameLower.EndsWith("_cache_y.dat")) + // { + // //parse the cache dat files. + // var dat = RpfMan.GetFile(entry); + // AllCacheFiles.Add(dat); + // foreach (var node in dat.AllMapNodes) + // { + // YmapHierarchyDict[node.Name] = node; + // } + // } + // } + // catch (Exception ex) + // { + // string errstr = entry.Path + "\n" + ex.ToString(); + // ErrorLog(errstr); + // } + // } + //} + } + + private void InitArchetypeDicts() + { + + YtypDict = new Dictionary(); + + archetypesLoaded = false; + archetypeDict.Clear(); + + + var rpfs = EnableDlc ? AllRpfs : BaseRpfs; + + foreach (RpfFile file in rpfs) //RpfMan.BaseRpfs)RpfMan.AllRpfs)//ActiveMapRpfFiles.Values) // + { + if (file.AllEntries == null) continue; + if (!EnableDlc && file.Path.StartsWith("update")) continue; + + //parse ytyps + foreach (RpfEntry entry in file.AllEntries) + { + try + { + if (entry.NameLower.EndsWith(".ytyp")) + { + AddYtypToDictionary(entry); + } + } + catch (Exception ex) + { + ErrorLog(entry.Path + ": " + ex.Message); + } + } + } + + archetypesLoaded = true; + + } + + private void AddYtypToDictionary(RpfEntry entry) + { + UpdateStatus(string.Format(entry.Path)); + YtypFile ytypfile = RpfMan.GetFile(entry); + if (ytypfile == null) + { + throw new Exception("Couldn't load ytyp file."); //couldn't load the file for some reason... shouldn't happen.. + } + if (ytypfile.Meta == null) + { + throw new Exception("ytyp file was not in meta format."); + } + if (YtypDict.ContainsKey(ytypfile.NameHash)) + { + //throw new Exception("ytyp " + JenkIndex.GetString(ytypfile.NameHash) + " already loaded."); + //errorAction(entry.Path + ": ytyp " + JenkIndex.GetString(ytypfile.NameHash) + " already loaded."); + YtypDict[ytypfile.NameHash] = ytypfile; //override ytyp and continue anyway, could be unique archetypes in here still... + } + else + { + YtypDict.Add(ytypfile.NameHash, ytypfile); + } + + + + if ((ytypfile.AllArchetypes == null) || (ytypfile.AllArchetypes.Length == 0)) + { + ErrorLog(entry.Path + ": no archetypes found"); + } + else + { + foreach (var arch in ytypfile.AllArchetypes) + { + uint hash = arch.Hash; + if (hash == 0) continue; + if (archetypeDict.ContainsKey(hash)) + { + var oldval = archetypeDict[hash]; //replace old archetype? + } + archetypeDict[hash] = arch; + } + } + + + ////if (ytypfile.AudioEmitters != null) + ////{ + //// foreach (CExtensionDefAudioEmitter emitter in ytypfile.AudioEmitters) + //// { + //// //audioind++; + //// //uint hash = emitter.name; + //// //if (hash == 0) hash = archetype.name; + //// //if (hash == 0) + //// // continue; + //// //if (AudioArchetypes.ContainsKey(hash)) + //// //{ + //// // var oldval = AudioArchetypes[hash]; + //// // //errorAction(entry.Path + ": " + emitter.ToString() + ": (CTimeArchetypeDef) Already in archetype dict. Was in: " + oldval.ToString()); + //// // //overwrite with new definition? how to tell? + //// // AudioArchetypes[hash] = new Tuple(ytypfile, audioind); + //// //} + //// //else + //// //{ + //// // AudioArchetypes.Add(hash, new Tuple(ytypfile, audioind)); + //// //} + //// } + ////} + + } + + public void InitStringDicts() + { + string langstr = "american_rel"; //todo: make this variable? + + if (!DoFullStringIndex) + { + string globalgxt2path = "x64b.rpf\\data\\lang\\" + langstr + ".rpf\\global.gxt2"; + var globalgxt2 = RpfMan.GetFile(globalgxt2path); + if (globalgxt2 != null) + { + for (int i = 0; i < globalgxt2.TextEntries.Length; i++) + { + var e = globalgxt2.TextEntries[i]; + GlobalText.Ensure(e.Text, e.Hash); + } + } + return; + } + + + List gxt2files = new List(); + foreach (var rpf in AllRpfs) + { + foreach (var entry in rpf.AllEntries) + { + if (entry.NameLower.EndsWith(".gxt2") && entry.Path.Contains(langstr)) + { + var gxt2 = RpfMan.GetFile(entry); + if (gxt2 != null) + { + for (int i = 0; i < gxt2.TextEntries.Length; i++) + { + var e = gxt2.TextEntries[i]; + GlobalText.Ensure(e.Text, e.Hash); + } + gxt2files.Add(gxt2); + } + } + } + } + + GlobalText.FullIndexBuilt = true; + + + + + + foreach (var rpf in AllRpfs) + { + foreach (var entry in rpf.AllEntries) + { + if (entry.NameLower.EndsWith("statssetup.xml")) + { + var xml = RpfMan.GetFileXml(entry.Path); + if (xml == null) + { continue; } + + var statnodes = xml.SelectNodes("StatsSetup/stats/stat"); + + foreach (XmlNode statnode in statnodes) + { + if (statnode == null) + { continue; } + var statname = Xml.GetStringAttribute(statnode, "Name"); + if (string.IsNullOrEmpty(statname)) + { continue; } + + var statnamel = statname.ToLower(); + StatsNames.Ensure(statname); + StatsNames.Ensure(statnamel); + + StatsNames.Ensure("sp_" + statnamel); + StatsNames.Ensure("mp0_" + statnamel); + StatsNames.Ensure("mp1_" + statnamel); + + } + } + } + } + + StatsNames.FullIndexBuilt = true; + } + + + + public bool SetDlcLevel(string dlc, bool enable) + { + bool dlcchange = (dlc != SelectedDlc); + bool enablechange = (enable != EnableDlc); + bool change = (dlcchange && enable) || enablechange; + + if (change) + { + lock (updateSyncRoot) + { + lock (textureSyncRoot) + { + SelectedDlc = dlc; + EnableDlc = enable; + + //mainCache.Clear(); + ClearCachedMaps(); + + InitDlc(); + } + } + } + + return change; + } + + public bool SetModsEnabled(bool enable) + { + bool change = (enable != EnableMods); + + if (change) + { + lock (updateSyncRoot) + { + lock (textureSyncRoot) + { + EnableMods = enable; + RpfMan.EnableMods = enable; + + mainCache.Clear(); + + InitGlobal(); + InitDlc(); + } + } + } + + return change; + } + + + private void ClearCachedMaps() + { + if (AllYmapsDict != null) + { + foreach (var ymap in AllYmapsDict.Values) + { + GameFileCacheKey k = new GameFileCacheKey(ymap.ShortNameHash, GameFileType.Ymap); + mainCache.Remove(k); + } + } + } + + + + private void TryLoadEnqueue(GameFile gf) + { + if (((!gf.Loaded)) && (requestQueue.Count < 5))//(!gf.LoadQueued) && + { + requestQueue.Push(gf); + gf.LoadQueued = true; + } + } + + + public Archetype GetArchetype(uint hash) + { + if (!archetypesLoaded) return null; + Archetype arch = null; + archetypeDict.TryGetValue(hash, out arch); + return arch; + } + public MapDataStoreNode GetMapNode(uint hash) + { + if (!IsInited) return null; + MapDataStoreNode node = null; + YmapHierarchyDict.TryGetValue(hash, out node); + return node; + } + + public YdrFile GetYdr(uint hash) + { + if (!IsInited) return null; + lock (requestSyncRoot) + { + var key = new GameFileCacheKey(hash, GameFileType.Ydr); + YdrFile ydr = mainCache.TryGet(key) as YdrFile; + if (ydr == null) + { + var e = GetYdrEntry(hash); + if (e != null) + { + ydr = new YdrFile(e); + if (mainCache.TryAdd(key, ydr)) + { + TryLoadEnqueue(ydr); + } + else + { + ydr.LoadQueued = false; + //ErrorLog("Out of cache space - couldn't load drawable: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else + { + //ErrorLog("Drawable not found: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else if (!ydr.Loaded) + { + TryLoadEnqueue(ydr); + } + return ydr; + } + } + public YddFile GetYdd(uint hash) + { + if (!IsInited) return null; + lock (requestSyncRoot) + { + var key = new GameFileCacheKey(hash, GameFileType.Ydd); + YddFile ydd = mainCache.TryGet(key) as YddFile; + if (ydd == null) + { + var e = GetYddEntry(hash); + if (e != null) + { + ydd = new YddFile(e); + if (mainCache.TryAdd(key, ydd)) + { + TryLoadEnqueue(ydd); + } + else + { + ydd.LoadQueued = false; + //ErrorLog("Out of cache space - couldn't load drawable dictionary: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else + { + //ErrorLog("Drawable dictionary not found: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else if(!ydd.Loaded) + { + TryLoadEnqueue(ydd); + } + return ydd; + } + } + public YtdFile GetYtd(uint hash) + { + if (!IsInited) return null; + lock (requestSyncRoot) + { + var key = new GameFileCacheKey(hash, GameFileType.Ytd); + YtdFile ytd = mainCache.TryGet(key) as YtdFile; + if (ytd == null) + { + var e = GetYtdEntry(hash); + if (e != null) + { + ytd = new YtdFile(e); + if (mainCache.TryAdd(key, ytd)) + { + TryLoadEnqueue(ytd); + } + else + { + ytd.LoadQueued = false; + //ErrorLog("Out of cache space - couldn't load texture dictionary: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else + { + //ErrorLog("Texture dictionary not found: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else if (!ytd.Loaded) + { + TryLoadEnqueue(ytd); + } + return ytd; + } + } + public YmapFile GetYmap(uint hash) + { + if (!IsInited) return null; + lock (requestSyncRoot) + { + var key = new GameFileCacheKey(hash, GameFileType.Ymap); + YmapFile ymap = mainCache.TryGet(key) as YmapFile; + if (ymap == null) + { + var e = GetYmapEntry(hash); + if (e != null) + { + ymap = new YmapFile(e); + if (mainCache.TryAdd(key, ymap)) + { + TryLoadEnqueue(ymap); + } + else + { + ymap.LoadQueued = false; + //ErrorLog("Out of cache space - couldn't load ymap: " + JenkIndex.GetString(hash)); + } + } + else + { + //ErrorLog("Ymap not found: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else if (!ymap.Loaded) + { + TryLoadEnqueue(ymap); + } + return ymap; + } + } + public YftFile GetYft(uint hash) + { + if (!IsInited) return null; + lock (requestSyncRoot) + { + var key = new GameFileCacheKey(hash, GameFileType.Yft); + YftFile yft = mainCache.TryGet(key) as YftFile; + if (yft == null) + { + var e = GetYftEntry(hash); + if (e != null) + { + yft = new YftFile(e); + if (mainCache.TryAdd(key, yft)) + { + TryLoadEnqueue(yft); + } + else + { + yft.LoadQueued = false; + //ErrorLog("Out of cache space - couldn't load yft: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else + { + //ErrorLog("Yft not found: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else if (!yft.Loaded) + { + TryLoadEnqueue(yft); + } + return yft; + } + } + public YbnFile GetYbn(uint hash) + { + if (!IsInited) return null; + lock (requestSyncRoot) + { + var key = new GameFileCacheKey(hash, GameFileType.Ybn); + YbnFile ybn = mainCache.TryGet(key) as YbnFile; + if (ybn == null) + { + var e = GetYbnEntry(hash); + if (e != null) + { + ybn = new YbnFile(e); + if (mainCache.TryAdd(key, ybn)) + { + TryLoadEnqueue(ybn); + } + else + { + ybn.LoadQueued = false; + //ErrorLog("Out of cache space - couldn't load ybn: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else + { + //ErrorLog("Ybn not found: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else if (!ybn.Loaded) + { + TryLoadEnqueue(ybn); + } + return ybn; + } + } + public YcdFile GetYcd(uint hash) + { + if (!IsInited) return null; + lock (requestSyncRoot) + { + var key = new GameFileCacheKey(hash, GameFileType.Ycd); + YcdFile ycd = mainCache.TryGet(key) as YcdFile; + if (ycd == null) + { + var e = GetYcdEntry(hash); + if (e != null) + { + ycd = new YcdFile(e); + if (mainCache.TryAdd(key, ycd)) + { + TryLoadEnqueue(ycd); + } + else + { + ycd.LoadQueued = false; + //ErrorLog("Out of cache space - couldn't load ycd: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else + { + //ErrorLog("Ycd not found: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else if (!ycd.Loaded) + { + TryLoadEnqueue(ycd); + } + return ycd; + } + } + public YnvFile GetYnv(uint hash) + { + if (!IsInited) return null; + lock (requestSyncRoot) + { + var key = new GameFileCacheKey(hash, GameFileType.Ynv); + YnvFile ynv = mainCache.TryGet(key) as YnvFile; + if (ynv == null) + { + var e = GetYnvEntry(hash); + if (e != null) + { + ynv = new YnvFile(e); + if (mainCache.TryAdd(key, ynv)) + { + TryLoadEnqueue(ynv); + } + else + { + ynv.LoadQueued = false; + //ErrorLog("Out of cache space - couldn't load ycd: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else + { + //ErrorLog("Ycd not found: " + JenkIndex.GetString(hash)); //too spammy... + } + } + else if (!ynv.Loaded) + { + TryLoadEnqueue(ynv); + } + return ynv; + } + } + + + public RpfFileEntry GetYdrEntry(uint hash) + { + RpfFileEntry entry; + YdrDict.TryGetValue(hash, out entry); + return entry; + } + public RpfFileEntry GetYddEntry(uint hash) + { + RpfFileEntry entry; + YddDict.TryGetValue(hash, out entry); + return entry; + } + public RpfFileEntry GetYtdEntry(uint hash) + { + RpfFileEntry entry; + YtdDict.TryGetValue(hash, out entry); + return entry; + } + public RpfFileEntry GetYmapEntry(uint hash) + { + RpfFileEntry entry; + if (!YmapDict.TryGetValue(hash, out entry)) + { + AllYmapsDict.TryGetValue(hash, out entry); + } + return entry; + } + public RpfFileEntry GetYftEntry(uint hash) + { + RpfFileEntry entry; + YftDict.TryGetValue(hash, out entry); + return entry; + } + public RpfFileEntry GetYbnEntry(uint hash) + { + RpfFileEntry entry; + YbnDict.TryGetValue(hash, out entry); + return entry; + } + public RpfFileEntry GetYcdEntry(uint hash) + { + RpfFileEntry entry; + YcdDict.TryGetValue(hash, out entry); + return entry; + } + public RpfFileEntry GetYnvEntry(uint hash) + { + RpfFileEntry entry; + YnvDict.TryGetValue(hash, out entry); + return entry; + } + + + + public bool LoadFile(T file) where T:GameFile,PackedFile + { + if (file == null) return false; + RpfFileEntry entry = file.RpfFileEntry; + if (entry != null) + { + return RpfMan.LoadFile(file, entry); + } + return false; + } + + + public void InitYmapEntityArchetypes(YmapFile file) + { + if (file == null) return; + if (file.AllEntities != null) + { + for (int i = 0; i < file.AllEntities.Length; i++) + { + var ent = file.AllEntities[i]; + var arch = GetArchetype(ent.CEntityDef.archetypeName); + ent.SetArchetype(arch); + + if (ent.MloData != null) + { + var entities = ent.MloData.AllEntities; + if (entities != null) + { + for (int j = 0; j < entities.Length; j++) + { + var ient = entities[j]; + var iarch = GetArchetype(ient.CEntityDef.archetypeName); + ient.SetArchetype(iarch); + if (iarch == null) + { } //can't find archetype - des stuff eg {des_prologue_door} + } + } + } + + } + } + if (file.GrassInstanceBatches != null) + { + for (int i = 0; i < file.GrassInstanceBatches.Length; i++) + { + var batch = file.GrassInstanceBatches[i]; + batch.Archetype = GetArchetype(batch.Batch.archetypeName); + } + } + + if (file.TimeCycleModifiers != null) + { + for (int i = 0; i < file.TimeCycleModifiers.Length; i++) + { + var tcm = file.TimeCycleModifiers[i]; + World.TimecycleMod wtcm; + if (TimeCycleModsDict.TryGetValue(tcm.CTimeCycleModifier.name.Hash, out wtcm)) + { + tcm.TimeCycleModData = wtcm; + } + } + } + + } + + + + + public void ContentThreadProc() + { + Monitor.Enter(updateSyncRoot); + + GameFile req; + //bool loadedsomething = false; + + int itemcount = 0; + + while (requestQueue.TryPop(out req) && (itemcount < MaxItemsPerLoop)) + { + //process content requests. + if (req.Loaded) + continue; //it's already loaded... (somehow) + + if ((req.LastUseTime - DateTime.Now).TotalSeconds > 0.5) + continue; //hasn't been requested lately..! ignore, will try again later if necessary + + itemcount++; + //if (!loadedsomething) + //{ + //UpdateStatus("Loading " + req.RpfFileEntry.Name + "..."); + //} + + switch (req.Type) + { + case GameFileType.Ydr: + req.Loaded = LoadFile(req as YdrFile); + break; + case GameFileType.Ydd: + req.Loaded = LoadFile(req as YddFile); + break; + case GameFileType.Ytd: + req.Loaded = LoadFile(req as YtdFile); + if (req.Loaded) AddTextureLookups(req as YtdFile); + break; + case GameFileType.Ymap: + req.Loaded = LoadFile(req as YmapFile); + if (req.Loaded) InitYmapEntityArchetypes(req as YmapFile); + break; + case GameFileType.Yft: + req.Loaded = LoadFile(req as YftFile); + break; + case GameFileType.Ybn: + req.Loaded = LoadFile(req as YbnFile); + break; + case GameFileType.Ycd: + req.Loaded = LoadFile(req as YcdFile); + break; + case GameFileType.Ynv: + req.Loaded = LoadFile(req as YnvFile); + break; + default: + break; + } + + string str = (req.Loaded ? "Loaded " : "Error loading ") + req.ToString(); + //string str = string.Format("{0}: {1}: {2}", requestQueue.Count, (req.Loaded ? "Loaded" : "Error loading"), req); + + UpdateStatus(str); + //ErrorLog(str); + if (!req.Loaded) + { + ErrorLog("Error loading " + req.ToString()); + } + + + //loadedsomething = true; + } + + ItemsStillPending = (itemcount >= MaxItemsPerLoop); + + + Monitor.Exit(updateSyncRoot); + } + + + + + + + private void AddTextureLookups(YtdFile ytd) + { + if (ytd == null) return; + if (ytd.TextureDict == null) return; + if (ytd.TextureDict.TextureNameHashes == null) return; + + lock (textureSyncRoot) + { + foreach (uint hash in ytd.TextureDict.TextureNameHashes) + { + textureLookup[hash] = ytd.RpfFileEntry; + } + + } + } + public YtdFile TryGetTextureDictForTexture(uint hash) + { + lock (textureSyncRoot) + { + RpfFileEntry e; + if (textureLookup.TryGetValue(hash, out e)) + { + return GetYtd(e.ShortNameHash); + } + + } + return null; + } + public YtdFile TryGetParentYtd(uint hash) + { + uint phash; + if(textureParents.TryGetValue(hash, out phash)) + { + return GetYtd(phash); + } + return null; + } + public uint TryGetParentYtdHash(uint hash) + { + uint phash = 0; + textureParents.TryGetValue(hash, out phash); + return phash; + } + + public Texture TryFindTextureInParent(uint texhash, uint txdhash) + { + Texture tex = null; + + var ytd = TryGetParentYtd(txdhash); + while ((ytd != null) && (ytd.Loaded) && (ytd.TextureDict != null) && (tex == null)) + { + tex = ytd.TextureDict.Lookup(texhash); + if (tex == null) + { + ytd = TryGetParentYtd(ytd.Key.Hash); + } + } + + return tex; + } + + + + + + + + + + + private string[] GetExcludePaths() + { + string[] exclpaths = Settings.Default.ExcludeFolders.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + if (exclpaths.Length > 0) + { + for (int i = 0; i < exclpaths.Length; i++) + { + exclpaths[i] = exclpaths[i].ToLower(); + } + } + else + { + exclpaths = null; + } + return exclpaths; + } + + + + + + + + public void TestYmaps() + { + foreach (RpfFile file in AllRpfs) + { + foreach (RpfEntry entry in file.AllEntries) + { + try + { + if (entry.NameLower.EndsWith(".ymap")) + { + UpdateStatus(string.Format(entry.Path)); + YmapFile ymapfile = RpfMan.GetFile(entry); + if ((ymapfile != null))// && (ymapfile.Meta != null)) + { } + } + } + catch (Exception ex) + { + UpdateStatus("Error! " + ex.ToString()); + } + } + } + } + public void TestPlacements() + { + //int totplacements = 0; + //int tottimedplacements = 0; + //int totaudioplacements = 0; + //StringBuilder sbtest = new StringBuilder(); + //StringBuilder sbterr = new StringBuilder(); + //sbtest.AppendLine("X, Y, Z, name, assetName, drawableDictionary, textureDictionary, ymap"); + //foreach (RpfFile file in RpfMan.AllRpfs) + //{ + // foreach (RpfEntry entry in file.AllEntries) + // { + // try + // { + // if (entry.NameLower.EndsWith(".ymap")) + // { + // UpdateStatus(string.Format(entry.Path)); + // YmapFile ymapfile = RpfMan.GetFile(entry); + // if ((ymapfile != null))// && (ymapfile.Meta != null)) + // { + // //if (ymapfile.CMapData.parent == 0) //root ymap output + // //{ + // // sbtest.AppendLine(JenkIndex.GetString(ymapfile.CMapData.name) + ": " + entry.Path); + // //} + // if (ymapfile.CEntityDefs != null) + // { + // for (int n = 0; n < ymapfile.CEntityDefs.Length; n++) + // { + // //find ytyp... + // var entdef = ymapfile.CEntityDefs[n]; + // var pos = entdef.position; + // bool istimed = false; + // Tuple archetyp; + // if (!BaseArchetypes.TryGetValue(entdef.archetypeName, out archetyp)) + // { + // sbterr.AppendLine("Couldn't find ytyp for " + entdef.ToString()); + // } + // else + // { + // int ymapbasecount = (archetyp.Item1.CBaseArchetypeDefs != null) ? archetyp.Item1.CBaseArchetypeDefs.Length : 0; + // int baseoffset = archetyp.Item2 - ymapbasecount; + // if (baseoffset >= 0) + // { + // if ((archetyp.Item1.CTimeArchetypeDefs == null) || (baseoffset > archetyp.Item1.CTimeArchetypeDefs.Length)) + // { + // sbterr.AppendLine("Couldn't lookup CTimeArchetypeDef... " + archetyp.ToString()); + // continue; + // } + + // istimed = true; + + // //it's a CTimeArchetypeDef... + // CTimeArchetypeDef ctad = archetyp.Item1.CTimeArchetypeDefs[baseoffset]; + + // //if (ctad.ToString().Contains("spider")) + // //{ + // //} + // //sbtest.AppendFormat("{0}, {1}, {2}, {3}, {4}", pos.X, pos.Y, pos.Z, ctad.ToString(), entry.Name); + // //sbtest.AppendLine(); + + // tottimedplacements++; + // } + // totplacements++; + // } + + // Tuple audiotyp; + // if (AudioArchetypes.TryGetValue(entdef.archetypeName, out audiotyp)) + // { + // if (istimed) + // { + // } + // if (!BaseArchetypes.TryGetValue(entdef.archetypeName, out archetyp)) + // { + // sbterr.AppendLine("Couldn't find ytyp for " + entdef.ToString()); + // } + // if (audiotyp.Item1 != archetyp.Item1) + // { + // } + + // CBaseArchetypeDef cbad = archetyp.Item1.CBaseArchetypeDefs[archetyp.Item2]; + // CExtensionDefAudioEmitter emitr = audiotyp.Item1.AudioEmitters[audiotyp.Item2]; + + // if (emitr.name != cbad.name) + // { + // } + + // string hashtest = JenkIndex.GetString(emitr.effectHash); + + // sbtest.AppendFormat("{0}, {1}, {2}, {3}, {4}, {5}", pos.X, pos.Y, pos.Z, cbad.ToString(), entry.Name, hashtest); + // sbtest.AppendLine(); + + // totaudioplacements++; + // } + + // } + // } + + // //if (ymapfile.TimeCycleModifiers != null) + // //{ + // // for (int n = 0; n < ymapfile.TimeCycleModifiers.Length; n++) + // // { + // // var tcmod = ymapfile.TimeCycleModifiers[n]; + // // Tuple archetyp; + // // if (BaseArchetypes.TryGetValue(tcmod.name, out archetyp)) + // // { + // // } + // // else + // // { + // // } + // // } + // //} + // } + // } + // } + // catch (Exception ex) + // { + // sbterr.AppendLine(entry.Path + ": " + ex.ToString()); + // } + // } + //} + + //UpdateStatus("Ymap scan finished."); + + //sbtest.AppendLine(); + //sbtest.AppendLine(totplacements.ToString() + " total CEntityDef placements parsed"); + //sbtest.AppendLine(tottimedplacements.ToString() + " total CTimeArchetypeDef placements"); + //sbtest.AppendLine(totaudioplacements.ToString() + " total CExtensionDefAudioEmitter placements"); + + //string teststr = sbtest.ToString(); + //string testerr = sbterr.ToString(); + + //return; + } + public void TestDrawables() + { + + + DateTime starttime = DateTime.Now; + + bool doydr = false; + bool doydd = false; + bool doyft = true; + + List errs = new List(); + Dictionary vdecls = new Dictionary(); + Dictionary vdecluse = new Dictionary(); + int drawablecount = 0; + foreach (RpfFile file in AllRpfs) + { + foreach (RpfEntry entry in file.AllEntries) + { + try + { + if (doydr && entry.NameLower.EndsWith(".ydr")) + { + UpdateStatus(entry.Path); + YdrFile ydr = RpfMan.GetFile(entry); + + if (ydr == null) + { + errs.Add(entry.Path + ": Couldn't read file"); + continue; + } + if (ydr.Drawable == null) + { + errs.Add(entry.Path + ": Couldn't read drawable data"); + continue; + } + drawablecount++; + foreach (var kvp in ydr.Drawable.VertexDecls) + { + if (!vdecls.ContainsKey(kvp.Key)) + { + vdecls.Add(kvp.Key, kvp.Value); + vdecluse.Add(kvp.Key, 1); + } + else + { + vdecluse[kvp.Key]++; + } + } + } + else if (doydd & entry.NameLower.EndsWith(".ydd")) + { + UpdateStatus(entry.Path); + YddFile ydd = RpfMan.GetFile(entry); + + if (ydd == null) + { + errs.Add(entry.Path + ": Couldn't read file"); + continue; + } + if (ydd.Dict == null) + { + errs.Add(entry.Path + ": Couldn't read drawable dictionary data"); + continue; + } + foreach (var drawable in ydd.Dict.Values) + { + drawablecount++; + foreach (var kvp in drawable.VertexDecls) + { + if (!vdecls.ContainsKey(kvp.Key)) + { + vdecls.Add(kvp.Key, kvp.Value); + vdecluse.Add(kvp.Key, 1); + } + else + { + vdecluse[kvp.Key]++; + } + } + } + } + else if (doyft && entry.NameLower.EndsWith(".yft")) + { + UpdateStatus(entry.Path); + YftFile yft = RpfMan.GetFile(entry); + + if (yft == null) + { + errs.Add(entry.Path + ": Couldn't read file"); + continue; + } + if (yft.Fragment == null) + { + errs.Add(entry.Path + ": Couldn't read fragment data"); + continue; + } + if (yft.Fragment.Drawable != null) + { + drawablecount++; + foreach (var kvp in yft.Fragment.Drawable.VertexDecls) + { + if (!vdecls.ContainsKey(kvp.Key)) + { + vdecls.Add(kvp.Key, kvp.Value); + vdecluse.Add(kvp.Key, 1); + } + else + { + vdecluse[kvp.Key]++; + } + } + } + if ((yft.Fragment.Clothes != null) && (yft.Fragment.Clothes.data_items != null)) + { + foreach (var cloth in yft.Fragment.Clothes.data_items) + { + drawablecount++; + foreach (var kvp in cloth.Drawable.VertexDecls) + { + if (!vdecls.ContainsKey(kvp.Key)) + { + vdecls.Add(kvp.Key, kvp.Value); + vdecluse.Add(kvp.Key, 1); + } + else + { + vdecluse[kvp.Key]++; + } + } + } + } + if ((yft.Fragment.Unknown_28h_Data != null) && (yft.Fragment.Unknown_28h_Data.data_items != null)) + { + foreach (var drawable in yft.Fragment.Unknown_28h_Data.data_items) + { + drawablecount++; + foreach (var kvp in drawable.VertexDecls) + { + if (!vdecls.ContainsKey(kvp.Key)) + { + vdecls.Add(kvp.Key, kvp.Value); + vdecluse.Add(kvp.Key, 1); + } + else + { + vdecluse[kvp.Key]++; + } + } + } + } + + } + + } + catch (Exception ex) + { + errs.Add(entry.Path + ": " + ex.ToString()); + } + } + } + + + string errstr = string.Join("\r\n", errs); + + + + //build vertex types code string + errs.Clear(); + StringBuilder sbverts = new StringBuilder(); + foreach (var kvp in vdecls) + { + var vd = kvp.Value; + int usage = vdecluse[kvp.Key]; + sbverts.AppendFormat("public struct VertexType{0} //id: {1}, stride: {2}, flags: {3}, types: {4}, refs: {5}", vd.Flags, kvp.Key, vd.Stride, vd.Flags, vd.Types, usage); + sbverts.AppendLine(); + sbverts.AppendLine("{"); + uint compid = 1; + for (int i = 0; i < 16; i++) + { + if (((vd.Flags >> i) & 1) == 1) + { + string typestr = "Unknown"; + uint type = (uint)((vd.Types >> (4 * i)) & 0xF); + switch (type) + { + case 0: typestr = "ushort"; break;// Data[i] = new ushort[1 * count]; break; + case 1: typestr = "ushort2"; break;// Data[i] = new ushort[2 * count]; break; + case 2: typestr = "ushort3"; break;// Data[i] = new ushort[3 * count]; break; + case 3: typestr = "ushort4"; break;// Data[i] = new ushort[4 * count]; break; + case 4: typestr = "float"; break;// Data[i] = new float[1 * count]; break; + case 5: typestr = "Vector2"; break;// Data[i] = new float[2 * count]; break; + case 6: typestr = "Vector3"; break;// Data[i] = new float[3 * count]; break; + case 7: typestr = "Vector4"; break;// Data[i] = new float[4 * count]; break; + case 8: typestr = "uint"; break;// Data[i] = new uint[count]; break; + case 9: typestr = "uint"; break;// Data[i] = new uint[count]; break; + case 10: typestr = "uint"; break;// Data[i] = new uint[count]; break; + default: + break; + } + sbverts.AppendLine(" public " + typestr + " Component" + compid.ToString() + ";"); + compid++; + } + + } + sbverts.AppendLine("}"); + sbverts.AppendLine(); + } + + string vertstr = sbverts.ToString(); + string verrstr = string.Join("\r\n", errs); + + UpdateStatus((DateTime.Now - starttime).ToString() + " elapsed, " + drawablecount.ToString() + " drawables, " + errs.Count.ToString() + " errors."); + + } + public void GetArchetypeTimesList() + { + + StringBuilder sb = new StringBuilder(); + sb.AppendLine("Name,AssetName,12am,1am,2am,3am,4am,5am,6am,7am,8am,9am,10am,11am,12pm,1pm,2pm,3pm,4pm,5pm,6pm,7pm,8pm,9pm,10pm,11pm,+12am,+1am,+2am,+3am,+4am,+5am,+6am,+7am"); + foreach (var ytyp in YtypDict.Values) + { + foreach (var arch in ytyp.AllArchetypes) + { + if (arch.IsTimeArchetype) + { + var t = arch.TimeArchetype.timeFlags; + sb.Append(arch.TimeArchetype.CBaseArchetypeDef.name.ToString()); + sb.Append(","); + sb.Append(arch.TimeArchetype.CBaseArchetypeDef.assetName.ToString()); + sb.Append(","); + for (int i = 0; i < 32; i++) + { + bool v = ((t >> i) & 1) == 1; + sb.Append(v ? "1" : "0"); + sb.Append(","); + } + sb.AppendLine(); + } + } + } + + var csv = sb.ToString(); + + + + } + + public void DecodeRelFiles() + { + UpdateStatus("Decoding REL files"); + + StringBuilder sb = new StringBuilder(); + StringBuilder sbh = new StringBuilder(); + + foreach (RpfFile rpf in RpfMan.AllRpfs) + { + foreach (RpfEntry entry in rpf.AllEntries) + { + RpfFileEntry rfe = entry as RpfFileEntry; + if (rfe == null) continue; + + if (rfe.NameLower.EndsWith(".rel")) + { + RelFile rel = new RelFile(rfe); + RpfMan.LoadFile(rel, rfe); + + if (rel.NameTable == null) + { + sb.AppendLine(rfe.Path + ": no strings found"); + } + else + { + sb.AppendLine(rfe.Path + ": " + rel.NameTable.Length.ToString() + " strings found:"); + foreach (string str in rel.NameTable) + { + sb.AppendLine(str); + } + } + if (rel.IndexStrings != null) + { + sb.AppendLine("Config-specific:"); + foreach (var unk in rel.IndexStrings) + { + sb.AppendLine(unk.ToString()); + } + } + if (rel.IndexHashes != null) + { + sbh.AppendLine(rfe.Path + ": " + rel.IndexHashes.Length.ToString() + " entries:"); + foreach (var unk in rel.IndexHashes) + { + sbh.Append(unk.Name.Hash.ToString("X8")); + string strval; + if (JenkIndex.Index.TryGetValue(unk.Name, out strval)) + { + sbh.Append(" - "); + sbh.Append(strval); + } + sbh.AppendLine(); + //sbh.AppendLine(unk.ToString()); + } + sbh.AppendLine(); + } + if (rel.Unk05Hashes != null) + { + sbh.AppendLine(rfe.Path + ": " + rel.Unk05Hashes.Length.ToString() + " Hashes1:"); + foreach (var unk in rel.Unk05Hashes) + { + sbh.Append(unk.Hash.ToString("X8")); + string strval; + if (JenkIndex.Index.TryGetValue(unk, out strval)) + { + sbh.Append(" - "); + sbh.Append(strval); + } + sbh.AppendLine(); + } + sbh.AppendLine(); + } + if (rel.Unk06Hashes != null) + { + sbh.AppendLine(rfe.Path + ": " + rel.Unk06Hashes.Length.ToString() + " Hashes2:"); + foreach (var unk in rel.Unk06Hashes) + { + sbh.Append(unk.Hash.ToString("X8")); + string strval; + if (JenkIndex.Index.TryGetValue(unk, out strval)) + { + sbh.Append(" - "); + sbh.Append(strval); + } + sbh.AppendLine(); + } + sbh.AppendLine(); + } + + sb.AppendLine(); + } + + } + + } + + string relstrs = sb.ToString(); + string hashstrs = sbh.ToString(); + + } + + } + + public struct GameFileCacheKey + { + public uint Hash { get; set; } + public GameFileType Type { get; set; } + + public GameFileCacheKey(uint hash, GameFileType type) + { + Hash = hash; + Type = type; + } + } + + +} diff --git a/GameFiles/MetaTypes/Meta.cs b/GameFiles/MetaTypes/Meta.cs new file mode 100644 index 0000000..ac5198f --- /dev/null +++ b/GameFiles/MetaTypes/Meta.cs @@ -0,0 +1,641 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Meta : ResourceFileBase + { + public override long BlockLength + { + get { return 112; } + } + + // structure data + public int Unknown_10h { get; set; } = 0x50524430; + public short Unknown_14h { get; set; } = 0x0079; + public byte HasUselessData { get; set; } + public byte Unknown_17h { get; set; } = 0x00; + public int Unknown_18h { get; set; } = 0x00000000; + public int RootBlockIndex { get; set; } + public long StructureInfosPointer { get; set; } + public long EnumInfosPointer { get; set; } + public long DataBlocksPointer { get; set; } + public long NamePointer { get; set; } + public long UselessPointer { get; set; } + public short StructureInfosCount { get; set; } + public short EnumInfosCount { get; set; } + public short DataBlocksCount { get; set; } + public short Unknown_4Eh { get; set; } = 0x0000; + public uint Unknown_50h { get; set; } = 0x00000000; + public uint Unknown_54h { get; set; } = 0x00000000; + public uint Unknown_58h { get; set; } = 0x00000000; + public uint Unknown_5Ch { get; set; } = 0x00000000; + public uint Unknown_60h { get; set; } = 0x00000000; + public uint Unknown_64h { get; set; } = 0x00000000; + public uint Unknown_68h { get; set; } = 0x00000000; + public uint Unknown_6Ch { get; set; } = 0x00000000; + + // reference data + public ResourceSimpleArray StructureInfos { get; set; } + public ResourceSimpleArray EnumInfos { get; set; } + public ResourceSimpleArray DataBlocks { get; set; } + public string Name { get; private set; } + //public string[] Strings { get; set; } + + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadInt32(); + this.Unknown_14h = reader.ReadInt16(); + this.HasUselessData = reader.ReadByte(); + this.Unknown_17h = reader.ReadByte(); + this.Unknown_18h = reader.ReadInt32(); + this.RootBlockIndex = reader.ReadInt32(); + this.StructureInfosPointer = reader.ReadInt64(); + this.EnumInfosPointer = reader.ReadInt64(); + this.DataBlocksPointer = reader.ReadInt64(); + this.NamePointer = reader.ReadInt64(); + this.UselessPointer = reader.ReadInt64(); + this.StructureInfosCount = reader.ReadInt16(); + this.EnumInfosCount = reader.ReadInt16(); + this.DataBlocksCount = reader.ReadInt16(); + this.Unknown_4Eh = reader.ReadInt16(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + + // read reference data + this.StructureInfos = reader.ReadBlockAt>( + (ulong)this.StructureInfosPointer, // offset + this.StructureInfosCount + ); + + this.EnumInfos = reader.ReadBlockAt>( + (ulong)this.EnumInfosPointer, // offset + this.EnumInfosCount + ); + + this.DataBlocks = reader.ReadBlockAt>( + (ulong)this.DataBlocksPointer, // offset + this.DataBlocksCount + ); + + this.Name = reader.ReadStringAt(//BlockAt( + (ulong)this.NamePointer // offset + ); + + //Strings = MetaTypes.GetStrings(this); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + this.StructureInfosPointer = this.StructureInfos?.FilePosition ?? 0; + this.EnumInfosPointer = this.EnumInfos?.FilePosition ?? 0; + this.DataBlocksPointer = this.DataBlocks?.FilePosition ?? 0; + //this.NamePointer = this.Name?.Position ?? 0; //TODO: fix + this.UselessPointer = 0; + this.StructureInfosCount = (short)(this.StructureInfos?.Count ?? 0); + this.EnumInfosCount = (short)(this.EnumInfos?.Count ?? 0); + this.DataBlocksCount = (short)(this.DataBlocks?.Count ?? 0); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.HasUselessData); + writer.Write(this.Unknown_17h); + writer.Write(this.Unknown_18h); + writer.Write(this.RootBlockIndex); + writer.Write(this.StructureInfosPointer); + writer.Write(this.EnumInfosPointer); + writer.Write(this.DataBlocksPointer); + writer.Write(this.NamePointer); + writer.Write(this.UselessPointer); + writer.Write(this.StructureInfosCount); + writer.Write(this.EnumInfosCount); + writer.Write(this.DataBlocksCount); + writer.Write(this.Unknown_4Eh); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if ((StructureInfos != null) && (StructureInfos.Count > 0)) list.Add(StructureInfos); + if ((EnumInfos != null) && (EnumInfos.Count > 0)) list.Add(EnumInfos); + if ((DataBlocks != null) && (DataBlocks.Count > 0)) list.Add(DataBlocks); + //if (Name != null) list.Add(Name); //TODO: fix + return list.ToArray(); + } + + + + + public MetaDataBlock FindBlock(MetaName name) + { + if (DataBlocks == null) return null; + foreach (var block in DataBlocks) + { + if (block.StructureNameHash == name) + { + return block; + } + } + return null; + } + + + public MetaDataBlock GetRootBlock() + { + MetaDataBlock block = null; + var rootind = RootBlockIndex - 1; + if ((rootind >= 0) && (rootind < DataBlocks.Count) && (DataBlocks.Data != null)) + { + block = DataBlocks[rootind]; + } + return block; + } + public MetaDataBlock GetBlock(int id) + { + MetaDataBlock block = null; + var ind = id - 1; + if ((ind >= 0) && (ind < DataBlocks.Count) && (DataBlocks.Data != null)) + { + block = DataBlocks[ind]; + } + return block; + } + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class MetaStructureInfo : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32; } + } + + // structure data + public MetaName StructureNameHash { get; set; } + public uint StructureKey { get; set; } + public uint Unknown_8h { get; set; } + public uint Unknown_Ch { get; set; } = 0x00000000; + public long EntriesPointer { get; private set; } + public int StructureSize { get; set; } + public short Unknown_1Ch { get; set; } = 0x0000; + public short EntriesCount { get; private set; } + + // reference data + public MetaStructureEntryInfo_s[] Entries { get; private set; } + + private ResourceSystemStructBlock EntriesBlock = null; + + + public MetaStructureInfo() + { } + public MetaStructureInfo(MetaName nameHash, uint key, uint unknown, int length, params MetaStructureEntryInfo_s[] entries) + { + StructureNameHash = nameHash; + StructureKey = key; + Unknown_8h = unknown; + StructureSize = length; + Entries = entries; + } + + + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.StructureNameHash = (MetaName)reader.ReadInt32(); + this.StructureKey = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.EntriesPointer = reader.ReadInt64(); + this.StructureSize = reader.ReadInt32(); + this.Unknown_1Ch = reader.ReadInt16(); + this.EntriesCount = reader.ReadInt16(); + + // read reference data + this.Entries = reader.ReadStructsAt((ulong)this.EntriesPointer, (uint)this.EntriesCount); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.EntriesPointer = this.Entries?.Position ?? 0; //TODO: fix + //this.EntriesCount = (short)(this.Entries?.Count ?? 0); + this.EntriesPointer = this.EntriesBlock?.FilePosition ?? 0; //TODO: fix + this.EntriesCount = (short)(this.EntriesBlock?.ItemCount ?? 0); + + // write structure data + writer.Write((int)this.StructureNameHash); + writer.Write(this.StructureKey); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.EntriesPointer); + writer.Write(this.StructureSize); + writer.Write(this.Unknown_1Ch); + writer.Write(this.EntriesCount); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (EntriesBlock == null) + { + EntriesBlock = new ResourceSystemStructBlock(Entries); + } + if (EntriesBlock != null) list.Add(EntriesBlock); + + //if (Entries != null) list.Add(Entries); //TODO: fix + return list.ToArray(); + } + + public override string ToString() + { + return StructureNameHash.ToString(); + } + } + + public enum MetaStructureEntryDataType : byte + { + Boolean = 0x01, + SignedByte = 0x10, + UnsignedByte = 0x11, // OCCURS IN ARRAY + SignedShort = 0x12, + UnsignedShort = 0x13, // OCCURS IN ARRAY + SignedInt = 0x14, + UnsignedInt = 0x15, // OCCURS IN ARRAY + Float = 0x21, // OCCURS IN ARRAY + Float_XYZ = 0x33, // OCCURS IN ARRAY + Float_XYZW = 0x34, + ByteEnum = 0x60, // has enum name hash in info + IntEnum = 0x62, // has enum name hash in info + ShortFlags = 0x64, // has enum name hash in info + IntFlags1 = 0x63, // has enum name hash in info + IntFlags2 = 0x65, // has enum name hash in info (optional?) + Hash = 0x4A, // OCCURS IN ARRAY + Array = 0x52, + ArrayOfChars = 0x40, // has length in info + ArrayOfBytes = 0x50, // has length in info + DataBlockPointer = 0x59, + CharPointer = 0x44, + StructurePointer = 0x07, // OCCURS IN ARRAY + Structure = 0x05 // has structure name hash in info, OCCURS IN ARRAY + } + public static class MetaStructureEntryDataTypes + { + public static string GetCSharpTypeName(MetaStructureEntryDataType t) + { + switch (t) + { + case MetaStructureEntryDataType.Boolean: return "bool"; + case MetaStructureEntryDataType.SignedByte: return "sbyte"; + case MetaStructureEntryDataType.UnsignedByte: return "byte"; + case MetaStructureEntryDataType.SignedShort: return "short"; + case MetaStructureEntryDataType.UnsignedShort: return "ushort"; + case MetaStructureEntryDataType.SignedInt: return "int"; + case MetaStructureEntryDataType.UnsignedInt: return "uint"; + case MetaStructureEntryDataType.Float: return "float"; + case MetaStructureEntryDataType.Float_XYZ: return "Vector3"; + case MetaStructureEntryDataType.Float_XYZW: return "Vector4"; + + case MetaStructureEntryDataType.Hash: return "uint"; //uint hashes... + case MetaStructureEntryDataType.ByteEnum: return "byte"; //convert to enum later.. + case MetaStructureEntryDataType.IntEnum: return "int"; + case MetaStructureEntryDataType.ShortFlags: return "short"; + case MetaStructureEntryDataType.IntFlags1: return "int"; + case MetaStructureEntryDataType.IntFlags2: return "int"; + + case MetaStructureEntryDataType.Array: + case MetaStructureEntryDataType.ArrayOfChars: + case MetaStructureEntryDataType.ArrayOfBytes: + case MetaStructureEntryDataType.DataBlockPointer: + case MetaStructureEntryDataType.CharPointer: + case MetaStructureEntryDataType.StructurePointer: + case MetaStructureEntryDataType.Structure: + default: + return t.ToString(); + } + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct MetaStructureEntryInfo_s + { + // structure data + public MetaName EntryNameHash { get; set; } + public int DataOffset { get; set; } + public MetaStructureEntryDataType DataType { get; set; } + public byte Unknown_9h { get; set; } + public short ReferenceTypeIndex { get; set; } + public MetaName ReferenceKey { get; set; } + + public MetaStructureEntryInfo_s(MetaName nameHash, int dataOffset, MetaStructureEntryDataType dataType, byte unk9h, short referenceTypeIndex, MetaName referenceKey) + { + EntryNameHash = nameHash; + DataOffset = dataOffset; + DataType = dataType; + Unknown_9h = unk9h; + ReferenceTypeIndex = referenceTypeIndex; + ReferenceKey = referenceKey; + } + + public override string ToString() + { + return DataOffset.ToString() + ": " + DataType.ToString() + ": " + ReferenceKey.ToString() + ": " + EntryNameHash.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class MetaEnumInfo : ResourceSystemBlock + { + public override long BlockLength + { + get { return 24; } + } + + // structure data + public MetaName EnumNameHash { get; set; } + public uint EnumKey { get; set; } + public long EntriesPointer { get; private set; } + public int EntriesCount { get; private set; } + public int Unknown_14h { get; set; } = 0x00000000; + + // reference data + //public ResourceSimpleArray Entries; + public MetaEnumEntryInfo_s[] Entries { get; private set; } + + private ResourceSystemStructBlock EntriesBlock = null; + + + public MetaEnumInfo() + { } + public MetaEnumInfo(MetaName nameHash, uint key, params MetaEnumEntryInfo_s[] entries) + { + EnumNameHash = nameHash; + EnumKey = key; + Entries = entries; + } + + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.EnumNameHash = (MetaName)reader.ReadInt32(); + this.EnumKey = reader.ReadUInt32(); + this.EntriesPointer = reader.ReadInt64(); + this.EntriesCount = reader.ReadInt32(); + this.Unknown_14h = reader.ReadInt32(); + + // read reference data + //this.Entries = reader.ReadBlockAt>( + // (ulong)this.EntriesPointer, // offset + // this.EntriesCount + //); + this.Entries = reader.ReadStructsAt((ulong)this.EntriesPointer, (uint)this.EntriesCount); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.EntriesPointer = this.Entries?.Position ?? 0; //TODO: fix + //this.EntriesCount = this.Entries?.Count ?? 0; + this.EntriesPointer = this.EntriesBlock?.FilePosition ?? 0; //TODO: fix + this.EntriesCount = (short)(this.EntriesBlock?.ItemCount ?? 0); + + // write structure data + writer.Write((int)this.EnumNameHash); + writer.Write(this.EnumKey); + writer.Write(this.EntriesPointer); + writer.Write(this.EntriesCount); + writer.Write(this.Unknown_14h); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Entries != null) list.Add(Entries); + if (EntriesBlock == null) + { + EntriesBlock = new ResourceSystemStructBlock(Entries); + } + if (EntriesBlock != null) list.Add(EntriesBlock); + + return list.ToArray(); + } + + public override string ToString() + { + return EnumNameHash.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct MetaEnumEntryInfo_s + { + // structure data + public MetaName EntryNameHash { get; set; } + public int EntryValue { get; set; } + + public MetaEnumEntryInfo_s(MetaName nameHash, int value) + { + EntryNameHash = nameHash; + EntryValue = value; + } + + public override string ToString() + { + return EntryNameHash.ToString() + ": " + EntryValue.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class MetaDataBlock : ResourceSystemBlock + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public MetaName StructureNameHash { get; set; } + public int DataLength { get; set; } + public long DataPointer { get; private set; } + + // reference data + public byte[] Data { get; set; } + private ResourceSystemDataBlock DataBlock = null; + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.StructureNameHash = (MetaName)reader.ReadInt32(); + this.DataLength = reader.ReadInt32(); + this.DataPointer = reader.ReadInt64(); + + + this.Data = reader.ReadBytesAt((ulong)this.DataPointer, (uint)DataLength); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.DataLength = this.Data?.Length ?? 0; + //this.DataPointer = (this.Data!=null)? DataPos : 0; //TODO:fix... + this.DataPointer = this.DataBlock?.FilePosition ?? 0; + + // write structure data + writer.Write((int)this.StructureNameHash); + writer.Write(this.DataLength); + writer.Write(this.DataPointer); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (DataBlock == null) + { + DataBlock = new ResourceSystemDataBlock(Data); + } + if (DataBlock != null) list.Add(DataBlock); + //if (Data != null) list.Add(Data); + return list.ToArray(); + } + + public override string ToString() + { + return StructureNameHash.ToString() + ": " + DataPointer.ToString() + " (" + DataLength.ToString() + ")"; + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct MetaHash + { + public uint Hash { get; set; } + + public string Hex + { + get + { + return Hash.ToString("X").PadLeft(8, '0'); + } + } + + public MetaHash(uint h) { Hash = h; } + + public override string ToString() + { + var str = JenkIndex.TryGetString(Hash); + if (!string.IsNullOrEmpty(str)) return str; + return GlobalText.GetString(Hash); + } + + + public static implicit operator uint(MetaHash h) + { + return h.Hash; //implicit conversion + } + + public static implicit operator MetaHash(uint v) + { + return new MetaHash(v); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct TextHash + { + public uint Hash { get; set; } + + public string Hex + { + get + { + return Hash.ToString("X"); + } + } + + public TextHash(uint h) { Hash = h; } + + public override string ToString() + { + return GlobalText.GetString(Hash); + } + + + public static implicit operator uint(TextHash h) + { + return h.Hash; //implicit conversion + } + + public static implicit operator TextHash(uint v) + { + return new TextHash(v); + } + } + + +} \ No newline at end of file diff --git a/GameFiles/MetaTypes/MetaBuilder.cs b/GameFiles/MetaTypes/MetaBuilder.cs new file mode 100644 index 0000000..e8d435c --- /dev/null +++ b/GameFiles/MetaTypes/MetaBuilder.cs @@ -0,0 +1,377 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class MetaBuilder + { + + List Blocks = new List(); + + int MaxBlockLength = 0x2000; //TODO: figure what this should be! + + + public MetaBuilderBlock EnsureBlock(MetaName type) + { + foreach (var block in Blocks) + { + if (block.StructureNameHash == type) + { + if (block.TotalSize < MaxBlockLength) + { + return block; + } + } + } + MetaBuilderBlock b = new MetaBuilderBlock(); + b.StructureNameHash = type; + b.Index = Blocks.Count; + Blocks.Add(b); + return b; + } + + public MetaBuilderPointer AddItem(MetaName type, T item) where T : struct + { + MetaBuilderBlock block = EnsureBlock(type); + byte[] data = MetaTypes.ConvertToBytes(item); + int brem = data.Length % 16; + if (brem > 0) + { + int newlen = data.Length - brem + 16; + byte[] newdata = new byte[newlen]; + Buffer.BlockCopy(data, 0, newdata, 0, data.Length); + data = newdata; //make sure item size is multiple of 16... so pointers don't need sub offsets! + } + int idx = block.AddItem(data); + MetaBuilderPointer r = new MetaBuilderPointer(); + r.Block = block.Index + 1; + r.Offset = (idx * data.Length) / 16; + r.Length = data.Length; + return r; + } + public MetaBuilderPointer AddItemArray(MetaName type, T[] items) where T : struct + { + MetaBuilderBlock block = EnsureBlock(type); + byte[] data = MetaTypes.ConvertArrayToBytes(items); + int datalen = data.Length; + int newlen = datalen; + int lenrem = newlen % 16; + if (lenrem != 0) + { + newlen += (16 - lenrem); + } + byte[] newdata = new byte[newlen]; + Buffer.BlockCopy(data, 0, newdata, 0, datalen); + int offs = block.TotalSize / 16; + int idx = block.AddItem(newdata); + MetaBuilderPointer r = new MetaBuilderPointer(); + r.Block = block.Index + 1; + r.Offset = offs; //(idx * data.Length) / 16; + r.Length = items.Length; + return r; + } + public MetaBuilderPointer AddString(string str) + { + MetaBuilderBlock block = EnsureBlock(MetaName.STRING); + byte[] data = Encoding.ASCII.GetBytes(str); + int datalen = data.Length; + int newlen = datalen; + int lenrem = newlen % 16; + if (lenrem != 0) //need to pad the data length up to multiple of 16. + { + newlen += (16 - lenrem); + } + byte[] newdata = new byte[newlen]; + Buffer.BlockCopy(data, 0, newdata, 0, datalen); + int offs = block.TotalSize / 16; + int idx = block.AddItem(newdata); + MetaBuilderPointer r = new MetaBuilderPointer(); + r.Block = block.Index + 1; + r.Offset = offs;// (idx * data.Length) / 16;//not sure if this is correct! should also use sub-offset! + r.Length = datalen; //actual length of string. + return r; + } + + public MetaPOINTER AddItemPtr(MetaName type, T item) where T : struct //helper method for AddItem + { + var ptr = AddItem(type, item); + return new MetaPOINTER((ushort)ptr.Block, (ushort)ptr.Offset, 0); + } + public Array_Structure AddItemArrayPtr(MetaName type, T[] items) where T : struct //helper method for AddItemArray + { + if ((items == null) || (items.Length == 0)) return new Array_Structure(); + var ptr = AddItemArray(type, items); + return new Array_Structure(ptr); + } + public Array_uint AddHashArrayPtr(MetaHash[] items) + { + if ((items == null) || (items.Length == 0)) return new Array_uint(); + var ptr = AddItemArray(MetaName.HASH, items); + return new Array_uint(ptr); + } + public Array_ushort AddUshortArrayPtr(ushort[] items) + { + if ((items == null) || (items.Length == 0)) return new Array_ushort(); + var ptr = AddItemArray(MetaName.USHORT, items); + return new Array_ushort(ptr); + } + public CharPointer AddStringPtr(string str) //helper method for AddString + { + var ptr = AddString(str); + return new CharPointer(ptr); + } + + + public Array_StructurePointer AddPointerArray(MetaPOINTER[] arr) + { + if ((arr == null) || (arr.Length == 0)) return new Array_StructurePointer(); + var ptr = AddItemArray(MetaName.POINTER, arr); + Array_StructurePointer sp = new Array_StructurePointer(); + sp.Count1 = (ushort)arr.Length; + sp.Count2 = sp.Count1; + sp.Pointer = ptr.Pointer; + return sp; + } + + public Array_StructurePointer AddItemPointerArrayPtr(MetaName type, T[] items) where T : struct + { + //helper method for creating a pointer array + if ((items == null) || (items.Length == 0)) return new Array_StructurePointer(); + + MetaPOINTER[] ptrs = new MetaPOINTER[items.Length]; + for (int i = 0; i < items.Length; i++) + { + ptrs[i] = AddItemPtr(type, items[i]); + } + return AddPointerArray(ptrs); + + //Array_StructurePointer sp = new Array_StructurePointer(); + //sp.Count1 = (ushort)items.Length; + //sp.Count2 = sp.Count1; + //for (int i = 0; i < items.Length; i++) + //{ + // var item = items[i]; + // var meptr = AddItemPtr(type, item); + // var mptr = AddItem(MetaName.POINTER, meptr); + // if (i == 0) + // { + // sp.Pointer = mptr.Pointer; //main pointer points to the first item. + // } + //} + //return sp; + } + + + public Array_StructurePointer AddWrapperArrayPtr(MetaWrapper[] items) + { + if ((items == null) || (items.Length == 0)) return new Array_StructurePointer(); + + + MetaPOINTER[] ptrs = new MetaPOINTER[items.Length]; + for (int i = 0; i < items.Length; i++) + { + ptrs[i] = items[i].Save(this); + } + return AddPointerArray(ptrs); + + //Array_StructurePointer sp = new Array_StructurePointer(); + //sp.Count1 = (ushort)items.Length; + //sp.Count2 = sp.Count1; + //for (int i = 0; i < items.Length; i++) + //{ + // var item = items[i]; + // var meptr = item.Save(this); + // var mptr = AddItem(MetaName.POINTER, meptr); + // if (i == 0) + // { + // sp.Pointer = mptr.Pointer; //main pointer points to the first item. + // } + //} + //return sp; + } + + public Array_Structure AddWrapperArray(MetaWrapper[] items) + { + if ((items == null) || (items.Length == 0)) return new Array_Structure(); + + var sa = new Array_Structure(); + sa.Count1 = (ushort)items.Length; + sa.Count2 = sa.Count1; + for (int i = 0; i < items.Length; i++) + { + var item = items[i]; + var meptr = item.Save(this); + if (i == 0) + { + MetaBuilderPointer mbp = new MetaBuilderPointer(); + mbp.Block = meptr.BlockID; + mbp.Offset = meptr.ItemOffset; + sa.Pointer = mbp.Pointer; + } + } + return sa; + } + + + public byte[] GetData() + { + int totlen = 0; + for (int i = 0; i < Blocks.Count; i++) + { + totlen += Blocks[i].TotalSize; + } + byte[] data = new byte[totlen]; + int offset = 0; + for (int i = 0; i < Blocks.Count; i++) + { + var block = Blocks[i]; + for (int j = 0; j < block.Items.Count; j++) + { + var bdata = block.Items[j]; + Buffer.BlockCopy(bdata, 0, data, offset, bdata.Length); + offset += bdata.Length; + } + } + if (offset != data.Length) + { } + return data; + } + + + + Dictionary StructureInfos = new Dictionary(); + Dictionary EnumInfos = new Dictionary(); + + public void AddStructureInfo(MetaName name) + { + if (!StructureInfos.ContainsKey(name)) + { + MetaStructureInfo si = MetaTypes.GetStructureInfo(name); + if (si != null) + { + StructureInfos[name] = si; + } + } + } + public void AddEnumInfo(MetaName name) + { + if (!EnumInfos.ContainsKey(name)) + { + MetaEnumInfo ei = MetaTypes.GetEnumInfo(name); + if (ei != null) + { + EnumInfos[name] = ei; + } + } + } + + + + + public Meta GetMeta() + { + Meta m = new Meta(); + m.FileVFT = 0x405bc808; + m.FileUnknown = 1; + m.Unknown_10h = 0x50524430; + m.Unknown_14h = 0x0079; + + m.RootBlockIndex = 1; //assume first block is root. todo: make adjustable? + + m.StructureInfos = new ResourceSimpleArray(); + foreach (var si in StructureInfos.Values) + { + m.StructureInfos.Add(si); + } + m.StructureInfosCount = (short)m.StructureInfos.Count; + + m.EnumInfos = new ResourceSimpleArray(); + foreach (var ei in EnumInfos.Values) + { + m.EnumInfos.Add(ei); + } + m.EnumInfosCount = (short)m.EnumInfos.Count; + + m.DataBlocks = new ResourceSimpleArray(); + foreach (var bb in Blocks) + { + m.DataBlocks.Add(bb.GetMetaDataBlock()); + } + m.DataBlocksCount = (short)m.DataBlocks.Count; + + return m; + } + + + } + + + public class MetaBuilderBlock + { + public MetaName StructureNameHash { get; set; } + public List Items { get; set; } = new List(); + public int TotalSize { get; set; } = 0; + public int Index { get; set; } = 0; + + public int AddItem(byte[] item) + { + int idx = Items.Count; + Items.Add(item); + TotalSize += item.Length; + return idx; + } + + public uint BasePointer + { + get + { + return (((uint)Index + 1) & 0xFFF); + } + } + + + public MetaDataBlock GetMetaDataBlock() + { + if (TotalSize <= 0) return null; + + byte[] data = new byte[TotalSize]; + int offset = 0; + for (int j = 0; j < Items.Count; j++) + { + var bdata = Items[j]; + Buffer.BlockCopy(bdata, 0, data, offset, bdata.Length); + offset += bdata.Length; + } + + MetaDataBlock db = new MetaDataBlock(); + db.StructureNameHash = StructureNameHash; + db.DataLength = TotalSize; + db.Data = data; + + return db; + } + + + } + + public struct MetaBuilderPointer + { + public int Block { get; set; } //0-based index + public int Offset { get; set; } //(byteoffset/16) + public int Length { get; set; } //for temp use... + public uint Pointer + { + get + { + uint bidx = (((uint)Block) & 0xFFF); + uint offs = (((uint)Offset) & 0xFFFF) << 16; + return bidx + offs; + } + } + } + + +} diff --git a/GameFiles/MetaTypes/MetaNames.cs b/GameFiles/MetaTypes/MetaNames.cs new file mode 100644 index 0000000..fc2c0bd --- /dev/null +++ b/GameFiles/MetaTypes/MetaNames.cs @@ -0,0 +1,6874 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + public class MetaNamesUtil + { + + + public static string GetNameEnumCode() + { + //code to generate the enum code with the hash from the list of names + StringBuilder sb = new StringBuilder(); + string[] names = ShaderParamNames.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + foreach (string name in names) + { + uint hash = JenkHash.GenHash(name/*.ToLower()*/, JenkHashInputEncoding.UTF8); + sb.AppendFormat("{0} = {1},", name, hash); + sb.AppendLine(); + } + string result = sb.ToString(); + return result; + } + + public static string ShaderParamNames = @" +_dimensionLOD2 +_fakedGrassNormal +_vecCollParams +_vecVehColl0B +_vecVehColl0M +_vecVehColl0R +_vecVehColl1B +_vecVehColl1M +_vecVehColl1R +_vecVehColl2B +_vecVehColl2M +_vecVehColl2R +_vecVehColl3B +_vecVehColl3M +_vecVehColl3R +_vecVehCollB +_vecVehCollM +_vecVehCollR +Acceleration_Delta +accumulationBufferSampler0 +accumulationBufferSampler1 +activeShadowCascades +adapDOFProj +AdapLumSampler +AdaptedLumMax +AdaptedLumMin +AdaptionParams +adaptive +AdaptiveDofDepthDownSampleParams +adaptiveDOFExposureSampler +AdaptiveDofFocusDistanceDampingParams1 +AdaptiveDofFocusDistanceDampingParams2 +AdaptiveDOFOutputBuffer +AdaptiveDofParams0 +AdaptiveDofParams1 +AdaptiveDofParams2 +AdaptiveDofParams3 +AdaptiveDOFParamsBuffer +adaptiveDOFSampler +adaptiveDOFSamplerDepth +AdaptTime +AirResist +alphaAdjust +AlphaMaskMapSampler +AlphaRange +AlphaScale +AlphaTest +alphaTestValue +altRemap +AmbientDecalMask +AmbientLightingParams +ambientOcclusionContrast +AmbientOccSampler +AnimatedNormalMapMask0Sampler +AnimatedNormalMapMask1Sampler +AnimatedNormalMapMask2Sampler +animatedNormalMapMod1 +animatedNormalMapMod2 +AnisoNoiseSpecSampler +AnisotropicAlphaBias +anisotropicSpecularColour +anisotropicSpecularExponent +anisotropicSpecularIntensity +APlaneSampler +ApplyDamageSampler +approxTangent +ArmourStrength +AttenuationSampler +AverageLuminanceOut +AvgLuminanceTexture +AzimuthColor +AzimuthColorEast +azimuthEastColor +AzimuthHeight +AzimuthStrength +azimuthTransitionColor +azimuthTransitionPosition +azimuthWestColor +BackBufferSampler +BackBufferTexture +BaseSampler +baseTextureSampler +bDebugDisplayDamageMap +bDebugDisplayDamageScale +Billboard +blitSampler +BloodSampler +BloodSamplerVS +BloodZoneAdjust +bloomLum +BloomParams +BloomSampler +BloomSamplerG +BloomTexelSize +BlueOff +blurIntensity +BlurSampler +BlurVignettingParams +BokehAlphaCutoff +BokehBrightnessParams +BokehEnableVar +BokehGlobalAlpha +BokehNumAddedToBuckets +BokehParams1 +BokehParams2 +BokehPointBuffer +BokehSortedIndexBuffer +BokehSortedListBuffer +BokehSortLevel +BokehSortLevelMask +BokehSortTransposeMatHeight +BokehSortTransposeMatWidth +BokehSpritePointBuffer +bottomSkyColour +BoundRadius +branchBendPivot +branchBendStiffnessAdjust +Brightness +BrightnessSetting +BrightTonemapParams0 +BrightTonemapParams1 +BrokenBumpSampler +BrokenColor +BrokenDiffuseColor +BrokenDiffuseSampler +BrokenGlassTileScale +BrokenSpecularColor +BrokenSpecularSampler +bumpiness +BumpSampler +BumpSampler_layer0 +BumpSampler_layer1 +BumpSampler_layer2 +BumpSampler_layer3 +BumpSampler_layer4 +BumpSampler_layer5 +BumpSampler_layer6 +BumpSampler2 +BumpSamplerFur +bumpSelfShadowAmount +BurnoutLimit +cBPlaneSampler +ChromAbParam +clearcol +clippingPlane +ClipPlanes +ClothDarken +ClothDarkenColor +clothParentMatrix +ClothSweatMapSampler +ClothSweatSpec +cloudBaseColour +cloudBaseMinusMidColour +CloudBias +cloudBillboardParams +CloudColor +cloudConstants1 +cloudConstants2 +cloudConstants3 +cloudDetailConstants +CloudFadeOut +CloudInscatteringRange +cloudLayerAnimScale1 +cloudLayerAnimScale2 +cloudLayerAnimScale3 +cloudMidColour +cloudShadowColour +cloudShadowMinusBaseColourTimesShadowStrength +CloudShadowOffset +CloudShadowStrength +CloudThicknessEdgeSmoothDetailScaleStrength +CloudThreshold +ClumpBump +COCOutputTexture +ColorCorrect +ColorCorrectHighLum +ColorFringeParams1 +ColorFringeParams2 +colorHighLum +colorLowLum +colorLum +ColorSampler +colorScaler +ColorShift +ColorShiftLowLum +ColorShiftScalar +ColorTexture +ComboHeightSamplerFur +ComboHeightSamplerFur01 +ComboHeightSamplerFur2 +ComboHeightSamplerFur23 +ComboHeightSamplerFur3 +ComboHeightSamplerFur4 +ComboHeightSamplerFur45 +ComboHeightSamplerFur67 +ComboHeightTexMask +Contrast +ConvertSampler +CoronasDepthMapSampler +CrackDecalBumpAlphaThreshold +CrackDecalBumpAmount +CrackDecalBumpTileScale +CrackEdgeBumpAmount +CrackEdgeBumpTileScale +crackleIntensity +CrackleSampler +CrackMatrix +CrackOffset +CrackSampler +cRPlaneSampler +cubeFace +CurLumSampler +currentDOFTechnique +currentLum +currentResolution +curveCoeffs +DamagedWheelOffsets +DamageMultiplier +DamageSampler +damageSpecTextureSampler +DamageTextureOffset +damageTextureSampler +DamageVertBuffer +DarkTonemapParams0 +DarkTonemapParams1 +deathIntensity +DeathSampler +debugCloudsParams +debugLightColour +DecalSampler +DecalTint +DecorationFrameInfo +DecorationTattooAdjust +DecorationTintPaletteSel +DecorationTintPaletteTexSampler +deferredLightDownsampleDepthSampler +deferredLightParams +deferredLightScreenSize +deferredLightVolumeParams +deferredPerspectiveShearParams0 +deferredPerspectiveShearParams1 +deferredPerspectiveShearParams2 +deferredProjectionParams +deferredVolumeColour +deferredVolumeDepthBufferSamp +deferredVolumeDirection +deferredVolumePosition +deferredVolumeShaftCompositeMtx +deferredVolumeShaftGradient +deferredVolumeShaftGradientColourInv +deferredVolumeShaftPlanes +deferredVolumeTangentXAndShaftRadius +deferredVolumeTangentYAndShaftLength +DensitySampler +DepthBlurHalfResSampler +DepthBlurHalfResTexture +DepthBlurSampler +DepthBlurTexture +depthBuffer +depthBuffer2 +depthBuffer2_Sampler +DepthBufferSamp +DepthBufferSampler +DepthMapPointSampler +DepthMapSampler +DepthMapTexSampler +DepthSampler +depthSourceSampler +depthTexture +DepthTextureMS +deSatContrastGamma +Desaturate +desaturateTint +detailBumpiness +DetailBumpSampler +DetailDensity2Sampler +DetailDensitySampler +detailMapOffset +DetailMapSampler +detailMapUScale +detailMapVScale +DetailNormal2Sampler +DetailNormalSampler +DetailOffset +DetailSampler +detailSettings +detailUVScale +diffuse2SpecMod +diffuseCol +DiffuseExtraSampler +DiffuseHfSampler +diffuseMod +DiffuseNoBorderTexSampler +DiffuseSampler +DiffuseSampler2 +DiffuseSamplerFur +DiffuseSamplerPhase2 +DiffuseSamplerPoint +DiffuseSplatterTexSampler +DiffuseTexSampler +DiffuseTexSampler01 +DiffuseTexSampler02 +DiffuseTexSampler03 +DiffuseTexSampler04 +DiffuseTexTileUV +DiffuseWoundTexSampler +DiffusionRadius +dimmerSet +dimmerSetPacked +DirectionalMotionBlurIterParams +DirectionalMotionBlurLength +DirectionalMotionBlurParams +dirtColor +DirtDecalMask +dirtLevel +dirtLevelMod +DirtSampler +DiskBrakeGlow +displParams +distanceMapSampler +DistEpsilonScaleMin +DistMapCenterVal +distortionParams +DistortionSampler +ditherSampler +dofBlur +DofBlurWeight +dofDist +dofInten +dofNoBlurBlendRingSize +dofNoBlurRadius +DOFOutputTexture +dofProj +dofProjCompute +dofRenderTargetSize +DOFSampler +dofShear +dofSkyWeightModifier +DOFTargetSize +downsampledDepthSampler +DownsampleDepthSampler +dpMapFarClip +dpMapNearClip +drawBucket +dReflectionParams +droopParams +DruggedEffectColorShift +DruggedEffectParams +dShadowMatrix +dShadowOffsetScale +dShadowParam0123 +dShadowParam4567 +dShadowParam891113 +DstTextureSize +eaaParams2 +earlyOut +earlyOut_Sampler +earlyOutParams +EastColor +EdgeMarkParams +EdgeThreshold +EdgeThresholdMin +effectsConstants +ElapsedTime +emissiveMultiplier +emissiveReflectMultiplier +EmitterParamLifeAndSpeed +EmitterParamPos +EmitterParamPosRange +EmitterParamProbablityPhase2 +EmitterTransform +EmitterVelocityBoxPos +EmitterVelocityBoxRange +EnvBloodBinormal +EnvBloodData +EnvBloodPos +EnvBloodSampler +EnvBloodTangent +envEffFatThickness +envEffScale +envEffTexTileUV +envEffThickness +EnvironmentSampler +Exposure +ExposureClampAndHistory +ExposureCurve +ExposureParams0 +ExposureParams1 +ExposureParams2 +ExposureParams3 +Exposures +ExposureSwitches +faceTextureSampler +facetMask +Fade_Thickness +fadeAlphaDist +fadeAlphaDistUmTimer +fadeAlphaLOD1Dist +fadeAlphaLOD2Dist +fadeAlphaLOD2DistFar0 +fAge +FallOffAndKernelParam +fillColor +Filmic0 +fIntensity +FlowSampler +FoamSampler +FogColor +FogParams +FogRayTexSampler +FogSampler +fogVolumeColor +fogVolumeDepthSampler +fogVolumeInvTransform +fogVolumeParams +fogVolumePosition +fogVolumeTransform +foliageBranchBendPivot +foliageBranchBendStiffnessAdjust +FontNormalSampler +FontNormalScale +FontSampler +FontTexture +fourPlaneDof +fpvMotionBlurSize +fpvMotionBlurVelocity +fpvMotionBlurWeights +FrameMap +FrameMapTexSampler +Frequency1 +Frequency2 +fresnelRolloff +FullSampler +furAlphaClip03 +furAlphaClip47 +furAlphaDistance +furAOBlend +furAttenCoef +furBendParams +furDitherAlphaFadeParams +furGlobalParams +furLayerParams +furLayerParams2 +furLayerParams3 +furLayerStep +furLength +FurMaskSampler +furMaxLayers +furMinLayers +furNoiseUVScale +furNumLayers +furSelfShadowMin +furShadow03 +furShadow47 +furStiffness +furUvScales +g_AlphaFade +g_BloodColor +g_BloodSplatParams +g_CPQSMix_QSFadeIn +g_CurrentValue +g_EdgeHighlightColour +g_f4RTSize +g_fBilateralCoefficient +g_fBilateralEdgeThreshold +g_fCollisionSqScale +g_fEnableSpringForces +g_fGrassSpringRigidity +g_fGrassSpringScale +g_fRippleRainStrength +g_fSSAOBilateralCoef +g_fSSAOKernelScale +g_fVolumetricLightRayIntensityMult +g_GBufferTexture3Param +g_GhostLevel +g_HDAO_Params1 +g_HDAO_Params2 +g_HDAOApplyParams +g_HDAOComputeParams +g_HDAOExtraParams +g_HDAOValleyParams +g_HighlightScale +g_ImposterSize +g_LightningStrikeNoiseParams +g_LightningStrikeParams +g_LinearClampSampler +g_MSAAPointTexture1_Dim +g_MSAAPointTexture2_Dim +g_OcclusionTextureParams +g_PointSampler +g_projParams +g_projShear +g_Puddle_ScaleXY_Range +g_PuddleParams +g_ResultTexture +g_SSAOStrength +g_targetSize +g_TextColour +g_TextShadowColour +g_TextShadowScale +g_vCollisionParams +g_vCollisionSpheres +g_vPlayerPosition +g_vRelativeLuminanceThresholdParams +g_vRippleAttributes +g_vRippleTexelSize +g_vTexelSize +g_WaveXOffset +g_WaveXZoom +g_WaveYZoom +g_WidthScalar +gActiveUnit +GalaxyOffset +GalaxySampler +gAlphaCutoffMinMax +gAlphaTest +gAlphaToCoverageScale +gAmbientAmount +gAmbientColor +gAmbientMult +gAmbientShadow +Gamma +GammaCorrection +gAnimatedNormalMapParams +gAnimBlendWeights +gAnimCombine +gAnimSculpt +GaussianWeights +gBackgroundDistortionAlphaBooster +gBackgroundDistortionAmount +gBackgroundDistortionVisibilityPercentage +gBiasToCamera +gBlitMatrix +gBloodData +gBloodUVBoundsPage +gBlurAmount +gBoneDamage0 +gBoneDamageEnabled +gBounceColor +gBoxCentrePos +gBoxForward +gBoxRight +gBoxSize +GBufferStencilTextureSampler +gbufferTexture0 +gbufferTexture2 +gbufferTextureDepth +GBufferTextureSampler0 +GBufferTextureSampler1 +GBufferTextureSampler2 +GBufferTextureSampler3 +GBufferTextureSamplerDepth +GBufferTextureSamplerSSAODepth +gCableParams +gCamAngleLimits +gCameraBias +gCameraDistanceAtMaxDisplacement +gCameraPos +gCameraPosition +gCameraShrink +gClipPlanes +gCloudColor +gCloudViewProj +gCollisionLifeModifier +gCollisionPositionModifier +gCollisionVelocityModifier +gColorTint +gColorTintPhase2 +gColour +gColourSplash +gControlLight +gCrossFadeDistance +gCSMParticleShadowSamp +gCSMParticleShadowTexture +gCSMShaderVars_deferred +gDayNightScale +gDecalChannelSelection +gDecalNormalSampler +gDecalSampler +gDeferredInverseViewProjMatrix +gDeferredLightColourAndIntensity +gDeferredLightConeAngle +gDeferredLightConeAngleI +gDeferredLightConeOffset +gDeferredLightConeScale +gDeferredLightDirection +gDeferredLightInvSqrRadius +gDeferredLightPosition +gDeferredLightRadius +gDeferredLightRadiusProjShearParams +gDeferredLightSampler +gDeferredLightSampler0P +gDeferredLightSampler1 +gDeferredLightSampler2 +gDeferredLightShadowMap0 +gDeferredLightShadowMap1 +gDeferredLightShadowMap2 +gDeferredLightShadowMap3 +gDeferredLightShaftParams +gDeferredLightTangent +gDeferredLightType +gDeferredLightVolumeParams +gDeferredProjParams +gDeferredVolumeRadiusScale +gDensityShiftScale +gDepthViewProjMtx +gDiffuse +gDirectional +gDirectionalLightShadowAmount +gDirectionalMotionBlurLength +gDirectionalMult +gDirectionalVelocityAdd +gDirectionalZOffsetMinRange +gDirNormalBias +gDispersalSettings +gDistanceScale +gEastMinusWestColor +gEdgeSoftness +GeneralParams0 +GeneralParams1 +gExtraLightMult +gExtraLights +gExtraParams0 +gExtraParams1 +gExtraParams2 +gExtraParams3 +gExtraParams4 +gFadeInOut +gFadeNearFar +gFadeZBaseLoHi +gFirstTimeUpdate +gFogCompositeAmbientColor +gFogCompositeDirectionalColor +gFogCompositeParams +gFogCompositeTexOffset +gFrustumParameters +gGrassSkipInstance +gGravityWindTimeStepCut +gGustAmplifier +gGustSpacing +gHDRExposure +gHeatHaze +gHeatHazeRippleLength +gHeatHazeRippleRate +gHeatHazeScale +gHeatHazeSize +gHeatHazeWidth +gHeatPhase +gHitPlane +ghorizScale +gHybridAddRatio +gInstanceVars +gInstCullParams +gIntensity +gInterpolationFactor +gIsShadowPass +gLifeFade +gLifeMinMaxClampToGround +gLifeTimeScale +gLightIntensityClamp +gLightIntensityMult +gLightSettings +globalAnimUV0 +globalAnimUV1 +globalFogRayFadeParam +globalFogRayParam +globalFreeAimDir +gLocalLightsMultiplier +gLodFadeControlRange +gLodFadePower +gLodFadeRange +gLodFadeStartDist +gLodFadeTileScale +gLodInstantTransition +gLodThresholds +gLowResDepthSampler +gLowResDepthTexture +gMaxDisplacement +gMaxLife +gMirrorBounds +gMirrorCrackAmount +gMirrorCrackSampler +gMirrorDebugParams +gMirrorDistortionAmount +gMotionBlur +gNearFarQMult +gNormalArc +gNormalHeight +gNormalMapMult +gNormalOffset +gNormalScale +gNumClipPlanes +gOffsetParticlePos +gOffsetScale0 +gOffsetScale1 +goldFactor +goldFresnelRolloff +goldReflectColorBase +goldReflectColorOverlay +goldReflectivePower +goldSpecMapIntMask +goldSpecularFactor +GolfTrailTextureSamp +gooDeferredLightScreenSize +gOrientToTerrain +gParticleColorPercentage +gParticleTextureSize +gPerspectiveShearParams0 +gPerspectiveShearParams1 +gPerspectiveShearParams2 +gPiercingLightPower_Strength_NormalStrength_Thickness +gPositionOffset +gPositionScale +gPower +gPrevViewProj +gProjParams +GradientFilterColBottom +GradientFilterColMiddle +GradientFilterColTop +gRadius +gRainDebug +gravityDroop +GreenOff +gReflScales +gRefParticlePos +gRefraction +gRescaleUV1 +gRescaleUV2 +gRescaleUV3 +gResetParticles +gRG_BlendEndDistance +gRG_BlendStartDistance +gRotationCenter +gRotSpeedMinRange +groundColor +gScaleDiffuseFillAmbient +gScaleFade +gScaleRange +gScatterG_GSquared_PhaseMult_Scale +gShadowAmount +gSizeMinMax +gSizeMinRange +gSkyColor +gSoftness +gSoftnessCurve +gSoftnessShadowMult +gSoftnessShadowOffset +gSoftParticleRange +gSpecularExponent +gSpecularIntensity +gSplashFrames +gSplashSizeMinMax +gSunColor +gSunDirection +gSuperAlpha +gSurfaceSettings +gtaSkyDomeClip +gtaSkyDomeFade +gtaWaterColor +gTexCoordScaleOffset0 +gTexCoordScaleOffset1 +gTexCoordScaleOffset2 +gTexCoordScaleOffset3 +gTextureAngleRads +gTextureAnimation +gTextureAnimRateScaleOverLifeStart2End2 +gTextureRowsCols +gTextureRowsColsStartEnd +gTotalLifeTimeScale +gUseComputeShaderOutputBuffer +gUseDirectional +gUseShadows +gUVOffset +gUVOffset1 +gUVOffset2 +gUVOffset3 +gVelocityMax +gVelocityMin +gvertScale +gViewProj +gVolumeLightsSampler +gVolumeLightsTexture +gWaterHeight +gWestColor +gWindBaseVel +gWindBendingGlobals +gWindBendScaleVar +gWindGustVel +gWindMultParams +gWindParams +gWindVarianceVel +gWorldBinormal +gWorldInstanceInverseTranspose +gWorldInstanceMatrix +gWorldTangent +gWrapBias +gWrapLighting +gWrapLighting_MSAARef +gWrapScale +gZdampen +HardAlphaBlend +HDRColorTexture +HDRExposure +HDRExposureClamp +hdrIntensity +HDRIntensityMultiplier +HDRPointSampler +HDRSampler +HDRSunExposure +HDRTextureAA +HeatHazeOffsetParams +HeatHazeParams +HeatHazeSampler +HeatHazeTex1Params +HeatHazeTex2Params +heightBias +heightBias0 +heightBias1 +heightBias2 +heightBias3 +HeightFogParams +HeightMapSampler +heightMapSamplerLayer0 +heightMapSamplerLayer1 +heightMapSamplerLayer2 +heightMapSamplerLayer3 +HeightMapTransformMtx +HeightOpacity +heightSampler +heightScale +heightScale0 +heightScale1 +heightScale2 +heightScale3 +heightTexture +hemi_bias +hemi_near +hemi_params +hemi_range +hemi_res +HemiCubeSampler +hiDofMiscParams +hiDofParams +HighDetailNoiseBumpSampler +HighDetailNoiseSampler +highDetailSampler +highLum +history +HmdWarpParam +horizonLevel +HybridAdd +HybridAddRatio +ImageFXParams +importanceBufferSampler +imposterDir +imposterSampler +imposterWorldX +imposterWorldY +imposterWorldZ +InitPositionTexSampler +InitVelocityTexSampler +InputTex +InstanceBuffer +InterlaceIndex +InterlaceMapSampler +InterlaceTotalNum +intermediateTarget +intermediateTarget_Sampler +intermediateTargetAA +JitterSampler +kernelParam +kernelRadius +KillFlashCol +KillFlashUVOff +LaserSampler +LaserVisibilityMinMax +LastBufferSize +LensArtefactsParams0 +LensArtefactsParams1 +LensArtefactsParams2 +LensArtefactsParams3 +LensArtefactsParams4 +LensArtefactsParams5 +LensCenter +LensDistortionParams +LetterIndex1 +LetterIndex2 +LetterSize +LicensePlateFontExtents +LicensePlateFontTint +LightColor +LightDir +LightOcclusionSampler +lightrayParams +lightrayParams2 +LightStreaksBlurDir +LightStreaksColorShift0 +LinearSampler +LinearSampler1 +LinearSampler2 +LinearWrapSampler +LinearWrapSampler2 +LinearWrapTexture3 +lookupSampler +lowLum +LowResDepthMapPointSampler +LowResDepthPointMap +LumFilterParams +LuminanceConstants +LuminanceDownsampleOOSrcDstSize +lunarCycle +manualDepthTest +MaskAlphaReverse +maskTextureSampler +matDiffuseColor +matDiffuseColor2 +matDiffuseColorTint +materialDiffuse +materialIdSampler +materialWetnessMultiplier +matGrassTransform +matMaterialColorScale +matWheelTransform +matWheelWorld +matWheelWorldViewProj +MBPerspectiveShearParams0 +MBPerspectiveShearParams1 +MBPerspectiveShearParams2 +MBPrevViewProjMatrixW +MBPrevViewProjMatrixX +MBPrevViewProjMatrixY +MipMapLod +mirrorIntensity +mirrorNormalIntensity +mirrorParams +mirrorReflectionSkyIntensity +mirrorSpecMaskIntensity +MLAAAreaLUTSampler +MLAALinearSampler +MLAAPointSampler +moonColor +MoonColorConstant +moonDirection +MoonGlow +MoonGlowSampler +moonIntensity +MoonLight +moonPosition +moonSampler +moonTexConvert +MoonTexPosition +MoonVisiblity +MoonXVector +MoonYVector +motionBlurMatrix +MotionBlurSampler +MP_BulletTimeParams +MSAAPointSampler1 +MSAAPointTexture1 +MSAAPointTexture2 +nearFarClip +Noise1Sampler +Noise2Sampler +noiseDensityOffset +NoiseFilterArea +noiseFrequency +noiseHighLum +noiseLowLum +noiseLum +NoiseMapSampler +NoiseParams +noisePhase +NoiseSampler +noiseScale +noiseSoftness +NoiseTexSampler +noiseTexture +NoiseTextureSampler +noiseThreshold +NoiseWarp +normalBuffer +normalBufferSamp +normalMapBlendRatio +normalMapMod +NormalMapSampler +NormalMapSampler1 +NormalMapSampler2 +NormalMapTexSampler +normalSampler +NormalSpecMapTexSampler +normalTexture +NormalTextureSampler +NormBufferSampler +normFresnelRolloff +normReflectivePower +normSpecMapIntMask +normSpecularFactor +normTable +numActiveShadowCascades +numChildren +NumLetters +occlusionSampler +occlusionTexture +OceanLocalParams0 +offsetHighLum +offsetLowLum +offsetLum +orderNumber +paletteColor0 +paletteColor1 +paletteColor2 +paletteColor3 +paletteIndex +PaletteSampler +paletteSelector +paletteSelector2 +ParabSampler +parallaxScaleBias +parallaxSelfShadowAmount +param0 +param1 +param2 +param3 +param4 +param5 +param6 +param7 +params +ParticleCollisionSampler +ParticlePosTexSampler +ParticlePosXYTexSampler +ParticlePosZWTexSampler +particleShadowsParams +ParticleVelTexSampler +ParticleVelXYTexSampler +ParticleVelZWTexSampler +PedBrightness +PerlinNoiseSampler +perlinSampler +Persistance +perspectiveShearParam +Phase +plantColor +PlateBgBumpSampler +PlateBgSampler +PLAYER_MASK +PlayerBrightness +playerLFootPos +playerRFootPos +PointSampler +PointSampler1 +PointSampler2 +PointTexture1 +PointTexture2 +PointTexture3 +PointTexture4 +PointTexture5 +poisson12 +polyRejectThreshold +PositionTexSampler +PostFXAdaptiveDofCustomPlanesParams +PostFXAdaptiveDofEnvBlurParams +PostFxSampler2 +PostFxSampler3 +postProcess_FlipDepth_NearPlaneFade_Params +projectionParams +PRTOccSampler +PtfxAlphaMapSampler +PtfxDepthMapSampler +PuddleBumpSampler +PuddleMaskSampler +PuddlePlayerBumpSampler +QuadAlpha +QuadPosition +QuadScale +QuadTexCoords +QualitySubpix +radialBlurCenter +RadialBlurSampler +radialBlurSampleScale +radialBlurScale +radialBlurTextureStep +RadialFadeArea +RadialFadeTime +RadialWaveParam +radius +RainNormalControls +RainNormalSampler +RawInstanceBuffer +rcpFrame +RedOff +reductionDepthTexture +ReductionOutputTexture +RefBlurMapSampler +ReflectanceSampler +reflectivePower +reflectivePowerED +ReflectTextureSampler +refMipBlurParams +RefMipBlurSampler +RefractionMapTexSampler +RefractSampler +RenderCubeMapSampler +RenderMapPointSampler +RenderMapPointSamplerMSAA +RenderPointMapINT +RenderPointMapINTParam +RenderTargetSize +RenderTexArray +RenderTexArraySampler +RenderTexFmask +RenderTexMSAA +RenderTexMSAAINT +RenderTexMSAAParam +RESERVE_VS_CONST_c253 +RESERVE_VS_CONST_c254 +RESERVE_VS_CONST_c255 +ResolvedDepthSampler +ResolvedDepthTexture +Result +rimAmount +rimPower +RippleBumpiness +RippleData +RippleScale +RippleScaleOffset +RippleSpeed +ropeColor +samp +sampFiltered +sampleAngle +sampleScale +Scale +ScaleIn +scalerLum +ScanlineFilterParams +ScreenBlurFade +ScreenCenter +screenRes +ScreenRez +ScreenSizeHalfScale +SeamTextureSampler +seeThroughColorFar +seeThroughColorNear +seeThroughColorVisibleBase +seeThroughColorVisibleWarm +seeThroughParams +SegmentSize +SelfShadowing +SfxWindSampler3D +shader_cableAmbient +shader_cableDiffuse +shader_cableDiffuse2 +shader_cableEmissive +shader_fadeExponent +shader_radiusScale +shader_windAmount +shaderVariables +ShadowFacingOffset +ShadowFalloff +shadowmap_res +shadowMapSamp +shadowParams2 +skinColourTweak +SkinParams +SkyColor +SkyMapSampler +skyPlaneColor +skyPlaneParams +smallCloudColorHdr +smallCloudColorXHdrIntensity +smallCloudConstants +SmartBlitCubeMapSampler +SmartBlitCubeMapTexture +SmartBlitSampler +SmartBlitTexture +SmokeParams +SmokeSampler +SnowSampler +SnowSampler0 +SnowSampler1 +SoakFrameInfo +Softness +source +SpecDesaturateExponent +SpecDesaturateIntensity +SpecExp +specFalloffAdjust +specFresnelExp +specFresnelMax +specFresnelMin +SpecIntensity +specIntensityAdjust +specMapExpMask +specMapIntMask +specMapReflectMask +SpecSampler +SpecSampler_layer01 +SpecSampler_layer23 +specTexTileUV +specular2Color +specular2Color_DirLerp +specular2ColorIntensity +specular2ColorIntensityED +specular2ColorIntensityRE +specular2Factor +specular2FactorED +specularColorFactor +specularColorFactor1 +specularColorFactor2 +specularColorFactor3 +specularColorFactorED +specularFactor +specularFactor1 +specularFactor2 +specularFactor3 +specularFactorED +SpecularFalloff +specularFalloffMult +specularFalloffMultSpecMap +specularFresnel +SpecularIntensity +specularIntensityMult +specularIntensityMultSpecMap +specularNoiseMapUVScaleFactor +SpecularPower +speedConstants +sphereReflectionSkyIntensity +SplatterFrameInfo +srcTextureSize +sslrCenter +sslrParams +SSLRSampler +StarFieldBrightness +starfieldIntensity +StarFieldSampler +StarFieldUVRepeat +StarThreshold +StencilCopy +StencilCopySampler +StencilCopyTexture +StencilTech +StippleSampler +StubbleControl +SubColor +SubScatWidth +SubScatWrap +SubsurfaceColor +SubsurfaceIntensity +SubsurfaceRollOff +SubViewportParams +SunAxias +SunCentre +sunColor +sunColorHdr +sunColour +sunConstants +sunDirection +sunDiscColor +sunDiscColorHdr +SunElevation +sunHdrIntensity +sunPosition +SunRaysParams +SunsetColor +SunSize +SurfaceTextureSampler +SweatMapSampler +switchOn +targetSize +targetSizeParam +TearGasParams +TerrainGridCentrePos +TerrainGridForward +TerrainGridHighHeightCol +TerrainGridLowHeightCol +TerrainGridMidHeightCol +TerrainGridParams +TerrainGridParams2 +TerrainGridRight +tessellationMultiplier +TexelSize +Texm +TextureClamp +TextureGrassSampler +TextureNoWrapSampler +textureSamp +TextureSampler +TextureSampler_layer0 +TextureSampler_layer1 +TextureSampler_layer2 +TextureSampler_layer3 +TextureSampler_layer4 +TextureSampler_layer5 +TextureSampler_layer6 +TextureSampler2 +TextureSamplerDiffPal +TextureSize +TiledLightingSampler +TimeOfDay +TintBlendAmount +tintBlendLayer0 +tintBlendLayer1 +tintBlendLayer2 +tintBlendLayer3 +tintBumpiness +tintBumpSampler +TintIntensity +TintPaletteSampler +tintPaletteSelector +tintSampler +tonemapColorFilterParams0 +tonemapColorFilterParams1 +TonemapParams +TopCloudBiasDetailThresholdHeight +TopCloudColor +TopCloudDetail +TopCloudHeight +TopCloudLight +TopCloudThreshold +topLum +TotalElapsedTime +TrackAnimUV +TransColor +TransparentDstMapSampler +TransparentSrcMap +TransparentSrcMapSampler +TransPos +TransTex0 +TransTex1 +TransTex2 +treeLod2Normal +treeLod2Params +txABC_Texture +txCOC_Texture +txX_Texture +txYn_Texture +tyreDeformParams +tyreDeformParams2 +tyreDeformSwitchOn +UIColor +UIColorXformOffset +UIColorXformScale +UIPosMtx +UIPremultiplyAlpha +UITex0Mtx +UITex1Mtx +UITexture0 +UITexture1 +umGlobalOverrideParams +umGlobalParams +uMovementParams +umTriWave1Params +umTriWave2Params +umTriWave3Params +UnderLightStrength +unsharpAmount +UpdateOffset +UpdateParams0 +UpdateParams1 +useTessellation +UseTreeNormals +UVScalar +uvScales +vBoneVelocitiesX +vBoneVelocitiesY +vCustomData +vecBatchAabbDelta +vecBatchAabbMin +vecCameraPos +vecPlayerPos +vehglassCrackTextureParams +vehglassCrackTextureSampler +Velocity1 +Velocity2 +VelocityBufferSampler +VelocityMapSampler +VelocityTexSampler +vHairParams +viewProj +viewToWorldProjectionParam +VignettingColor +VignettingParams +VisibleInstanceBuffer0 +VisibleInstanceBuffer1 +VisibleInstanceBuffer2 +VisibleInstanceBuffer3 +vNoiseParams +vol_offsets +VolumeSampler +vSkinSweat +vSweatParams +WaterBumpParams +waterColor +WaterColorSampler +waterColour +WaterFogFadeColor +waterfogPtfxParams +WaterHeight +waterIntensity +waterReflectionScale +waterReflectionSkyIntensity +waterRenderSimParam +WaterRippleSampler +waterSimParam +waterSimParams1 +waterSimParams2 +WaterSurfaceSampler +waterTexResValue +WaveMovement +WaveOffset +WestColor +WetAnisotropicSpecular +WetAnisotropicSpecularColour +WetDarken +wetnessMultiplier +WindGlobalParams +WindStr +WoundFrameInfo +wrapAmount +wrapLigthtingTerm +WrinkleMaskSampler_0 +WrinkleMaskSampler_1 +WrinkleMaskSampler_2 +WrinkleMaskSampler_3 +WrinkleMaskSampler_4 +WrinkleMaskSampler_5 +wrinkleMaskStrengths0 +wrinkleMaskStrengths1 +wrinkleMaskStrengths2 +wrinkleMaskStrengths3 +WrinkleSampler_A +WrinkleSampler_B +YPlaneSampler +YUVtoRGB +zenithColor +zenithConstants +zenithTransitionColor +ZoomBlurMaskSize +ZoomFocusDistance +zShift +zShiftScale +"; + + + public static string AllNames = @"aabb +AABB +AbilityType +Action +activeChangesetConditions +AdditiveDamageClipSet +AET_Directed_In_Place +AET_Flinch +AET_In_Place +AET_Interesting +AET_Threatened +AET_Threatening +aExplosionTagData +AFF_POOR +Affluence +Age +aircraftDownwashPtFxDist +aircraftDownwashPtFxEnabled +aircraftDownwashPtFxNameDefault +aircraftDownwashPtFxNameDirt +aircraftDownwashPtFxNameFoliage +aircraftDownwashPtFxNameSand +aircraftDownwashPtFxNameWater +aircraftDownwashPtFxRange +aircraftDownwashPtFxSpeedEvoMax +aircraftDownwashPtFxSpeedEvoMin +aircraftSectionDamageSmokePtFxEnabled +aircraftSectionDamageSmokePtFxName +aircraftSectionDamageSmokePtFxRange +aircraftSectionDamageSmokePtFxSpeedEvoMax +aircraftSectionDamageSmokePtFxSpeedEvoMin +ALL +Allow +allowBonnetSlide +AllowCloseSpawning +ALTERNATE_VARIATIONS_FILE +AmbientClipsForFlee +AmbulanceShouldRespondTo +Amount +Amplitude +anchor +ANCHOR_EARS +ANCHOR_EYES +ANCHOR_HEAD +ANCHOR_LEFT_WRIST +ANCHOR_RIGHT_WRIST +AnimalAudioObject +AnimatedModel +Animations +AnimDict +AnimName +AP_LOW +AP_MEDIUM +APF_ISBLENDAUTOREMOVE +APF_ISLOOPED +Apply +archetypeName +archetypes +areas +assetName +assetType +AT_TXD +AUDIO_DYNAMIXDATA +AUDIO_GAMEDATA +AUDIO_SOUNDDATA +AUDIO_SPEECHDATA +AUDIO_SYNTHDATA +AUDIO_WAVEPACK +audioApply +audioId +AUDIOMESH_INDEXREMAPPING_FILE +AutoOpenCloseRateTaper +AutoOpenCosineAngleBetweenThreshold +AutoOpenRadiusModifier +AutoOpenRate +AutoOpensForAllVehicles +AutoOpensForLawEnforcement +AutoOpensForMPPlayerPedsOnly +AutoOpensForMPVehicleWithPedsOnly +AutoOpensForSPPlayerPedsOnly +AutoOpensForSPVehicleWithPedsOnly +AutoOpenVolumeOffset +availableInMpSp +backfirePtFxEnabled +backfirePtFxName +backfirePtFxRange +bAppliesContinuousDamage +bbMax +bbMin +bCanSetPedOnFire +bDamageObjects +bDamageVehicles +BF_ALLOW_CONFRONT_FOR_TERRITORY_REACTIONS +BF_BOOST_BRAVERY_IN_GROUP +BF_COWARDLY_FOR_SHOCKING_EVENTS +Bias +BICYCLE +bIgnoreExplodingEntity +BIKE +blend +Blend +BlendOutDelta +BlendShapeFileName +block +BLOODFX_FILE +bmax +bmin +bNoOcclusion +BOAT +boatBowPtFxEnabled +boatBowPtFxForwardName +boatBowPtFxKeelEvoMax +boatBowPtFxKeelEvoMin +boatBowPtFxRange +boatBowPtFxReverseName +boatBowPtFxReverseOffset +boatBowPtFxScale +boatBowPtFxSpeedEvoMax +boatBowPtFxSpeedEvoMin +boatEntryPtFxEnabled +boatEntryPtFxName +boatEntryPtFxRange +boatEntryPtFxScale +boatEntryPtFxSpeedEvoMax +boatEntryPtFxSpeedEvoMin +boatLowLodWakePtFxEnabled +boatLowLodWakePtFxName +boatLowLodWakePtFxRangeMax +boatLowLodWakePtFxRangeMin +boatLowLodWakePtFxScale +boatLowLodWakePtFxSpeedEvoMax +boatLowLodWakePtFxSpeedEvoMin +boatPropellerPtFxBackwardSpeedEvoMax +boatPropellerPtFxBackwardSpeedEvoMin +boatPropellerPtFxDepthEvoMax +boatPropellerPtFxDepthEvoMin +boatPropellerPtFxEnabled +boatPropellerPtFxForwardSpeedEvoMax +boatPropellerPtFxForwardSpeedEvoMin +boatPropellerPtFxName +boatPropellerPtFxRange +boatPropellerPtFxScale +boatWashPtFxEnabled +boatWashPtFxName +boatWashPtFxRange +boatWashPtFxScale +boatWashPtFxSpeedEvoMax +boatWashPtFxSpeedEvoMin +bobble_base +bobble_head +bone +boneMask +boneTag +BONETAG_HEAD +BONETAG_INVALID +BONETAG_L_CALF +BONETAG_L_CLAVICLE +BONETAG_L_FINGER22 +BONETAG_L_FOOT +BONETAG_L_FOREARM +BONETAG_L_HAND +BONETAG_L_PH_HAND +BONETAG_L_THIGH +BONETAG_L_UPPERARM +BONETAG_NECK +BONETAG_NECK2 +BONETAG_PELVIS +BONETAG_PELVIS1 +BONETAG_R_CALF +BONETAG_R_CLAVICLE +BONETAG_R_FINGER22 +BONETAG_R_FOOT +BONETAG_R_FOREARM +BONETAG_R_HAND +BONETAG_R_PH_HAND +BONETAG_R_THIGH +BONETAG_R_UPPERARM +BONETAG_ROOT +BONETAG_SPINE_ROOT +BONETAG_SPINE0 +BONETAG_SPINE1 +BONETAG_SPINE2 +BONETAG_SPINE3 +BONETAG_TAIL1 +BONETAG_TAIL2 +bOnlyAffectsLivePeds +bOnlyBulkyItemVariations +bonnet +boot +bottom +bPostProcessCollisionsWithNoForce +bPreventWaterExplosionVFX +BreakableByVehicle +BreakingImpulse +bsCentre +bsRadius +bSuppressCrime +bumper_f +bumper_r +bUseDistanceDamageCalc +CAiCoverClipVariationHelper__Tunables +camAnimatedCameraMetadata +camAnimatedShakeMetadata +camAnimSceneDirectorMetadata +CAmbientLookAt__Tunables +CAmbientPedModelVariations +camCatchUpHelperMetadata +camCinematicAnimatedCameraMetadata +camCinematicBustedContextMetadata +camCinematicBustedShotMetadata +camCinematicCameraManCameraMetadata +camCinematicCameraManShotMetadata +camCinematicCameraOperatorShakeSettings +camCinematicCameraOperatorShakeTurbulenceSettings +camCinematicCameraOperatorShakeUncertaintySettings +camCinematicCraningCameraManShotMetadata +camCinematicDirectorMetadata +camCinematicFallFromHeliContextMetadata +camCinematicFallFromHeliShotMetadata +camCinematicFirstPersonIdleCameraMetadata +camCinematicGroupCameraMetadata +camCinematicHeliChaseCameraMetadata +camCinematicHeliTrackingShotMetadata +camCinematicIdleCameraMetadata +camCinematicIdleShots +camCinematicInTrainAtStationContextMetadata +camCinematicInTrainContextMetadata +camCinematicInVehicleContextMetadata +camCinematicInVehicleCrashShotMetadata +camCinematicInVehicleFirstPersonContextMetadata +camCinematicInVehicleMultiplayerPassengerContextMetadata +camCinematicInVehicleOverriddenFirstPersonContextMetadata +camCinematicInVehicleWantedContextMetadata +camCinematicMissileKillShotMetadata +camCinematicMountedCameraMetadata +camCinematicMountedCameraMetadataFirstPersonPitchOffset +camCinematicMountedCameraMetadataFirstPersonRoll +camCinematicMountedCameraMetadataLeadingLookSettings +camCinematicMountedCameraMetadataLookAroundSettings +camCinematicMountedCameraMetadataMovementOnAccelerationSettings +camCinematicMountedCameraMetadataOrientationSpring +camCinematicMountedCameraMetadataRelativePitchScalingToThrottle +camCinematicMountedPartCameraMetadata +camCinematicOnFootAssistedAimingContextMetadata +camCinematicOnFootAssistedAimingKillShotMetadata +camCinematicOnFootFirstPersonIdleShotMetadata +camCinematicOnFootIdleContextMetadata +camCinematicOnFootIdleShotMetadata +camCinematicOnFootMeleeContextMetadata +camCinematicOnFootMeleeShotMetadata +camCinematicOnFootSpectatingContextMetadata +camCinematicParachuteCameraManShotMetadata +camCinematicParachuteContextMetadata +camCinematicParachuteHeliShotMetadata +camCinematicPedCloseUpCameraMetadata +camCinematicPoliceExitVehicleShotMetadata +camCinematicPoliceHeliMountedShotMetadata +camCinematicPoliceInCoverShotMetadata +camCinematicPoliceRoadBlockShotMetadata +camCinematicPositionCameraMetadata +camCinematicScriptContextMetadata +camCinematicScriptedMissionCreatorFailContextMetadata +camCinematicScriptedRaceCheckPointContextMetadata +camCinematicScriptRaceCheckPointShotMetadata +camCinematicShots +camCinematicSpectatorNewsChannelContextMetadata +camCinematicStuntCameraMetadata +camCinematicStuntJumpContextMetadata +camCinematicStuntJumpShotMetadata +camCinematicTrainPassengerShotMetadata +camCinematicTrainRoofMountedShotMetadata +camCinematicTrainStationShotMetadata +camCinematicTrainTrackingCameraMetadata +camCinematicTrainTrackShotMetadata +camCinematicTwoShotCameraMetadata +camCinematicVehicleBonnetShotMetadata +camCinematicVehicleConvertibleRoofShotMetadata +camCinematicVehicleGroupShotMetadata +camCinematicVehicleLowOrbitCameraMetadata +camCinematicVehicleLowOrbitShotMetadata +camCinematicVehicleOrbitCameraInitalSettings +camCinematicVehicleOrbitCameraMetadata +camCinematicVehicleOrbitShotMetadata +camCinematicVehiclePartShotMetadata +camCinematicVehicleTrackingCameraMetadata +camCinematicWaterCrashCameraMetadata +camCinematicWaterCrashShotMetadata +camCollisionMetadata +camCollisionMetadataBuoyancySettings +camCollisionMetadataClippingAvoidance +camCollisionMetadataOcclusionSweep +camCollisionMetadataOrbitDistanceDamping +camCollisionMetadataPathFinding +camCollisionMetadataPullBackTowardsCollision +camCollisionMetadataPushBeyondEntitiesIfClipping +camCollisionMetadataRotationTowardsLos +camControlHelperMetadata +camControlHelperMetadataLookAround +camControlHelperMetaDataPrecisionAimSettings +camControlHelperMetadataViewModes +camControlHelperMetadataViewModeSettings +camControlHelperMetadataZoom +camCustomTimedSplineCameraMetadata +camCutsceneDirectorMetadata +camDebugDirectorMetadata +camDepthOfFieldSettingsMetadata +camEnvelopeMetadata +Camera +cameraPos +camFirstPersonAimCameraMetadataHeadingCorrection +camFirstPersonHeadTrackingAimCameraMetadata +camFirstPersonPedAimCameraMetadata +camFirstPersonShooterCameraMetadata +camFirstPersonShooterCameraMetadataCoverSettings +camFirstPersonShooterCameraMetadataOrientationSpring +camFirstPersonShooterCameraMetadataOrientationSpringLite +camFirstPersonShooterCameraMetadataRelativeAttachOrientationSettings +camFirstPersonShooterCameraMetadataSprintBreakOutSettings +camFirstPersonShooterCameraMetadataStickyAim +camFollowCameraMetadataFollowOrientationConing +camFollowCameraMetadataHighAltitudeZoomSettings +camFollowCameraMetadataPullAroundSettings +camFollowCameraMetadataRollSettings +camFollowParachuteCameraMetadata +camFollowParachuteCameraMetadataCustomSettings +camFollowPedCameraMetadata +camFollowPedCameraMetadataAssistedMovementAlignment +camFollowPedCameraMetadataCustomViewModeSettings +camFollowPedCameraMetadataDivingShakeSettings +camFollowPedCameraMetadataHighFallShakeSettings +camFollowPedCameraMetadataLadderAlignment +camFollowPedCameraMetadataOrbitPitchLimitsForOverheadCollision +camFollowPedCameraMetadataPushBeyondNearbyVehiclesInRagdollSettings +camFollowPedCameraMetadataRappellingAlignment +camFollowPedCameraMetadataRunningShakeSettings +camFollowPedCameraMetadataSwimmingShakeSettings +camFollowVehicleCameraMetadata +camFollowVehicleCameraMetadataDuckUnderOverheadCollisionSettings +camFollowVehicleCameraMetadataDuckUnderOverheadCollisionSettingsCapsuleSettings +camFollowVehicleCameraMetadataHandBrakeSwingSettings +camFollowVehicleCameraMetadataHighSpeedShakeSettings +camFollowVehicleCameraMetadataHighSpeedZoomSettings +camFollowVehicleCameraMetadataVerticalFlightModeSettings +camFollowVehicleCameraMetadataWaterEntryShakeSettings +camFreeCameraMetadata +camGameplayDirectorMetadata +camGameplayDirectorMetadataExplosionShakeSettings +camGameplayDirectorMetadataVehicleCustomSettings +camHintHelperMetadata +camHintHelperMetadataPivotPositionAdditive +camInconsistentBehaviourZoomHelperAirborneSettings +camInconsistentBehaviourZoomHelperDetectFastCameraTurnSettings +camInconsistentBehaviourZoomHelperDetectSuddenMovementSettings +camInconsistentBehaviourZoomHelperLosSettings +camInconsistentBehaviourZoomHelperMetadata +camLongSwoopSwitchHelperMetadata +camLookAheadHelperMetadata +camLookAtDampingHelperMetadata +camMarketingAToBCameraMetadata +camMarketingDirectorMetadata +camMarketingDirectorMetadataMode +camMarketingFreeCameraMetadata +camMarketingFreeCameraMetadataInputResponse +camMarketingMountedCameraMetadata +camMarketingOrbitCameraMetadata +camMarketingStickyCameraMetadata +camMetadataStore +camMotionBlurSettingsMetadata +camNearClipScannerMetadata +camOscillatorMetadata +camPreferredShotSelectionType +camReplayBaseCameraMetadataCollisionSettings +camReplayBaseCameraMetadataInputResponse +camReplayDirectorMetadata +camReplayFreeCameraMetadata +camReplayPresetCameraMetadata +camReplayRecordedCameraMetadata +camRoundedSplineCameraMetadata +camScriptDirectorMetadata +camScriptedCameraMetadata +camScriptedFlyCameraMetadata +camScriptedFlyCameraMetadataInputResponse +camSeatSpecificCameras +camShake +camShakeMetadata +camShakeMetadataFrameComponent +camShakeName +camShakeRollOffScaling +camShortRotationSwitchHelperMetadata +camShortTranslationSwitchHelperMetadata +camShortZoomInOutSwitchHelperMetadata +camShortZoomToHeadSwitchHelperMetadata +camSmoothedSplineCameraMetadata +camSpeedRelativeShakeSettingsMetadata +camSpringMountMetadata +camSwitchCameraMetadata +camSwitchDirectorMetadata +camSyncedSceneDirectorMetadata +camThirdPersonCameraMetadataBasePivotPosition +camThirdPersonCameraMetadataBasePivotPositionRollSettings +camThirdPersonCameraMetadataBuoyancySettings +camThirdPersonCameraMetadataCollisionFallBackPosition +camThirdPersonCameraMetadataCustomBoundingBoxSettings +camThirdPersonCameraMetadataLookOverSettings +camThirdPersonCameraMetadataPivotOverBoungingBoxSettings +camThirdPersonCameraMetadataPivotPosition +camThirdPersonCameraMetadataQuadrupedalHeightSpring +camThirdPersonCameraMetadataStealthZoomSettings +camThirdPersonCameraMetadataVehicleOnTopOfVehicleCollisionSettings +camThirdPersonPedAimCameraMetadata +camThirdPersonPedAimCameraMetadataLockOnOrbitDistanceSettings +camThirdPersonPedAimCameraMetadataLockOnTargetDampingSettings +camThirdPersonPedAimInCoverCameraMetadata +camThirdPersonPedAimInCoverCameraMetadataAimingSettings +camThirdPersonPedAimInCoverCameraMetadataLowCoverSettings +camThirdPersonPedAssistedAimCameraCinematicMomentSettings +camThirdPersonPedAssistedAimCameraInCoverSettings +camThirdPersonPedAssistedAimCameraLockOnAlignmentSettings +camThirdPersonPedAssistedAimCameraMetadata +camThirdPersonPedAssistedAimCameraPivotScalingSettings +camThirdPersonPedAssistedAimCameraPlayerFramingSettings +camThirdPersonPedAssistedAimCameraRecoilShakeScalingSettings +camThirdPersonPedAssistedAimCameraRunningShakeSettings +camThirdPersonPedAssistedAimCameraShakeActivityScalingSettings +camThirdPersonPedAssistedAimCameraShootingFocusSettings +camThirdPersonPedMeleeAimCameraMetadata +camThirdPersonVehicleAimCameraMetadata +camTimedSplineCameraMetadata +camVehicleCustomSettingsMetadata +camVehicleCustomSettingsMetadataAdditionalBoundScalingVehicleSettings +camVehicleCustomSettingsMetadataDoorAlignmentSettings +camVehicleCustomSettingsMetadataExitSeatPhaseForCameraExitSettings +camVehicleCustomSettingsMetadataInvalidCinematcShotsRefsForVehicleSettings +camVehicleCustomSettingsMetadataMultiplayerPassengerCameraHashSettings +camVehicleCustomSettingsMetadataSeatSpecficCameras +CAnimSpeedUps__Tunables +CanRideBikeWithNoHelmet +CanSpawnInCar +CantUse +CapsuleHalfHeight +CapsuleHalfWidth +CapsuleLen +CapsuleRadius +CapsuleZOffset +CAR +CARCOLS_FILE +carModel +CBaseArchetypeDef +CBikeLeanAngleHelper__Tunables +CCarGen +CClipScalingHelper__Tunables +CCombatTaskManager__Tunables +CCreatureMetaData +CCurve +CCurveSet +CDataFileMgr__ContentsOfDataFileXml +CDispatchAdvancedSpawnHelper__Tunables +CDispatchHelperSearchInAutomobile__Tunables +CDispatchHelperSearchInBoat__Tunables +CDispatchHelperSearchInHeli__Tunables +CDispatchHelperSearchOnFoot__Tunables +CDispatchHelperVolumes__Tunables +CDispatchSpawnHelper__Tunables +CDistantLODLight +CDoorTuningFile +CDynamicCoverHelper__Tunables +centerAndRadius +CEntityDef +CEventAgitated__Tunables +CEventCrimeCryForHelp__Tunables +CEventEncroachingPed__Tunables +CEventExplosionHeard__Tunables +CEventFootStepHeard__Tunables +CEventGunAimedAt__Tunables +CEventGunShot__Tunables +CEventMeleeAction__Tunables +CEventPedJackingMyVehicle__Tunables +CEventPotentialBeWalkedInto__Tunables +CEventPotentialBlast__Tunables +CEventPotentialGetRunOver__Tunables +CEventRequestHelp__Tunables +CEventRespondedToThreat__Tunables +CEventShocking__Tunables +CEventSuspiciousActivity__Tunables +CExplosionInfoManager +CExtensionDefAudioCollisionSettings +CExtensionDefAudioEmitter +CExtensionDefBuoyancy +CExtensionDefDoor +CExtensionDefExplosionEffect +CExtensionDefExpression +CExtensionDefLadder +CExtensionDefLightEffect +CExtensionDefLightShaft +CExtensionDefParticleEffect +CExtensionDefProcObject +CExtensionDefSpawnPoint +CExtensionDefSpawnPointOverride +CExtensionDefWindDisturbance +CFiringPatternInfo +CGrabHelper__Tunables +Chances +changeSetName +chassis +CHDTxdAssetBinding +childName +children +CLegIkSolver__Tunables +CLevelData +CLightAttrDef +Clip +CLIP_SETS_FILE +clipDictionaryMetadatas +clipDictionaryName +ClipDictionaryName +clipItems +clips +ClipSet +ClipSetId +clipSets +ClipSets +CLODLight +CLookAtHistory__Tunables +CMapData +CMapTypes +CMiniMap__Tunables +CMloArchetypeDef +CMloEntitySet +CMloInstanceDef +CMloPortalDef +CMloRoomDef +CMloTimeCycleModifier +CMultiTxdRelationship +CNmMessage +CNmParameterBool +CNmParameterFloat +CNmParameterInt +CNmParameterRandomFloat +CNmParameterRandomInt +CNmParameterResetMessage +CNmParameterString +CNmParameterVector +CNmTuningSet +col +collisionBone +CollisionData +CollisionRadius +color +Color +colors +colour +CombatInfo +Component +components +compositeEntityTypes +CompRestrictions +CONDITIONAL_ANIMS_FILE +CONTENT_UNLOCKING_META_FILE +contentChangeSets +contents +CONTENTS_ANIMATION +CONTENTS_CUTSCENE +CONTENTS_DLC_MAP_DATA +CONTENTS_LODS +CONTENTS_MAP +CONTENTS_PEDS +CONTENTS_PROPS +CONTENTS_VEHICLES +Context +corners +CPackFileMetaData +CPedCompExpressionData +CPedModelInfo__InitDataList +CPedModelInfo__PersonalityDataList +CPedPropExpressionData +CPedTargetEvaluator__Tunables +CPedTargetting__Tunables +CPlayerCoverClipVariationHelper__Tunables +CPlayerInfo__sPlayerStatInfo +CPlayerInfo__sSprintControlData +CPlayerInfo__Tunables +CPlayerPedTargeting__Tunables +CPoliceBoatDispatch__Tunables +CPrioritizedClipSetRequestManager__Tunables +CProceduralInfo +CPtFxAssetDependencyInfo +CPtFxAssetInfoMgr +CRandomEventManager__Tunables +CreatureMetadataName +CRelationshipManager__Tunables +Crimes +CScenarioClipHelper__Tunables +CScenarioPointGroup +CScenarioPointManifest +CScenarioPointRegionDef +CShaderVariableComponent +CSituationalClipSetStreamer__Tunables +CTacticalAnalysis__Tunables +CTacticalAnalysisCoverPoints__Tunables +CTacticalAnalysisCoverPointSearch__Tunables +CTacticalAnalysisNavMeshPoints__Tunables +CTargettingDifficultyInfo +CTaskAdvance__Tunables +CTaskAgitated__Tunables +CTaskAimAndThrowProjectile__Tunables +CTaskAimFromGround__Tunables +CTaskAimGunBlindFire__Tunables +CTaskAimGunFromCoverIntro__Tunables +CTaskAimGunFromCoverOutro__Tunables +CTaskAimGunOnFoot__Tunables +CTaskAimGunVehicleDriveBy__Tunables +CTaskAmbientClips__Tunables +CTaskAnimatedHitByExplosion__Tunables +CTaskArrestPed__Tunables +CTaskBoatChase__Tunables +CTaskBoatCombat__Tunables +CTaskBoatStrafe__Tunables +CTaskCallPolice__Tunables +CTaskCarReactToVehicleCollision__Tunables +CTaskChat__Tunables +CTaskCloseVehicleDoorFromInside__Tunables +CTaskCombat__Tunables +CTaskCombatAdditionalTask__Tunables +CTaskCombatFlank__Tunables +CTaskComplexEvasiveStep__Tunables +CTaskConfront__Tunables +CTaskConversationHelper__Tunables +CTaskCoupleScenario__Tunables +CTaskCover__Tunables +CTaskCowerScenario__Tunables +CTaskDamageElectric__Tunables +CTaskDraggingToSafety__Tunables +CTaskDyingDead__Tunables +CTaskEnterCover__Tunables +CTaskEnterVehicle__Tunables +CTaskEnterVehicleAlign__Tunables +CTaskEnterVehicleSeat__Tunables +CTaskExhaustedFlee__Tunables +CTaskExitCover__Tunables +CTaskExitVehicle__Tunables +CTaskExitVehicleSeat__Tunables +CTaskFall__Tunables +CTaskFishLocomotion__Tunables +CTaskFlyingWander__Tunables +CTaskFlyToPoint__Tunables +CTaskGetUp__Tunables +CTaskGoToScenario__Tunables +CTaskGrowlAndFlee__Tunables +CTaskGun__Tunables +CTaskHeliChase__Tunables +CTaskHeliCombat__Tunables +CTaskHelicopterStrafe__Tunables +CTaskHeliOrderResponse__Tunables +CTaskHeliPassengerRappel__Tunables +CTaskHumanLocomotion__Tunables +CTaskInCover__Tunables +CTaskIntimidate__Tunables +CTaskInVehicleBasic__Tunables +CTaskInvestigate__Tunables +CTaskJump__Tunables +CTaskMeleeActionResult__Tunables +CTaskMotionAiming__Tunables +CTaskMotionBasicLocomotionLowLod__Tunables +CTaskMotionInAutomobile__Tunables +CTaskMotionInCover__Tunables +CTaskMotionInTurret__Tunables +CTaskMotionInVehicle__Tunables +CTaskMotionOnBicycle__Tunables +CTaskMotionOnBicycleController__Tunables +CTaskMotionSwimming__Tunables +CTaskMotionTennis__Tunables +CTaskMoveCombatMounted__Tunables +CTaskMoveCrossRoadAtTrafficLights__Tunables +CTaskMoveFollowNavMesh__Tunables +CTaskMoveToTacticalPoint__Tunables +CTaskMoveWithinAttackWindow__Tunables +CTaskNMBalance__Tunables +CTaskNMBehaviour__Tunables +CTaskNMBrace__Tunables +CTaskNMBuoyancy__Tunables +CTaskNMControl__Tunables +CTaskNMDraggingToSafety__Tunables +CTaskNMDrunk__Tunables +CTaskNMElectrocute__Tunables +CTaskNMExplosion__Tunables +CTaskNMFlinch__Tunables +CTaskNMHighFall__Tunables +CTaskNMInjuredOnGround__Tunables +CTaskNMJumpRollFromRoadVehicle__Tunables +CTaskNMOnFire__Tunables +CTaskNMPrototype__Tunables +CTaskNMPrototype__Tunables__TimedTuning +CTaskNMRiverRapids__Tunables +CTaskNMShot__Tunables +CTaskNMSimple__Tunables +CTaskNMThroughWindscreen__Tunables +CTaskOpenVehicleDoorFromOutside__Tunables +CTaskParachute__Tunables +CTaskParachuteObject__Tunables +CTaskPlaneChase__Tunables +CTaskPlayerDrive__Tunables +CTaskPlayerOnFoot__Tunables +CTaskPoliceOrderResponse__Tunables +CTaskPursueCriminal__Tunables +CTaskQuadLocomotion__Tunables +CTaskRageRagdoll__Tunables +CTaskRappel__Tunables +CTaskReactAimWeapon__Tunables +CTaskReactAndFlee__Tunables +CTaskReactInDirection__Tunables +CTaskReactToBeingAskedToLeaveVehicle__Tunables +CTaskReactToBuddyShot__Tunables +CTaskReactToExplosion__Tunables +CTaskReactToImminentExplosion__Tunables +CTaskReactToPursuit__Tunables +CTaskRideTrain__Tunables +CTaskScenarioFlee__Tunables +CTaskSearch__Tunables +CTaskSearchBase__Tunables +CTaskSearchForUnknownThreat__Tunables +CTaskSearchInAutomobile__Tunables +CTaskSearchInBoat__Tunables +CTaskSearchInHeli__Tunables +CTaskSearchOnFoot__Tunables +CTaskSharkAttack__Tunables +CTaskSharkCircle__Tunables +CTaskShockingEvent__Tunables +CTaskShockingEventBackAway__Tunables +CTaskShockingEventGoto__Tunables +CTaskShockingEventHurryAway__Tunables +CTaskShockingEventReact__Tunables +CTaskShockingEventReactToAircraft__Tunables +CTaskShockingEventStopAndStare__Tunables +CTaskShockingEventWatch__Tunables +CTaskShockingPoliceInvestigate__Tunables +CTaskShootOutTire__Tunables +CTaskShove__Tunables +CTaskShoved__Tunables +CTaskSmartFlee__Tunables +CTaskStandGuard__Tunables +CTaskStealVehicle__Tunables +CTaskSwapWeapon__Tunables +CTaskSwatOrderResponse__Tunables +CTaskSwimmingWander__Tunables +CTaskTakeOffPedVariation__Tunables +CTaskTargetUnreachable__Tunables +CTaskTargetUnreachableInExterior__Tunables +CTaskTargetUnreachableInInterior__Tunables +CTaskTrainBase__Tunables +CTaskTryToGrabVehicleDoor__Tunables +CTaskUnalerted__Tunables +CTaskUseScenario__Tunables +CTaskUseVehicleScenario__Tunables +CTaskVariedAimPose__Tunables +CTaskVault__Tunables +CTaskVehicleApproach__Tunables +CTaskVehicleBlock__Tunables +CTaskVehicleBlockBackAndForth__Tunables +CTaskVehicleBlockBrakeInFront__Tunables +CTaskVehicleBlockCruiseInFront__Tunables +CTaskVehicleChase__Tunables +CTaskVehicleCombat__Tunables +CTaskVehicleCrash__Tunables +CTaskVehicleCruiseBoat__Tunables +CTaskVehicleDeadDriver__Tunables +CTaskVehicleFlee__Tunables +CTaskVehicleFleeBoat__Tunables +CTaskVehicleFSM__Tunables +CTaskVehicleGoToBoat__Tunables +CTaskVehicleGoToHelicopter__Tunables +CTaskVehicleGoToPlane__Tunables +CTaskVehicleGoToPointWithAvoidanceAutomobile__Tunables +CTaskVehicleLandPlane__Tunables +CTaskVehicleMissionBase__Tunables +CTaskVehicleParkNew__Tunables +CTaskVehiclePersuit__Tunables +CTaskVehiclePlaneChase__Tunables +CTaskVehiclePullAlongside__Tunables +CTaskVehiclePursue__Tunables +CTaskVehicleRam__Tunables +CTaskVehicleShotTire__Tunables +CTaskVehicleSpinOut__Tunables +CTaskWalkAway__Tunables +CTaskWander__Tunables +CTaskWanderInArea__Tunables +CTaskWanderingScenario__Tunables +CTaskWitness__Tunables +CTimeArchetypeDef +CTimeCycleModifier +CustomTriggerBox +CVehicleClipRequestHelper__Tunables +CVehicleModelInfoVarGlobal +CVehicleModelInfoVariation +CVehicleScenarioManager__AttractorTuning__Tunables +CVfxVehicleInfo +CVfxVehicleInfoMgr +CWanted__Tunables +CWantedHelicopterDispatch__Tunables +CWildlifeManager__Tunables +damageAtCentre +damageAtEdge +dataFiles +DECALS_FILE +decayFactor +DecisionMakerName +Default +DefaultBrawlingStyle +DefaultGestureClipSet +DefaultRemoveRangeMultiplier +DefaultSpawningPreference +DefaultTaskDataSetName +DefaultUnarmedWeapon +DefaultVisemeClipSet +DelayDoorClosingForPlayer +Density +DensityRange +directedLifeTime +directedWidth +direction +Direction +disableBonnetCamera +disabled +Disabled +disabledFiles +Dispatch +Distance +DistanceRange +DISTANT_LIGHTS_FILE +DISTANT_LIGHTS_HD_FILE +distBetweenCoronas +distBetweenCoronas_far +DLC_ITYP_REQUEST +DLC_SCRIPT_METAFILE +DLC_WEAPON_PICKUPS +dlcName +DontCloseWhenTouched +door_dside_f +door_dside_r +door_pside_f +door_pside_r +DOOR_TUNING_FILE +drawableDictionary +DrawableId +DrawableIndex +DSP_NORMAL +duration +Duration +Edges +effectsData +emmissiveBoost +EMPTY +Enable +enabled +Enabled +EnabledByDefault +end +End +endHour +EndModel +endPhase +endRadius +enforceLsnSorting +engineblock +engineDamagePtFxEnabled +engineDamagePtFxHasPanel +engineDamagePtFxHasRotorEvo +engineDamagePtFxNoPanelName +engineDamagePtFxPanelOpenName +engineDamagePtFxPanelShutName +engineDamagePtFxRange +engineDamagePtFxSpeedEvoMax +engineDamagePtFxSpeedEvoMin +engineStartupPtFxEnabled +engineStartupPtFxName +engineStartupPtFxRange +entities +ENTITYFX_FILE +EventType +exclusions +executionConditions +exhaust +exhaust_2 +exhaust_3 +exhaust_4 +exhaustPtFxCutOffSpeed +exhaustPtFxEnabled +exhaustPtFxName +exhaustPtFxRange +exhaustPtFxScale +exhaustPtFxSpeedEvoMax +exhaustPtFxSpeedEvoMin +exhaustPtFxTempEvoMax +exhaustPtFxTempEvoMin +exhaustPtFxThrottleEvoOnGearChange +explodeAttachEntityWhenFinished +Explosion +EXPLOSION_INFO_FILE +EXPLOSIONFX_FILE +ExpressionDictionaryName +expressionName +ExpressionName +ExpressionSetName +extendedRange +extensions +ExternallyDrivenDOFs +extra_1 +extra_2 +extra_3 +extra_4 +extra_5 +EXTRA_FOLDER_MOUNT_DATA +EXTRA_TITLE_UPDATE_DATA +FacialClipsetGroupName +fallbackId +Falling +falloff +falloffExponent +falloffMax +Female +FFrontOffset +Fight +filename +filesToDisable +filesToEnable +filesToInvalidate +fileType +FIREFX_FILE +FirstPersonDriveByIKOffset +flags +Flags +flash +Flee +forceFactor +Forward +Fov +fragDamage +fRagdollForceModifier +frontIndicatorCorona +fSelfForceModifier +FullBodyDamageClipSet +FUpOffset +fwClipItem +fwClipItemWithProps +fwClipSet +fwClipSetManager +fxName +fxOffsetPos +fxOffsetRot +fxType +GetupSetHash +GroundColor +group +Group +Groups +GTXD_PARENTING_DATA +guid +HANDLING_FILE +hash +HDDist +HDTxd +HDTxdBindingArray +Heading +HeadingLimits +headLight +headlight_l +headlight_r +headLightCorona +Height +HIGH_HEELS +highPri +HoldDuration +hub_lf +hub_rf +iCosZ +id +Id +identifier +Idle +IdleTransitionBlendOutTime +IdleTransitions +ids +IgnoreMaxInRange +IgnoreOpenDoorTaskEdgeLerp +IgnorePavementChecks +imapDependencies +imapDependencies_2 +imapName +IN_VEHICLE +includedDataFiles +includedXmlFiles +Index +indicator +indicator_lf +indicator_rf +indices +Infos +InitDatas +initSpeed +InjuredStrafeClipSet +innerConeAngle +installPartition +intensity +Intensity +intensity_far +IntensityVar +interior +INTERIOR_PROXY_ORDER_FILE +InteriorNames +Interiors +IPL_FILE +iRadius +IsHeadBlendPed +iSinZ +IsStreamedGfx +Item +itypDependencies_2 +iType +JUNCTION_TEMPLATES_FILE +JUNCTION_TEMPLATES_PSO_FILE +kBoth +Key +KilledPerceptionRangeModifer +kitName +kits +Kits +kitType +leakPtFxEnabled +leakPtFxOilName +leakPtFxPetrolName +leakPtFxRange +leakPtFxSpeedEvoMax +leakPtFxSpeedEvoMin +length +LifeTime +Lights +lightSettings +limitAngle +linkedModels +linkMods +LIQUIDFX_FILE +liveries +livery +liveryNames +loadCompletely +LoadOut +LOADOUTS_FILE +locations +locked +lodDist +lodLevel +LODTYPES_DEPTH_HD +LODTYPES_DEPTH_SLOD1 +LODTYPES_DEPTH_SLOD2 +mapChangeSetData +MapDataGroups +MAPZONES_FILE +maskID +MassMultiplier +MATERIALFX_FILE +max +Max +MaxDistance +MaxPassengersInCar +MaxScale +MaxScaleZ +MaxSpeed +MaxTime +MaxTintPalette +MaxXRotation +MaxYRotation +MaxZOffset +MaxZRotation +memoryGroup +MicroMovementsFreqH +MicroMovementsFreqV +MicroMovementsScaleH +MicroMovementsScaleV +min +Min +MinActivationImpulse +MinDistance +minorExplosion +MinScale +MinScaleZ +MinTime +MinTintPalette +MinXRotation +MinYRotation +MinZOffset +MinZRotation +mirrorTexture +misc_a +misc_b +misc_c +misc_d +misc_e +misc_f +misc_g +misc_h +misc_i +misc_j +misc_k +misc_l +misc_m +misc_n +misc_o +misc_p +misc_q +misc_r +misc_s +misc_t +misc_u +misc_v +misc_w +misc_x +misc_y +misc_z +misfirePtFxEnabled +misfirePtFxName +misfirePtFxRange +MKT_SPECIAL +MKT_SPORT +MKT_STANDARD +MKT_SUV +mod_col_1 +mod_col_2 +mod_col_3 +mod_col_4 +mod_col_5 +ModelId +modelName +ModelName +ModelSet +ModelToTuneMapping +modifier +modShopLabel +MotionTaskDataSetName +Move +MOVE_NETWORK_DEFS +MoveBlendRatio +MovementClipSet +MovementClipSetId +MovementModes +MovementModeUnholsterData +MovementToStrafeClipSet +moveNetworkFlags +MP_STATS_DISPLAY_LIST_FILE +MP_STATS_UI_LIST_FILE +mtlBangPtFxVehicleEvo +mtlBangPtFxVehicleScale +mtlScrapePtFxVehicleEvo +mtlScrapePtFxVehicleScale +multiples +multiTxdRelationships +MustUse +name +Name +NamedTuningArray +NavCapabilitiesName +NAVMESH_INDEXREMAPPING_FILE +NAVNODE_INDEXREMAPPING_FILE +networkPedModifier +networkPlayerModifier +Nodes +none +None +normal +Normal +NormalMapName +NUM_ANCHORS +numCoronas +OBJ_COVER_TUNING_FILE +offset +offsetPosition +offsetRotation +ON_FOOT +opacity +outerConeAngle +overlay +OVERLAY_INFO_FILE +overturnedSmokePtFxAngleThresh +overturnedSmokePtFxEnabled +overturnedSmokePtFxEngineHealthThresh +overturnedSmokePtFxName +overturnedSmokePtFxRange +overturnedSmokePtFxSpeedThresh +owner +OwnerName +Pad +parent +parentIndex +parentName +PARTITION_0 +PARTITION_1 +PARTITION_2 +patchFiles +PATH_ZONES_FILE +PED_DAMAGE_APPEND_FILE +PED_FIRST_PERSON_ALTERNATE_DATA +PED_FIRST_PERSON_ASSET_DATA +PED_METADATA_FILE +PED_OVERLAY_FILE +PED_PERSONALITY_FILE +PedCapsuleName +pedCompExpressionIndex +pedCompExpressions +pedcompID +pedCompID +PedComponentClothName +PedComponentSetName +pedCompVarIndex +PedIKSettingsName +PedLayoutName +PedPersonalities +pedPropExpressionIndex +pedPropExpressions +pedPropID +pedPropVarIndex +Peds +PedScale +PEDSTREAM_FILE +pedType +Pedtype +PedVoiceGroup +percentage +PerceptionInfo +PERMANENT_ITYP_FILE +persistent +Personality +petrolTankFirePtFxName +petrolTankFirePtFxRadius +petrolTankFirePtFxRange +petrolTankFirePtFxSpeedEvoMax +petrolTankFirePtFxSpeedEvoMin +Pistol +Pitch +PitchChangeRate +PitchLimits +PitchOffset +PLANE +planeAfterburnerPtFxEnabled +planeAfterburnerPtFxName +planeAfterburnerPtFxRange +planeAfterburnerPtFxScale +planeDamageFirePtFxEnabled +planeDamageFirePtFxName +planeDamageFirePtFxRange +planeDamageFirePtFxSpeedEvoMax +planeDamageFirePtFxSpeedEvoMin +planeGroundDisturbPtFxDist +planeGroundDisturbPtFxEnabled +planeGroundDisturbPtFxNameDefault +planeGroundDisturbPtFxNameDirt +planeGroundDisturbPtFxNameFoliage +planeGroundDisturbPtFxNameSand +planeGroundDisturbPtFxNameWater +planeGroundDisturbPtFxRange +planeGroundDisturbPtFxSpeedEvoMax +planeGroundDisturbPtFxSpeedEvoMin +planeWingTipPtFxEnabled +planeWingTipPtFxName +planeWingTipPtFxRange +planeWingTipPtFxSpeedEvoMax +planeWingTipPtFxSpeedEvoMin +plantInfos +PlantTag +plateProbabilities +Player +POPGRP_FILE +POPSCHED_FILE +PoseMatcherName +PoseMatcherProneName +position +Position +PositionOffset +posn +PovCameraOffset +PreciseUseTime +priority +Priority +Probabilities +probability +PROC_META_FILE +PROCOBJ_ALIGN_OBJ +PROCOBJ_CAST_SHADOW +PROCOBJ_FILE +PROCOBJ_IS_FLOATING +PROCOBJ_NETWORK_GAME +PROCOBJ_USE_SEED +procObjInfos +PROCPLANT_CAMERADONOTCULL +PROCPLANT_FURGRASS +PROCPLANT_GROUNDSCALE1VERT +PROCPLANT_LOD0 +PROCPLANT_LOD1 +PROCPLANT_LOD2 +PROCPLANT_NOGROUNDSKEW_LOD0 +PROCPLANT_NOGROUNDSKEW_LOD1 +PROCPLANT_NOGROUNDSKEW_LOD2 +PROCPLANT_NOSHADOW +PROCPLANT_UNDERWATER +procTagTable +PropRestrictions +props +PropsName +ptfxAssetDependencyInfos +PTFXASSETINFO_FILE +ptFxHasTint +ptFxIsTriggered +ptFxName +ptFxProbability +ptFxScale +ptFxSize +ptFxSpeedEvoMax +ptFxSpeedEvoMin +ptFxTag +ptFxTintB +ptFxTintG +ptFxTintR +pull +pullCoronaIn +PV_COMP_ACCS +PV_COMP_BERD +PV_COMP_DECL +PV_COMP_FEET +PV_COMP_HAIR +PV_COMP_HAND +PV_COMP_HEAD +PV_COMP_JBIB +PV_COMP_LOWR +PV_COMP_MAX +PV_COMP_TASK +PV_COMP_TEEF +PV_COMP_UPPR +RADIO_GENRE_CLASSIC_ROCK +RADIO_GENRE_JAZZ +RADIO_GENRE_MEXICAN +RADIO_GENRE_MODERN_ROCK +RADIO_GENRE_MOTOWN +RADIO_GENRE_OFF +RADIO_GENRE_PUNK +RADIO_GENRE_REGGAE +RADIO_GENRE_RIGHT_WING_TALK +RADIO_GENRE_SURF +Radio1 +Radio2 +radius +Radius +RadiusScale +rage__fwInstancedMapData +rage__phVerletClothCustomBounds +rage__spdGrid2D +range +Rate +rear +rearIndicatorCorona +RegionDefs +RelationshipGroup +requiredImap +requiresLoadingScreen +ResetNoCollisionOnCleanUp +residentAnims +residentResources +residentTxd +Restriction +reversingLight +reversingLightCorona +RFrontOffset +RGBI +Rifle +rimRadius +Roll +rooms +rotate +rotation +Rotation +RotationLimitAngle +RPF_FILE +RPF_FILE_PRE_INSTALL +RumbleDuration +RUpOffset +SAT_NONE +scale +Scale +SCALEFORM_DLC_FILE +ScaleRange +ScaleRangeXYZ +ScaleRangeZ +ScaleVariationXY +ScaleVariationZ +ScaleXY +ScaleZ +SCENARIO_INFO_FILE +SCENARIO_POINTS_PSO_FILE +SCENARIO_POP_STREAMING_NORMAL +ScenarioPoints +ScenarioPopStreamingSlot +ScenarioType +SCRIPTFX_FILE +SeatIndex +Seats +sets +Sets +settings +Settings +Sexiness +SF_HOT_PERSON +SF_JEER_AT_HOT_PED +shaderVariableComponents +shaderVariableHashString +shadowBlur +shockingEventAudioRangeOverride +shockingEventVisualRangeOverride +SHOP_PED_APPAREL_META_FILE +shortRange +ShouldLatchShut +SidestepClipSet +sirenSettings +Situations +size +size_far +sLevelData +SLOD_HUMAN +slot +slotNames +SLOWNESS_ZONES_FILE +Sniper +SP_Low +SP_Medium +SP_MULTIPLAYER_RESIDENT +SP_SINGLEPLAYER_RESIDENT +SP_STATS_DISPLAY_LIST_FILE +SP_STATS_UI_LIST_FILE +SP_STREAMING +spacing +Spacing +spawnType +specialAttribute +speed +sphere +Spheres +splashInPtFxEnabled +splashInPtFxName +splashInPtFxRange +splashInPtFxSizeEvoMax +splashInPtFxSpeedDownwardEvoMax +splashInPtFxSpeedDownwardEvoMin +splashInPtFxSpeedDownwardThresh +splashInPtFxSpeedLateralEvoMax +splashInPtFxSpeedLateralEvoMin +splashOutPtFxEnabled +splashOutPtFxName +splashOutPtFxRange +splashOutPtFxSizeEvoMax +splashOutPtFxSpeedLateralEvoMax +splashOutPtFxSpeedLateralEvoMin +splashOutPtFxSpeedUpwardEvoMax +splashOutPtFxSpeedUpwardEvoMin +splashTrailPtFxEnabled +splashTrailPtFxName +splashTrailPtFxRange +splashTrailPtFxSizeEvoMax +splashTrailPtFxSpeedEvoMax +splashTrailPtFxSpeedEvoMin +splashWadePtFxEnabled +splashWadePtFxName +splashWadePtFxRange +splashWadePtFxSizeEvoMax +splashWadePtFxSpeedRiverEvoMax +splashWadePtFxSpeedRiverEvoMin +splashWadePtFxSpeedVehicleEvoMax +splashWadePtFxSpeedVehicleEvoMin +sStatsMetadataTuning +StaggerFall +Standard +start +Start +startHour +StartModel +startPhase +StationaryReactions +statMods +STATS_METADATA_PSO_FILE +StdDoorOpenBothDir +StdDoorOpenNegDir +StdDoorRotDir +steeringwheel +Stiffness +StillToSitPedalGearApproachRate +StrafeClipSet +STREAMING_REQUEST_LISTS_FILE +streamingPolicy +streamingPriority +STREET_VEHICLE_ASSOCIATION_FILE +strength +Stubble +SuperlodType +Tag +tailLight +tailLightCorona +tailLightMiddleCorona +tangent +Target +targetAsset +TargetingThreatModifier +TargetOffset +TargetRadius +TaskDataName +TATTOO_SHOP_DLC_FILE +TB_WARM +TechSavvy +Teeter +template +texId +TEXTFILE_METAFILE +textureDictionary +TextureId +textureName +ThermalBehaviour +time +TIME_FILE +TIMECYCLE_FILE +TIMECYCLEMOD_FILE +timeCycleModifiers +timeTillPedLeaves +top +TorqueAngularVelocityLimit +tracks +TRAILER +TRAINCONFIGS_FILE +TRAINTRACK_FILE +TriggerBoxMinMax +TS_LOW +Tunables +Tuning +TuningName +Turn +turnOffBones +turnOffExtra +txdRelationships +txdToLoad +txdToUnload +type +types +UnholsterClipData +UnholsterClips +UnholsterClipSetId +unregisterResources +Update +UpperBodyFeatheredLeanEnabled +UpperBodyShadowExpressionEnabled +UseAutoOpenTriggerBox +UseLeftHandIk +UseWeaponAnimsForGrip +Value +variationData +Variations +VEHGEN_MARKUP_FILE +VEHICLE_LAYOUTS_FILE +VEHICLE_METADATA_FILE +VEHICLE_POPULATION_FILE +VEHICLE_RESPONSE_ARMY_BASE +VEHICLE_RESPONSE_COUNTRYSIDE +VEHICLE_SHOP_DLC_FILE +VEHICLE_VARIATION_FILE +VEHICLEEXTRAS_FILE +VehicleScale +Velocity +version +VersionNumber +verts +VFX_SETTINGS_FILE +VFXFOGVOLUMEINFO_FILE +VfxInfoName +VFXINTERIORINFO_FILE +VFXPEDINFO_FILE +VFXREGIONINFO_FILE +vfxTagHashName +VFXVEHICLEINFO_FILE +vfxVehicleInfos +VFXWEAPONINFO_FILE +visibleMods +vlink87812 +VMCP_DEFAULT +VMT_ARMOUR +VMT_BONNET +VMT_BRAKES +VMT_BUMPER_F +VMT_BUMPER_R +VMT_CHASSIS +VMT_CHASSIS2 +VMT_CHASSIS3 +VMT_CHASSIS4 +VMT_CHASSIS5 +VMT_DOOR_L +VMT_ENGINE +VMT_ENGINEBAY1 +VMT_ENGINEBAY2 +VMT_ENGINEBAY3 +VMT_EXHAUST +VMT_GEARBOX +VMT_GRILL +VMT_HORN +VMT_HYDRO +VMT_ICE +VMT_INTERIOR1 +VMT_INTERIOR2 +VMT_INTERIOR3 +VMT_INTERIOR4 +VMT_INTERIOR5 +VMT_KNOB +VMT_LIVERY_MOD +VMT_PLAQUE +VMT_PLTHOLDER +VMT_PLTVANITY +VMT_ROOF +VMT_SEATS +VMT_SKIRT +VMT_SPOILER +VMT_STEERING +VMT_SUSPENSION +VMT_TRUNK +VMT_WHEELS +VMT_WHEELS_REAR_OR_HYDRAULICS +VMT_WING_L +VMT_WING_R +vPos +WantedLevel1 +WantedLevel2 +WantedLevel3 +WantedLevel4 +WantedLevel5 +WATER_FILE +Weak +WEAPON_ANIMATIONS_FILE +WEAPON_METADATA_FILE +WEAPON_SHOP_INFO_METADATA_FILE +WeaponAccuracy +WeaponAnimations +WeaponClipFilterId +WeaponClipSetId +WEAPONCOMPONENTSINFO_FILE +WEAPONFX_FILE +WeaponImpulseMultiplier +WEAPONINFO_FILE +WEAPONINFO_FILE_PATCH +Weapons +WEATHER_FILE +WeatherTypes +weight +wheelBurnoutPtFxFricMult +wheelBurnoutPtFxTempMult +wheelBurstPtFxName +wheelBurstPtFxRange +wheelDisplacementPtFxDispMult +wheelFirePtFxName +wheelFirePtFxRange +wheelFirePtFxSpeedEvoMax +wheelFirePtFxSpeedEvoMin +wheelFrictionPtFxFricMult +WHEELFX_FILE +wheelGenericDecalSet +wheelGenericPtFxSet +wheelGenericRangeMult +wheelLowLodPtFxScale +wheelName +wheelPuncturePtFxName +wheelPuncturePtFxRange +Wheels +wheelSkidmarkPressureMult +wheelSkidmarkRearOnly +wheelSkidmarkSlipMult +wheelVariation +Width +WindBendScale +WindBendVariation +window_lf +window_rf +windowsWithExposedEdges +windscreen_r +wing_lf +wing_rf +WORLD_HEIGHTMAP_FILE +WORLD_WATERHEIGHT_FILE +wreckedFire2OffsetPos +wreckedFire2PtFxDurationMax +wreckedFire2PtFxDurationMin +wreckedFire2PtFxEnabled +wreckedFire2PtFxName +wreckedFire2PtFxRadius +wreckedFire2UseOverheatBone +wreckedFire3OffsetPos +wreckedFire3PtFxDurationMax +wreckedFire3PtFxDurationMin +wreckedFire3PtFxEnabled +wreckedFire3PtFxName +wreckedFire3PtFxRadius +wreckedFire3UseOverheatBone +wreckedFirePtFxDurationMax +wreckedFirePtFxDurationMin +wreckedFirePtFxEnabled +wreckedFirePtFxName +wreckedFirePtFxRadius +x +X +xRotation +y +Y +yRotation +z +Z +zBias +ZONEBIND_FILE +zRotation"; + + } + + + + + + public enum MetaName : uint + { + aabb = 293662904, + AABB = 1666779607, + AbilityType = 229841885, + Action = 1705836299, + activeChangesetConditions = 618424668, + AdditiveDamageClipSet = 1159808383, + AET_Directed_In_Place = 1450000159, + AET_Flinch = 2886590336, + AET_In_Place = 3552718780, + AET_Interesting = 478982036, + AET_Threatened = 1152560683, + AET_Threatening = 56876971, + aExplosionTagData = 2196546139, + AFF_POOR = 1885794222, + Affluence = 2895355855, + Age = 2099622785, + aircraftDownwashPtFxDist = 1452685083, + aircraftDownwashPtFxEnabled = 1469712840, + aircraftDownwashPtFxNameDefault = 461290670, + aircraftDownwashPtFxNameDirt = 2734634606, + aircraftDownwashPtFxNameFoliage = 2573299811, + aircraftDownwashPtFxNameSand = 1320803722, + aircraftDownwashPtFxNameWater = 1934771968, + aircraftDownwashPtFxRange = 192247734, + aircraftDownwashPtFxSpeedEvoMax = 632867260, + aircraftDownwashPtFxSpeedEvoMin = 4072762094, + aircraftSectionDamageSmokePtFxEnabled = 136971974, + aircraftSectionDamageSmokePtFxName = 345776584, + aircraftSectionDamageSmokePtFxRange = 2299979830, + aircraftSectionDamageSmokePtFxSpeedEvoMax = 1864737051, + aircraftSectionDamageSmokePtFxSpeedEvoMin = 3715270087, + ALL = 3690519890, + Allow = 1329228842, + allowBonnetSlide = 1294495304, + AllowCloseSpawning = 4019244692, + ALTERNATE_VARIATIONS_FILE = 611054590, + AmbientClipsForFlee = 1496688419, + AmbulanceShouldRespondTo = 2153846297, + Amount = 42366424, + Amplitude = 946881915, + anchor = 1880738441, + ANCHOR_EARS = 119829315, + ANCHOR_EYES = 1125276126, + ANCHOR_HEAD = 2389455644, + ANCHOR_LEFT_WRIST = 935290624, + ANCHOR_RIGHT_WRIST = 1131235937, + AnimalAudioObject = 1131698046, + AnimatedModel = 1544926406, + Animations = 212063203, + AnimDict = 1027851728, + AnimName = 1300132907, + AP_LOW = 2695760829, + AP_MEDIUM = 629290484, + APF_ISBLENDAUTOREMOVE = 4147018654, + APF_ISLOOPED = 829168795, + Apply = 804826100, + archetypeName = 2686689324, + archetypes = 25836315, + areas = 4258609502, + assetName = 2591541189, + assetType = 110101682, + AT_TXD = 3870813049, + AUDIO_DYNAMIXDATA = 2538787365, + AUDIO_GAMEDATA = 2568179508, + AUDIO_SOUNDDATA = 4061522791, + AUDIO_SPEECHDATA = 2934881832, + AUDIO_SYNTHDATA = 1488170759, + AUDIO_WAVEPACK = 1781244916, + audioApply = 636362136, + audioId = 3218488635, + AUDIOMESH_INDEXREMAPPING_FILE = 26529435, + AutoOpenCloseRateTaper = 838139088, + AutoOpenCosineAngleBetweenThreshold = 2537405501, + AutoOpenRadiusModifier = 380434751, + AutoOpenRate = 4024424870, + AutoOpensForAllVehicles = 1314594320, + AutoOpensForLawEnforcement = 711087453, + AutoOpensForMPPlayerPedsOnly = 2116737868, + AutoOpensForMPVehicleWithPedsOnly = 4004737101, + AutoOpensForSPPlayerPedsOnly = 17022999, + AutoOpensForSPVehicleWithPedsOnly = 883718936, + AutoOpenVolumeOffset = 2598815900, + availableInMpSp = 286077157, + backfirePtFxEnabled = 3590298048, + backfirePtFxName = 326241207, + backfirePtFxRange = 2051678496, + bAppliesContinuousDamage = 1994294878, + bbMax = 3884623384, + bbMin = 3656352310, + bCanSetPedOnFire = 1975010672, + bDamageObjects = 3087256498, + bDamageVehicles = 410915188, + BF_ALLOW_CONFRONT_FOR_TERRITORY_REACTIONS = 135224044, + BF_BOOST_BRAVERY_IN_GROUP = 1233676580, + BF_COWARDLY_FOR_SHOCKING_EVENTS = 2349079456, + Bias = 2130430791, + BICYCLE = 3348377513, + bIgnoreExplodingEntity = 558484383, + BIKE = 1039130067, + blend = 3933447691, + Blend = 3998560112, + BlendOutDelta = 2689634897, + BlendShapeFileName = 538335227, + block = 3828602749, + BLOODFX_FILE = 2150607422, + bmax = 3220565995, + bmin = 2028577215, + bNoOcclusion = 1554370232, + BOAT = 3921641754, + boatBowPtFxEnabled = 3846459290, + boatBowPtFxForwardName = 1639130517, + boatBowPtFxKeelEvoMax = 237804409, + boatBowPtFxKeelEvoMin = 3676512912, + boatBowPtFxRange = 985220618, + boatBowPtFxReverseName = 547727530, + boatBowPtFxReverseOffset = 3858334001, + boatBowPtFxScale = 1915459369, + boatBowPtFxSpeedEvoMax = 1653246433, + boatBowPtFxSpeedEvoMin = 2239940421, + boatEntryPtFxEnabled = 2986953331, + boatEntryPtFxName = 3178605558, + boatEntryPtFxRange = 3592388731, + boatEntryPtFxScale = 2701410410, + boatEntryPtFxSpeedEvoMax = 2846825758, + boatEntryPtFxSpeedEvoMin = 690983709, + boatLowLodWakePtFxEnabled = 1609784914, + boatLowLodWakePtFxName = 4184644587, + boatLowLodWakePtFxRangeMax = 2835234692, + boatLowLodWakePtFxRangeMin = 661173079, + boatLowLodWakePtFxScale = 3728892023, + boatLowLodWakePtFxSpeedEvoMax = 3584741482, + boatLowLodWakePtFxSpeedEvoMin = 1014081258, + boatPropellerPtFxBackwardSpeedEvoMax = 2824456943, + boatPropellerPtFxBackwardSpeedEvoMin = 3685235291, + boatPropellerPtFxDepthEvoMax = 1772973337, + boatPropellerPtFxDepthEvoMin = 3807963294, + boatPropellerPtFxEnabled = 620740022, + boatPropellerPtFxForwardSpeedEvoMax = 4046105228, + boatPropellerPtFxForwardSpeedEvoMin = 3958699285, + boatPropellerPtFxName = 2372580323, + boatPropellerPtFxRange = 333451303, + boatPropellerPtFxScale = 2960340578, + boatWashPtFxEnabled = 1083605797, + boatWashPtFxName = 1782303759, + boatWashPtFxRange = 3400904137, + boatWashPtFxScale = 3769797352, + boatWashPtFxSpeedEvoMax = 1641333397, + boatWashPtFxSpeedEvoMin = 3421082045, + bobble_base = 1417117096, + bobble_head = 1789547068, + bone = 282216227, + boneMask = 593061963, + boneTag = 702019504, + BONETAG_HEAD = 3914473216, + BONETAG_INVALID = 3548260605, + BONETAG_L_CALF = 4031667174, + BONETAG_L_CLAVICLE = 3253512823, + BONETAG_L_FINGER22 = 222561854, + BONETAG_L_FOOT = 1655517369, + BONETAG_L_FOREARM = 2583642279, + BONETAG_L_HAND = 3058573909, + BONETAG_L_PH_HAND = 2994337423, + BONETAG_L_THIGH = 2825836160, + BONETAG_L_UPPERARM = 3728862758, + BONETAG_NECK = 1526074386, + BONETAG_NECK2 = 3577705298, + BONETAG_PELVIS = 572940669, + BONETAG_PELVIS1 = 2070754819, + BONETAG_R_CALF = 1591530804, + BONETAG_R_CLAVICLE = 623050371, + BONETAG_R_FINGER22 = 1557592184, + BONETAG_R_FOOT = 3872946345, + BONETAG_R_FOREARM = 3269208355, + BONETAG_R_HAND = 1128649107, + BONETAG_R_PH_HAND = 1835505437, + BONETAG_R_THIGH = 1692969046, + BONETAG_R_UPPERARM = 868290042, + BONETAG_ROOT = 102109035, + BONETAG_SPINE_ROOT = 4085918559, + BONETAG_SPINE0 = 2529646404, + BONETAG_SPINE1 = 2239149219, + BONETAG_SPINE2 = 740327916, + BONETAG_SPINE3 = 2718199230, + BONETAG_TAIL1 = 1278001105, + BONETAG_TAIL2 = 2362982695, + bOnlyAffectsLivePeds = 2543255645, + bOnlyBulkyItemVariations = 3412263941, + bonnet = 1704829083, + boot = 3042873625, + bottom = 4007699126, + bPostProcessCollisionsWithNoForce = 1091620747, + bPreventWaterExplosionVFX = 3664732218, + BreakableByVehicle = 3427926298, + BreakingImpulse = 1467901147, + bsCentre = 3591926527, + bsRadius = 2196293086, + bSuppressCrime = 1060477616, + bumper_f = 3886330357, + bumper_r = 2370370867, + bUseDistanceDamageCalc = 1929564509, + CAiCoverClipVariationHelper__Tunables = 1889755865, + camAnimatedCameraMetadata = 2493365232, + camAnimatedShakeMetadata = 830598329, + camAnimSceneDirectorMetadata = 3688863121, + CAmbientLookAt__Tunables = 3791958970, + CAmbientPedModelVariations = 949980109, + camCatchUpHelperMetadata = 1074754094, + camCinematicAnimatedCameraMetadata = 597434980, + camCinematicBustedContextMetadata = 2582741472, + camCinematicBustedShotMetadata = 46335367, + camCinematicCameraManCameraMetadata = 1752694078, + camCinematicCameraManShotMetadata = 3795997700, + camCinematicCameraOperatorShakeSettings = 267450829, + camCinematicCameraOperatorShakeTurbulenceSettings = 2761299644, + camCinematicCameraOperatorShakeUncertaintySettings = 1672408332, + camCinematicCraningCameraManShotMetadata = 644794406, + camCinematicDirectorMetadata = 2947939407, + camCinematicFallFromHeliContextMetadata = 3141653833, + camCinematicFallFromHeliShotMetadata = 4001219648, + camCinematicFirstPersonIdleCameraMetadata = 3500761789, + camCinematicGroupCameraMetadata = 2180005320, + camCinematicHeliChaseCameraMetadata = 385169240, + camCinematicHeliTrackingShotMetadata = 50998987, + camCinematicIdleCameraMetadata = 3818374703, + camCinematicIdleShots = 3503595515, + camCinematicInTrainAtStationContextMetadata = 3022638185, + camCinematicInTrainContextMetadata = 3314933929, + camCinematicInVehicleContextMetadata = 1660686749, + camCinematicInVehicleCrashShotMetadata = 35962033, + camCinematicInVehicleFirstPersonContextMetadata = 976409621, + camCinematicInVehicleMultiplayerPassengerContextMetadata = 2822987935, + camCinematicInVehicleOverriddenFirstPersonContextMetadata = 1737743598, + camCinematicInVehicleWantedContextMetadata = 3656622133, + camCinematicMissileKillShotMetadata = 947812684, + camCinematicMountedCameraMetadata = 2185301869, + camCinematicMountedCameraMetadataFirstPersonPitchOffset = 2402191709, + camCinematicMountedCameraMetadataFirstPersonRoll = 4132129159, + camCinematicMountedCameraMetadataLeadingLookSettings = 954561561, + camCinematicMountedCameraMetadataLookAroundSettings = 1554281348, + camCinematicMountedCameraMetadataMovementOnAccelerationSettings = 3508760093, + camCinematicMountedCameraMetadataOrientationSpring = 356764392, + camCinematicMountedCameraMetadataRelativePitchScalingToThrottle = 745700012, + camCinematicMountedPartCameraMetadata = 3009480533, + camCinematicOnFootAssistedAimingContextMetadata = 3749335843, + camCinematicOnFootAssistedAimingKillShotMetadata = 2251342366, + camCinematicOnFootFirstPersonIdleShotMetadata = 371427845, + camCinematicOnFootIdleContextMetadata = 251156589, + camCinematicOnFootIdleShotMetadata = 1361168617, + camCinematicOnFootMeleeContextMetadata = 254446303, + camCinematicOnFootMeleeShotMetadata = 341599647, + camCinematicOnFootSpectatingContextMetadata = 4029911638, + camCinematicParachuteCameraManShotMetadata = 4063985916, + camCinematicParachuteContextMetadata = 13761107, + camCinematicParachuteHeliShotMetadata = 3350745713, + camCinematicPedCloseUpCameraMetadata = 3732353935, + camCinematicPoliceExitVehicleShotMetadata = 3244599436, + camCinematicPoliceHeliMountedShotMetadata = 216191320, + camCinematicPoliceInCoverShotMetadata = 971556424, + camCinematicPoliceRoadBlockShotMetadata = 1663387456, + camCinematicPositionCameraMetadata = 3193773259, + camCinematicScriptContextMetadata = 866723283, + camCinematicScriptedMissionCreatorFailContextMetadata = 1368189925, + camCinematicScriptedRaceCheckPointContextMetadata = 4197977312, + camCinematicScriptRaceCheckPointShotMetadata = 1301482539, + camCinematicShots = 3403418927, + camCinematicSpectatorNewsChannelContextMetadata = 1655520052, + camCinematicStuntCameraMetadata = 3215612005, + camCinematicStuntJumpContextMetadata = 3436792018, + camCinematicStuntJumpShotMetadata = 3180375976, + camCinematicTrainPassengerShotMetadata = 1891076392, + camCinematicTrainRoofMountedShotMetadata = 1375436400, + camCinematicTrainStationShotMetadata = 4261417377, + camCinematicTrainTrackingCameraMetadata = 2537902390, + camCinematicTrainTrackShotMetadata = 2718877126, + camCinematicTwoShotCameraMetadata = 2296445362, + camCinematicVehicleBonnetShotMetadata = 3690068033, + camCinematicVehicleConvertibleRoofShotMetadata = 4253546052, + camCinematicVehicleGroupShotMetadata = 3216211679, + camCinematicVehicleLowOrbitCameraMetadata = 1680076183, + camCinematicVehicleLowOrbitShotMetadata = 357811358, + camCinematicVehicleOrbitCameraInitalSettings = 3064456407, + camCinematicVehicleOrbitCameraMetadata = 4218813220, + camCinematicVehicleOrbitShotMetadata = 723416050, + camCinematicVehiclePartShotMetadata = 2287426079, + camCinematicVehicleTrackingCameraMetadata = 2837215026, + camCinematicWaterCrashCameraMetadata = 1054960932, + camCinematicWaterCrashShotMetadata = 2640788941, + camCollisionMetadata = 201950034, + camCollisionMetadataBuoyancySettings = 3616131743, + camCollisionMetadataClippingAvoidance = 3777878985, + camCollisionMetadataOcclusionSweep = 1331207488, + camCollisionMetadataOrbitDistanceDamping = 2044384768, + camCollisionMetadataPathFinding = 937440555, + camCollisionMetadataPullBackTowardsCollision = 1759437459, + camCollisionMetadataPushBeyondEntitiesIfClipping = 1986022537, + camCollisionMetadataRotationTowardsLos = 1805808954, + camControlHelperMetadata = 2587719592, + camControlHelperMetadataLookAround = 565470605, + camControlHelperMetaDataPrecisionAimSettings = 3449554353, + camControlHelperMetadataViewModes = 3633454422, + camControlHelperMetadataViewModeSettings = 517960737, + camControlHelperMetadataZoom = 1487224137, + camCustomTimedSplineCameraMetadata = 4009398869, + camCutsceneDirectorMetadata = 3410125985, + camDebugDirectorMetadata = 3499963834, + camDepthOfFieldSettingsMetadata = 3604381381, + camEnvelopeMetadata = 2722791558, + Camera = 2997360705, + cameraPos = 2339743138, + camFirstPersonAimCameraMetadataHeadingCorrection = 1094369805, + camFirstPersonHeadTrackingAimCameraMetadata = 3079183712, + camFirstPersonPedAimCameraMetadata = 821570743, + camFirstPersonShooterCameraMetadata = 3837693093, + camFirstPersonShooterCameraMetadataCoverSettings = 2863258061, + camFirstPersonShooterCameraMetadataOrientationSpring = 4197661848, + camFirstPersonShooterCameraMetadataOrientationSpringLite = 1421319957, + camFirstPersonShooterCameraMetadataRelativeAttachOrientationSettings = 1064503511, + camFirstPersonShooterCameraMetadataSprintBreakOutSettings = 3371709132, + camFirstPersonShooterCameraMetadataStickyAim = 2799165301, + camFollowCameraMetadataFollowOrientationConing = 2364914607, + camFollowCameraMetadataHighAltitudeZoomSettings = 418469874, + camFollowCameraMetadataPullAroundSettings = 3437120378, + camFollowCameraMetadataRollSettings = 1774242875, + camFollowParachuteCameraMetadata = 736042439, + camFollowParachuteCameraMetadataCustomSettings = 1574447900, + camFollowPedCameraMetadata = 3759477553, + camFollowPedCameraMetadataAssistedMovementAlignment = 559130398, + camFollowPedCameraMetadataCustomViewModeSettings = 2553880007, + camFollowPedCameraMetadataDivingShakeSettings = 2182445161, + camFollowPedCameraMetadataHighFallShakeSettings = 2518615630, + camFollowPedCameraMetadataLadderAlignment = 947799964, + camFollowPedCameraMetadataOrbitPitchLimitsForOverheadCollision = 1431341429, + camFollowPedCameraMetadataPushBeyondNearbyVehiclesInRagdollSettings = 2530185515, + camFollowPedCameraMetadataRappellingAlignment = 1129712783, + camFollowPedCameraMetadataRunningShakeSettings = 2053748298, + camFollowPedCameraMetadataSwimmingShakeSettings = 4069495749, + camFollowVehicleCameraMetadata = 420909885, + camFollowVehicleCameraMetadataDuckUnderOverheadCollisionSettings = 4113023525, + camFollowVehicleCameraMetadataDuckUnderOverheadCollisionSettingsCapsuleSettings = 3720026770, + camFollowVehicleCameraMetadataHandBrakeSwingSettings = 2830469256, + camFollowVehicleCameraMetadataHighSpeedShakeSettings = 2477380333, + camFollowVehicleCameraMetadataHighSpeedZoomSettings = 2338842389, + camFollowVehicleCameraMetadataVerticalFlightModeSettings = 62698329, + camFollowVehicleCameraMetadataWaterEntryShakeSettings = 3274567537, + camFreeCameraMetadata = 569456131, + camGameplayDirectorMetadata = 1800753065, + camGameplayDirectorMetadataExplosionShakeSettings = 2835005341, + camGameplayDirectorMetadataVehicleCustomSettings = 3404668154, + camHintHelperMetadata = 939949516, + camHintHelperMetadataPivotPositionAdditive = 242159927, + camInconsistentBehaviourZoomHelperAirborneSettings = 3999425876, + camInconsistentBehaviourZoomHelperDetectFastCameraTurnSettings = 193557158, + camInconsistentBehaviourZoomHelperDetectSuddenMovementSettings = 2547763044, + camInconsistentBehaviourZoomHelperLosSettings = 2655036129, + camInconsistentBehaviourZoomHelperMetadata = 589272335, + camLongSwoopSwitchHelperMetadata = 3366863628, + camLookAheadHelperMetadata = 1630118580, + camLookAtDampingHelperMetadata = 2621748074, + camMarketingAToBCameraMetadata = 2461291580, + camMarketingDirectorMetadata = 1412464790, + camMarketingDirectorMetadataMode = 1136544428, + camMarketingFreeCameraMetadata = 1284661433, + camMarketingFreeCameraMetadataInputResponse = 624552429, + camMarketingMountedCameraMetadata = 925580290, + camMarketingOrbitCameraMetadata = 545216445, + camMarketingStickyCameraMetadata = 915237293, + camMetadataStore = 1634862667, + camMotionBlurSettingsMetadata = 2215393933, + camNearClipScannerMetadata = 2769283405, + camOscillatorMetadata = 1877334503, + camPreferredShotSelectionType = 2475841577, + camReplayBaseCameraMetadataCollisionSettings = 1965600814, + camReplayBaseCameraMetadataInputResponse = 3315215408, + camReplayDirectorMetadata = 3250236667, + camReplayFreeCameraMetadata = 3833530058, + camReplayPresetCameraMetadata = 3519845310, + camReplayRecordedCameraMetadata = 68919197, + camRoundedSplineCameraMetadata = 4144888485, + camScriptDirectorMetadata = 808165906, + camScriptedCameraMetadata = 2249792487, + camScriptedFlyCameraMetadata = 201638894, + camScriptedFlyCameraMetadataInputResponse = 2912311349, + camSeatSpecificCameras = 3206558883, + camShake = 2812731727, + camShakeMetadata = 2610893148, + camShakeMetadataFrameComponent = 1092637061, + camShakeName = 3155961353, + camShakeRollOffScaling = 1058165836, + camShortRotationSwitchHelperMetadata = 4216220206, + camShortTranslationSwitchHelperMetadata = 1635202674, + camShortZoomInOutSwitchHelperMetadata = 1845372544, + camShortZoomToHeadSwitchHelperMetadata = 3608544718, + camSmoothedSplineCameraMetadata = 2992118265, + camSpeedRelativeShakeSettingsMetadata = 3163469773, + camSpringMountMetadata = 545475055, + camSwitchCameraMetadata = 3778407244, + camSwitchDirectorMetadata = 1186645804, + camSyncedSceneDirectorMetadata = 3842242989, + camThirdPersonCameraMetadataBasePivotPosition = 2562557362, + camThirdPersonCameraMetadataBasePivotPositionRollSettings = 3378401281, + camThirdPersonCameraMetadataBuoyancySettings = 4280883922, + camThirdPersonCameraMetadataCollisionFallBackPosition = 2931931466, + camThirdPersonCameraMetadataCustomBoundingBoxSettings = 542523046, + camThirdPersonCameraMetadataLookOverSettings = 1204861982, + camThirdPersonCameraMetadataPivotOverBoungingBoxSettings = 70704803, + camThirdPersonCameraMetadataPivotPosition = 3548788069, + camThirdPersonCameraMetadataQuadrupedalHeightSpring = 2372917588, + camThirdPersonCameraMetadataStealthZoomSettings = 1308532518, + camThirdPersonCameraMetadataVehicleOnTopOfVehicleCollisionSettings = 1457190622, + camThirdPersonPedAimCameraMetadata = 1732613077, + camThirdPersonPedAimCameraMetadataLockOnOrbitDistanceSettings = 2689046040, + camThirdPersonPedAimCameraMetadataLockOnTargetDampingSettings = 810467818, + camThirdPersonPedAimInCoverCameraMetadata = 3583421172, + camThirdPersonPedAimInCoverCameraMetadataAimingSettings = 2711282760, + camThirdPersonPedAimInCoverCameraMetadataLowCoverSettings = 4274825405, + camThirdPersonPedAssistedAimCameraCinematicMomentSettings = 2799730898, + camThirdPersonPedAssistedAimCameraInCoverSettings = 2194812563, + camThirdPersonPedAssistedAimCameraLockOnAlignmentSettings = 2731233901, + camThirdPersonPedAssistedAimCameraMetadata = 4075428929, + camThirdPersonPedAssistedAimCameraPivotScalingSettings = 774378567, + camThirdPersonPedAssistedAimCameraPlayerFramingSettings = 1026402136, + camThirdPersonPedAssistedAimCameraRecoilShakeScalingSettings = 3357216290, + camThirdPersonPedAssistedAimCameraRunningShakeSettings = 1609808531, + camThirdPersonPedAssistedAimCameraShakeActivityScalingSettings = 3550987017, + camThirdPersonPedAssistedAimCameraShootingFocusSettings = 4025041103, + camThirdPersonPedMeleeAimCameraMetadata = 3247898661, + camThirdPersonVehicleAimCameraMetadata = 1836891244, + camTimedSplineCameraMetadata = 2703512219, + camVehicleCustomSettingsMetadata = 2297662625, + camVehicleCustomSettingsMetadataAdditionalBoundScalingVehicleSettings = 2484857206, + camVehicleCustomSettingsMetadataDoorAlignmentSettings = 690471002, + camVehicleCustomSettingsMetadataExitSeatPhaseForCameraExitSettings = 2756864235, + camVehicleCustomSettingsMetadataInvalidCinematcShotsRefsForVehicleSettings = 4239733162, + camVehicleCustomSettingsMetadataMultiplayerPassengerCameraHashSettings = 695621723, + camVehicleCustomSettingsMetadataSeatSpecficCameras = 1805758296, + CAnimSpeedUps__Tunables = 1899092416, + CanRideBikeWithNoHelmet = 2247732941, + CanSpawnInCar = 2174732092, + CantUse = 4039535360, + CapsuleHalfHeight = 2163883074, + CapsuleHalfWidth = 629093761, + CapsuleLen = 3235184882, + CapsuleRadius = 1996975203, + CapsuleZOffset = 1054694912, + CAR = 185025060, + CARCOLS_FILE = 869804114, + carModel = 3176005905, + CBaseArchetypeDef = 2195127427, + CBikeLeanAngleHelper__Tunables = 1450700199, + CCarGen = 1860713439, + CClipScalingHelper__Tunables = 3772901649, + CCombatTaskManager__Tunables = 1555503841, + CCreatureMetaData = 2042092773, + CCurve = 608533002, + CCurveSet = 2222014563, + CDataFileMgr__ContentsOfDataFileXml = 1736702710, + CDispatchAdvancedSpawnHelper__Tunables = 91788279, + CDispatchHelperSearchInAutomobile__Tunables = 587339511, + CDispatchHelperSearchInBoat__Tunables = 2880812777, + CDispatchHelperSearchInHeli__Tunables = 1963636404, + CDispatchHelperSearchOnFoot__Tunables = 2463141505, + CDispatchHelperVolumes__Tunables = 3789346099, + CDispatchSpawnHelper__Tunables = 487533277, + CDistantLODLight = 2033467892, + CDoorTuningFile = 2411310721, + CDynamicCoverHelper__Tunables = 3153023901, + centerAndRadius = 4089746177, + CEntityDef = 3461354627, + CEventAgitated__Tunables = 2874507431, + CEventCrimeCryForHelp__Tunables = 2970598878, + CEventEncroachingPed__Tunables = 30996625, + CEventExplosionHeard__Tunables = 2586882546, + CEventFootStepHeard__Tunables = 2570549492, + CEventGunAimedAt__Tunables = 1810003585, + CEventGunShot__Tunables = 2246785633, + CEventMeleeAction__Tunables = 2580170005, + CEventPedJackingMyVehicle__Tunables = 3230173079, + CEventPotentialBeWalkedInto__Tunables = 447216401, + CEventPotentialBlast__Tunables = 3804045499, + CEventPotentialGetRunOver__Tunables = 4074745581, + CEventRequestHelp__Tunables = 1097617571, + CEventRespondedToThreat__Tunables = 1657862556, + CEventShocking__Tunables = 2688422386, + CEventSuspiciousActivity__Tunables = 2370193555, + CExplosionInfoManager = 254220034, + CExtensionDefAudioCollisionSettings = 366926375, + CExtensionDefAudioEmitter = 637823035, + CExtensionDefBuoyancy = 749982947, + CExtensionDefDoor = 1965932561, + CExtensionDefExplosionEffect = 104349545, + CExtensionDefExpression = 3870521079, + CExtensionDefLadder = 2182960161, + CExtensionDefLightEffect = 663891011, + CExtensionDefLightShaft = 2718997053, + CExtensionDefParticleEffect = 975627745, + CExtensionDefProcObject = 2565191912, + CExtensionDefSpawnPoint = 3300062776, + CExtensionDefSpawnPointOverride = 2716862120, + CExtensionDefWindDisturbance = 569228403, + CFiringPatternInfo = 4139644871, + CGrabHelper__Tunables = 1898505781, + Chances = 3434267272, + changeSetName = 3618800523, + chassis = 3558367838, + CHDTxdAssetBinding = 1501994083, + childName = 204594422, + children = 240949893, + CLegIkSolver__Tunables = 841524051, + CLevelData = 75111904, + CLightAttrDef = 4115341947, + Clip = 547633373, + CLIP_SETS_FILE = 4136207125, + clipDictionaryMetadatas = 3037672124, + clipDictionaryName = 635311839, + ClipDictionaryName = 2571958159, + clipItems = 3294768058, + clips = 1731275751, + ClipSet = 230522063, + ClipSetId = 1769383946, + clipSets = 2366522350, + ClipSets = 2460310938, + CLODLight = 2276214072, + CLookAtHistory__Tunables = 4214737672, + CMapData = 3545841574, + CMapTypes = 3649811809, + CMiniMap__Tunables = 4077958042, + CMloArchetypeDef = 273704021, + CMloEntitySet = 3601308153, + CMloInstanceDef = 164374718, + CMloPortalDef = 2572186314, + CMloRoomDef = 186126833, + CMloTimeCycleModifier = 807246248, + CMultiTxdRelationship = 1261337422, + CNmMessage = 540147835, + CNmParameterBool = 3201838637, + CNmParameterFloat = 2458347956, + CNmParameterInt = 1429899100, + CNmParameterRandomFloat = 3855903374, + CNmParameterRandomInt = 213806608, + CNmParameterResetMessage = 3594683582, + CNmParameterString = 2290405727, + CNmParameterVector = 1886176625, + CNmTuningSet = 1903166467, + col = 2082703339, + collisionBone = 3234051813, + CollisionData = 3547055785, + CollisionRadius = 2961500813, + color = 3914595625, + Color = 1308845671, + colors = 140995175, + colour = 1541149667, + CombatInfo = 894792629, + Component = 3344490581, + components = 3094514372, + compositeEntityTypes = 1709823211, + CompRestrictions = 1292693219, + CONDITIONAL_ANIMS_FILE = 7003891, + CONTENT_UNLOCKING_META_FILE = 138872183, + contentChangeSets = 614695604, + contents = 780522884, + CONTENTS_ANIMATION = 1729429563, + CONTENTS_CUTSCENE = 1341504475, + CONTENTS_DLC_MAP_DATA = 2008833657, + CONTENTS_LODS = 129500478, + CONTENTS_MAP = 3584173080, + CONTENTS_PEDS = 2150818969, + CONTENTS_PROPS = 85688491, + CONTENTS_VEHICLES = 3204813008, + Context = 2518983606, + corners = 1329770163, + CPackFileMetaData = 2477165103, + CPedCompExpressionData = 3105947251, + CPedModelInfo__InitDataList = 3715594014, + CPedModelInfo__PersonalityDataList = 2428131759, + CPedPropExpressionData = 2871393870, + CPedTargetEvaluator__Tunables = 1616944729, + CPedTargetting__Tunables = 3572343040, + CPlayerCoverClipVariationHelper__Tunables = 3847977171, + CPlayerInfo__sPlayerStatInfo = 1168828738, + CPlayerInfo__sSprintControlData = 2225340824, + CPlayerInfo__Tunables = 3763924699, + CPlayerPedTargeting__Tunables = 1955283657, + CPoliceBoatDispatch__Tunables = 308678703, + CPrioritizedClipSetRequestManager__Tunables = 76934329, + CProceduralInfo = 4283490117, + CPtFxAssetDependencyInfo = 3936596588, + CPtFxAssetInfoMgr = 3599498566, + CRandomEventManager__Tunables = 3308217727, + CreatureMetadataName = 982286538, + CRelationshipManager__Tunables = 1682166943, + Crimes = 944438733, + CScenarioClipHelper__Tunables = 1707736265, + CScenarioPointGroup = 3383680063, + CScenarioPointManifest = 1425675487, + CScenarioPointRegionDef = 1251976652, + CShaderVariableComponent = 3881120539, + CSituationalClipSetStreamer__Tunables = 1395325338, + CTacticalAnalysis__Tunables = 1413047452, + CTacticalAnalysisCoverPoints__Tunables = 3043164413, + CTacticalAnalysisCoverPointSearch__Tunables = 2640991648, + CTacticalAnalysisNavMeshPoints__Tunables = 1220308217, + CTargettingDifficultyInfo = 1135093158, + CTaskAdvance__Tunables = 166066110, + CTaskAgitated__Tunables = 451717787, + CTaskAimAndThrowProjectile__Tunables = 920055786, + CTaskAimFromGround__Tunables = 1016413941, + CTaskAimGunBlindFire__Tunables = 3400346520, + CTaskAimGunFromCoverIntro__Tunables = 675160047, + CTaskAimGunFromCoverOutro__Tunables = 753314165, + CTaskAimGunOnFoot__Tunables = 71881945, + CTaskAimGunVehicleDriveBy__Tunables = 3042947166, + CTaskAmbientClips__Tunables = 1589125251, + CTaskAnimatedHitByExplosion__Tunables = 1117516593, + CTaskArrestPed__Tunables = 1399891452, + CTaskBoatChase__Tunables = 3798971738, + CTaskBoatCombat__Tunables = 2409668190, + CTaskBoatStrafe__Tunables = 3036495892, + CTaskCallPolice__Tunables = 2834037164, + CTaskCarReactToVehicleCollision__Tunables = 2728841566, + CTaskChat__Tunables = 52767132, + CTaskCloseVehicleDoorFromInside__Tunables = 3615161210, + CTaskCombat__Tunables = 1035504443, + CTaskCombatAdditionalTask__Tunables = 4286320209, + CTaskCombatFlank__Tunables = 3480084478, + CTaskComplexEvasiveStep__Tunables = 1335476290, + CTaskConfront__Tunables = 150142004, + CTaskConversationHelper__Tunables = 754470627, + CTaskCoupleScenario__Tunables = 44269074, + CTaskCover__Tunables = 3452806650, + CTaskCowerScenario__Tunables = 27789385, + CTaskDamageElectric__Tunables = 856265530, + CTaskDraggingToSafety__Tunables = 4043706236, + CTaskDyingDead__Tunables = 2675734391, + CTaskEnterCover__Tunables = 1433330874, + CTaskEnterVehicle__Tunables = 1027962175, + CTaskEnterVehicleAlign__Tunables = 1636991334, + CTaskEnterVehicleSeat__Tunables = 135393357, + CTaskExhaustedFlee__Tunables = 633079219, + CTaskExitCover__Tunables = 3296810549, + CTaskExitVehicle__Tunables = 4141614587, + CTaskExitVehicleSeat__Tunables = 4292350695, + CTaskFall__Tunables = 3858033844, + CTaskFishLocomotion__Tunables = 528773834, + CTaskFlyingWander__Tunables = 2593718369, + CTaskFlyToPoint__Tunables = 2856283273, + CTaskGetUp__Tunables = 1454643673, + CTaskGoToScenario__Tunables = 342235337, + CTaskGrowlAndFlee__Tunables = 3882342074, + CTaskGun__Tunables = 1283860553, + CTaskHeliChase__Tunables = 4167522072, + CTaskHeliCombat__Tunables = 1828825613, + CTaskHelicopterStrafe__Tunables = 3763664820, + CTaskHeliOrderResponse__Tunables = 162290274, + CTaskHeliPassengerRappel__Tunables = 3828979530, + CTaskHumanLocomotion__Tunables = 2920137037, + CTaskInCover__Tunables = 1340552235, + CTaskIntimidate__Tunables = 1888161203, + CTaskInVehicleBasic__Tunables = 3591430584, + CTaskInvestigate__Tunables = 2122351816, + CTaskJump__Tunables = 1477206380, + CTaskMeleeActionResult__Tunables = 1673636385, + CTaskMotionAiming__Tunables = 1860470777, + CTaskMotionBasicLocomotionLowLod__Tunables = 835509391, + CTaskMotionInAutomobile__Tunables = 175867186, + CTaskMotionInCover__Tunables = 1914830328, + CTaskMotionInTurret__Tunables = 2020941567, + CTaskMotionInVehicle__Tunables = 2450186166, + CTaskMotionOnBicycle__Tunables = 1415781118, + CTaskMotionOnBicycleController__Tunables = 1645332033, + CTaskMotionSwimming__Tunables = 1000070523, + CTaskMotionTennis__Tunables = 3629609639, + CTaskMoveCombatMounted__Tunables = 1568594793, + CTaskMoveCrossRoadAtTrafficLights__Tunables = 2381559732, + CTaskMoveFollowNavMesh__Tunables = 418889424, + CTaskMoveToTacticalPoint__Tunables = 2603381663, + CTaskMoveWithinAttackWindow__Tunables = 938139729, + CTaskNMBalance__Tunables = 4156771533, + CTaskNMBehaviour__Tunables = 1424285270, + CTaskNMBrace__Tunables = 959283411, + CTaskNMBuoyancy__Tunables = 2908480529, + CTaskNMControl__Tunables = 208512313, + CTaskNMDraggingToSafety__Tunables = 4274630537, + CTaskNMDrunk__Tunables = 1927528235, + CTaskNMElectrocute__Tunables = 1986788875, + CTaskNMExplosion__Tunables = 3668321041, + CTaskNMFlinch__Tunables = 1394958084, + CTaskNMHighFall__Tunables = 4010904374, + CTaskNMInjuredOnGround__Tunables = 3943948180, + CTaskNMJumpRollFromRoadVehicle__Tunables = 465597172, + CTaskNMOnFire__Tunables = 749058568, + CTaskNMPrototype__Tunables = 2697213281, + CTaskNMPrototype__Tunables__TimedTuning = 1783260611, + CTaskNMRiverRapids__Tunables = 2208098656, + CTaskNMShot__Tunables = 365558263, + CTaskNMSimple__Tunables = 1759871612, + CTaskNMThroughWindscreen__Tunables = 701095463, + CTaskOpenVehicleDoorFromOutside__Tunables = 4000867050, + CTaskParachute__Tunables = 330647109, + CTaskParachuteObject__Tunables = 533009545, + CTaskPlaneChase__Tunables = 3362905475, + CTaskPlayerDrive__Tunables = 2233320042, + CTaskPlayerOnFoot__Tunables = 2843912235, + CTaskPoliceOrderResponse__Tunables = 1572997428, + CTaskPursueCriminal__Tunables = 1017737308, + CTaskQuadLocomotion__Tunables = 3451166416, + CTaskRageRagdoll__Tunables = 4111703670, + CTaskRappel__Tunables = 583393603, + CTaskReactAimWeapon__Tunables = 3431679747, + CTaskReactAndFlee__Tunables = 1455936464, + CTaskReactInDirection__Tunables = 1160501277, + CTaskReactToBeingAskedToLeaveVehicle__Tunables = 2747883046, + CTaskReactToBuddyShot__Tunables = 3060185515, + CTaskReactToExplosion__Tunables = 1714101654, + CTaskReactToImminentExplosion__Tunables = 2053606685, + CTaskReactToPursuit__Tunables = 3823017031, + CTaskRideTrain__Tunables = 85139718, + CTaskScenarioFlee__Tunables = 4223438874, + CTaskSearch__Tunables = 2186129008, + CTaskSearchBase__Tunables = 1006486559, + CTaskSearchForUnknownThreat__Tunables = 3552809742, + CTaskSearchInAutomobile__Tunables = 3157865989, + CTaskSearchInBoat__Tunables = 3740707804, + CTaskSearchInHeli__Tunables = 2902745725, + CTaskSearchOnFoot__Tunables = 1589612569, + CTaskSharkAttack__Tunables = 2411903884, + CTaskSharkCircle__Tunables = 3798074522, + CTaskShockingEvent__Tunables = 2668698466, + CTaskShockingEventBackAway__Tunables = 1421095933, + CTaskShockingEventGoto__Tunables = 3634782675, + CTaskShockingEventHurryAway__Tunables = 3936521982, + CTaskShockingEventReact__Tunables = 1524084241, + CTaskShockingEventReactToAircraft__Tunables = 1470816321, + CTaskShockingEventStopAndStare__Tunables = 1473719990, + CTaskShockingEventWatch__Tunables = 4159743939, + CTaskShockingPoliceInvestigate__Tunables = 2727614619, + CTaskShootOutTire__Tunables = 3623406952, + CTaskShove__Tunables = 2315221829, + CTaskShoved__Tunables = 2184485071, + CTaskSmartFlee__Tunables = 2929340853, + CTaskStandGuard__Tunables = 928089637, + CTaskStealVehicle__Tunables = 3788906738, + CTaskSwapWeapon__Tunables = 756021342, + CTaskSwatOrderResponse__Tunables = 1687602234, + CTaskSwimmingWander__Tunables = 581692275, + CTaskTakeOffPedVariation__Tunables = 2581463145, + CTaskTargetUnreachable__Tunables = 1996880107, + CTaskTargetUnreachableInExterior__Tunables = 1858966752, + CTaskTargetUnreachableInInterior__Tunables = 2878804031, + CTaskTrainBase__Tunables = 2321692150, + CTaskTryToGrabVehicleDoor__Tunables = 2780911905, + CTaskUnalerted__Tunables = 3631212269, + CTaskUseScenario__Tunables = 4286728767, + CTaskUseVehicleScenario__Tunables = 1105517236, + CTaskVariedAimPose__Tunables = 572125765, + CTaskVault__Tunables = 4107041159, + CTaskVehicleApproach__Tunables = 3998182611, + CTaskVehicleBlock__Tunables = 946218496, + CTaskVehicleBlockBackAndForth__Tunables = 3195863117, + CTaskVehicleBlockBrakeInFront__Tunables = 1783020311, + CTaskVehicleBlockCruiseInFront__Tunables = 2600077603, + CTaskVehicleChase__Tunables = 1182936554, + CTaskVehicleCombat__Tunables = 1479019922, + CTaskVehicleCrash__Tunables = 3962616343, + CTaskVehicleCruiseBoat__Tunables = 3100673805, + CTaskVehicleDeadDriver__Tunables = 2144691340, + CTaskVehicleFlee__Tunables = 195975428, + CTaskVehicleFleeBoat__Tunables = 1082281615, + CTaskVehicleFSM__Tunables = 2154756726, + CTaskVehicleGoToBoat__Tunables = 1874670628, + CTaskVehicleGoToHelicopter__Tunables = 505312818, + CTaskVehicleGoToPlane__Tunables = 2216414081, + CTaskVehicleGoToPointWithAvoidanceAutomobile__Tunables = 305265911, + CTaskVehicleLandPlane__Tunables = 2468823445, + CTaskVehicleMissionBase__Tunables = 3839812632, + CTaskVehicleParkNew__Tunables = 1266857276, + CTaskVehiclePersuit__Tunables = 424095714, + CTaskVehiclePlaneChase__Tunables = 2639568629, + CTaskVehiclePullAlongside__Tunables = 3971388892, + CTaskVehiclePursue__Tunables = 1465682442, + CTaskVehicleRam__Tunables = 4205884753, + CTaskVehicleShotTire__Tunables = 4029377803, + CTaskVehicleSpinOut__Tunables = 1106913269, + CTaskWalkAway__Tunables = 206304570, + CTaskWander__Tunables = 3543621225, + CTaskWanderInArea__Tunables = 711403403, + CTaskWanderingScenario__Tunables = 4183061553, + CTaskWitness__Tunables = 1436906951, + CTimeArchetypeDef = 1991296364, + CTimeCycleModifier = 1733268304, + CustomTriggerBox = 2579426011, + CVehicleClipRequestHelper__Tunables = 2857018690, + CVehicleModelInfoVarGlobal = 3184659407, + CVehicleModelInfoVariation = 746362187, + CVehicleScenarioManager__AttractorTuning__Tunables = 1138425769, + CVfxVehicleInfo = 2566559812, + CVfxVehicleInfoMgr = 13081091, + CWanted__Tunables = 2938521871, + CWantedHelicopterDispatch__Tunables = 3681116455, + CWildlifeManager__Tunables = 3899878125, + damageAtCentre = 626304432, + damageAtEdge = 1456455832, + dataFiles = 4164602339, + DECALS_FILE = 721270417, + decayFactor = 2187394038, + DecisionMakerName = 71722552, + Default = 1012917042, + DefaultBrawlingStyle = 665939989, + DefaultGestureClipSet = 289586118, + DefaultRemoveRangeMultiplier = 2267082285, + DefaultSpawningPreference = 3497281775, + DefaultTaskDataSetName = 2977281996, + DefaultUnarmedWeapon = 2801601573, + DefaultVisemeClipSet = 3269491505, + DelayDoorClosingForPlayer = 2356415658, + Density = 1026783212, + DensityRange = 4153067752, + directedLifeTime = 2075377911, + directedWidth = 932713096, + direction = 887068712, + Direction = 2690021765, + disableBonnetCamera = 1563940027, + disabled = 2572083169, + Disabled = 295298378, + disabledFiles = 3110537950, + Dispatch = 3591134869, + Distance = 1974652584, + DistanceRange = 1987085678, + DISTANT_LIGHTS_FILE = 983558349, + DISTANT_LIGHTS_HD_FILE = 2925996279, + distBetweenCoronas = 1962520137, + distBetweenCoronas_far = 232750087, + DLC_ITYP_REQUEST = 4114167230, + DLC_SCRIPT_METAFILE = 259967989, + DLC_WEAPON_PICKUPS = 3168769355, + dlcName = 2337697442, + DontCloseWhenTouched = 1465449817, + door_dside_f = 1744947660, + door_dside_r = 3782851822, + door_pside_f = 2553297679, + door_pside_r = 1096977781, + DOOR_TUNING_FILE = 57918953, + drawableDictionary = 4229936891, + DrawableId = 1166348048, + DrawableIndex = 1740452767, + DSP_NORMAL = 1082005734, + duration = 3674968789, + Duration = 2193831214, + Edges = 1456031062, + effectsData = 3285521232, + emmissiveBoost = 1697573984, + EMPTY = 2749884260, + Enable = 421699355, + enabled = 1527945487, + Enabled = 1989893331, + EnabledByDefault = 3921215899, + end = 2965669335, + End = 443072552, + endHour = 380604338, + EndModel = 3041118144, + endPhase = 1600588195, + endRadius = 306326438, + enforceLsnSorting = 3949387622, + engineblock = 2036489924, + engineDamagePtFxEnabled = 2314702693, + engineDamagePtFxHasPanel = 811799967, + engineDamagePtFxHasRotorEvo = 935734665, + engineDamagePtFxNoPanelName = 2142304406, + engineDamagePtFxPanelOpenName = 2589870806, + engineDamagePtFxPanelShutName = 2754603386, + engineDamagePtFxRange = 1633907331, + engineDamagePtFxSpeedEvoMax = 4116298751, + engineDamagePtFxSpeedEvoMin = 1190778122, + engineStartupPtFxEnabled = 2837195620, + engineStartupPtFxName = 2081216567, + engineStartupPtFxRange = 3534688011, + entities = 3433796359, + ENTITYFX_FILE = 209619560, + EventType = 2248400140, + exclusions = 1912839368, + executionConditions = 312713139, + exhaust = 2148626005, + exhaust_2 = 3047243728, + exhaust_3 = 4276408918, + exhaust_4 = 286750395, + exhaustPtFxCutOffSpeed = 1411922576, + exhaustPtFxEnabled = 3040982233, + exhaustPtFxName = 2262693655, + exhaustPtFxRange = 3636073, + exhaustPtFxScale = 4006380515, + exhaustPtFxSpeedEvoMax = 1132138093, + exhaustPtFxSpeedEvoMin = 2787040150, + exhaustPtFxTempEvoMax = 2189200497, + exhaustPtFxTempEvoMin = 2162145396, + exhaustPtFxThrottleEvoOnGearChange = 1254006862, + explodeAttachEntityWhenFinished = 2712903420, + Explosion = 3638218222, + EXPLOSION_INFO_FILE = 1307223293, + EXPLOSIONFX_FILE = 2522650906, + ExpressionDictionaryName = 1760551351, + expressionName = 1573835099, + ExpressionName = 3005293958, + ExpressionSetName = 2352891724, + extendedRange = 3534580187, + extensions = 4051599144, + ExternallyDrivenDOFs = 4106672091, + extra_1 = 3819846466, + extra_2 = 3050790801, + extra_3 = 2297431491, + extra_4 = 2590320813, + extra_5 = 2830583129, + EXTRA_FOLDER_MOUNT_DATA = 374419551, + EXTRA_TITLE_UPDATE_DATA = 2227896657, + FacialClipsetGroupName = 1843847949, + fallbackId = 3378470045, + Falling = 4171606781, + falloff = 3429369576, + falloffExponent = 733168314, + falloffMax = 2603992812, + Female = 107208361, + FFrontOffset = 2475984948, + Fight = 2236152585, + filename = 1087019066, + filesToDisable = 3328021166, + filesToEnable = 2417471446, + filesToInvalidate = 3805669424, + fileType = 345145806, + FIREFX_FILE = 1731707109, + FirstPersonDriveByIKOffset = 1272308759, + flags = 1741842546, + Flags = 1264718594, + flash = 2239439183, + Flee = 1684954205, + forceFactor = 3761213775, + Forward = 4076313930, + Fov = 3926516228, + fragDamage = 2676323813, + fRagdollForceModifier = 1451234527, + frontIndicatorCorona = 3430197797, + fSelfForceModifier = 3267483248, + FullBodyDamageClipSet = 4228310587, + FUpOffset = 4137555685, + fwClipItem = 4225016529, + fwClipItemWithProps = 615994212, + fwClipSet = 3765269019, + fwClipSetManager = 4032904779, + fxName = 1920790105, + fxOffsetPos = 3676475576, + fxOffsetRot = 1710928362, + fxType = 529104057, + GetupSetHash = 1726861708, + GroundColor = 860002656, + group = 3391120809, + Group = 1713610519, + Groups = 2500839488, + GTXD_PARENTING_DATA = 2798946644, + guid = 2591780461, + HANDLING_FILE = 46800217, + hash = 1048674328, + HDDist = 4257505727, + HDTxd = 1692217392, + HDTxdBindingArray = 4153080611, + Heading = 3903571810, + HeadingLimits = 2310315578, + headLight = 1105987835, + headlight_l = 2403350912, + headlight_r = 3886869072, + headLightCorona = 1649539989, + Height = 4052201683, + HIGH_HEELS = 2100709655, + highPri = 1331010150, + HoldDuration = 2367844690, + hub_lf = 3891344909, + hub_rf = 2300894090, + iCosZ = 3735431522, + id = 459292749, + Id = 3809113010, + identifier = 4004242505, + Idle = 923499413, + IdleTransitionBlendOutTime = 61709549, + IdleTransitions = 1687702635, + ids = 4038920459, + IgnoreMaxInRange = 3250311224, + IgnoreOpenDoorTaskEdgeLerp = 975984281, + IgnorePavementChecks = 1501464625, + imapDependencies = 735712319, + imapDependencies_2 = 3712769228, + imapName = 833569695, + IN_VEHICLE = 1015874207, + includedDataFiles = 2354614069, + includedXmlFiles = 3280956850, + Index = 1035793140, + indicator = 801150652, + indicator_lf = 3403024362, + indicator_rf = 2051585809, + indices = 3921649453, + Infos = 802810900, + InitDatas = 1512338287, + initSpeed = 3640438618, + InjuredStrafeClipSet = 1464530836, + innerConeAngle = 1245835442, + installPartition = 3475002187, + intensity = 4023228733, + Intensity = 140854398, + intensity_far = 3542645631, + IntensityVar = 2813237244, + interior = 560567274, + INTERIOR_PROXY_ORDER_FILE = 821873185, + InteriorNames = 2406565252, + Interiors = 947288719, + IPL_FILE = 2251386970, + iRadius = 1998996693, + IsHeadBlendPed = 591520311, + iSinZ = 1351095745, + IsStreamedGfx = 3353096503, + Item = 104834034, + itypDependencies_2 = 3529579673, + iType = 3252237582, + JUNCTION_TEMPLATES_FILE = 1075369871, + JUNCTION_TEMPLATES_PSO_FILE = 1684997832, + kBoth = 1849703770, + Key = 1620616462, + KilledPerceptionRangeModifer = 2618596152, + kitName = 1513897539, + kits = 1843360923, + Kits = 1497090499, + kitType = 3008983707, + leakPtFxEnabled = 1064432315, + leakPtFxOilName = 729665807, + leakPtFxPetrolName = 3533268990, + leakPtFxRange = 2910098562, + leakPtFxSpeedEvoMax = 1705315422, + leakPtFxSpeedEvoMin = 2575887885, + length = 2508072249, + LifeTime = 4209357938, + Lights = 2854514190, + lightSettings = 2377329928, + limitAngle = 2100360280, + linkedModels = 3815104759, + linkMods = 769154353, + LIQUIDFX_FILE = 1699106320, + liveries = 2791605300, + livery = 2153615120, + liveryNames = 1704397081, + loadCompletely = 713423689, + LoadOut = 4277349827, + LOADOUTS_FILE = 808720620, + locations = 3724288529, + locked = 2448219441, + lodDist = 3212107687, + lodLevel = 1821316885, + LODTYPES_DEPTH_HD = 3259521980, + LODTYPES_DEPTH_LOD = 2384644182, + LODTYPES_DEPTH_SLOD1 = 2554074988, + LODTYPES_DEPTH_SLOD2 = 315427988, + LODTYPES_DEPTH_SLOD3 = 2164549889, + LODTYPES_DEPTH_SLOD4 = 1868383667, + LODTYPES_DEPTH_ORPHANHD = 2106806081, + mapChangeSetData = 815157305, + MapDataGroups = 3039604259, + MAPZONES_FILE = 2154214988, + maskID = 2432235300, + MassMultiplier = 1613940114, + MATERIALFX_FILE = 905909785, + max = 1616931012, + Max = 344563784, + MaxDistance = 2770481267, + MaxPassengersInCar = 1694835331, + MaxScale = 4214801493, + MaxScaleZ = 1351348251, + MaxSpeed = 3972966657, + MaxTime = 786767296, + MaxTintPalette = 3492298933, + MaxXRotation = 658255980, + MaxYRotation = 2609605325, + MaxZOffset = 1569839200, + MaxZRotation = 3093288384, + memoryGroup = 1079355696, + MicroMovementsFreqH = 215094271, + MicroMovementsFreqV = 1945002622, + MicroMovementsScaleH = 2532792329, + MicroMovementsScaleV = 2313960935, + min = 4264617715, + Min = 3358645132, + MinActivationImpulse = 1033747207, + MinDistance = 1316787168, + minorExplosion = 3090421228, + MinScale = 2118753352, + MinScaleZ = 572504281, + MinTime = 614798748, + MinTintPalette = 2179154468, + MinXRotation = 3795236509, + MinYRotation = 2447817968, + MinZOffset = 1998724326, + MinZRotation = 2511320236, + mirrorTexture = 1892759569, + misc_a = 2172915033, + misc_b = 2948983260, + misc_c = 3705750550, + misc_d = 2334728355, + misc_e = 3629890315, + misc_f = 4003129225, + misc_g = 867496380, + misc_h = 702996000, + misc_i = 2672412968, + misc_j = 2246219354, + misc_k = 986218535, + misc_l = 1360178363, + misc_m = 4199644986, + misc_n = 3363543951, + misc_o = 2517907133, + misc_p = 3821556264, + misc_q = 101324459, + misc_r = 332902982, + misc_s = 3515428266, + misc_t = 526666079, + misc_u = 1020363837, + misc_v = 1257971856, + misc_w = 1686098841, + misc_x = 2041970181, + misc_y = 1413133063, + misc_z = 2850643555, + misfirePtFxEnabled = 2760245605, + misfirePtFxName = 4265177602, + misfirePtFxRange = 3937313011, + MKT_SPECIAL = 2316627489, + MKT_SPORT = 3608585597, + MKT_STANDARD = 315733923, + MKT_SUV = 2385734984, + mod_col_1 = 1338030889, + mod_col_2 = 2758960267, + mod_col_3 = 1785032818, + mod_col_4 = 1092558310, + mod_col_5 = 119450078, + ModelId = 2410101093, + modelName = 194221603, + ModelName = 4216861609, + ModelSet = 1518141539, + ModelToTuneMapping = 1001913906, + modifier = 1699237703, + modShopLabel = 4132169566, + MotionTaskDataSetName = 1092878940, + Move = 528166787, + MOVE_NETWORK_DEFS = 4182086555, + MoveBlendRatio = 778269991, + MovementClipSet = 3248325447, + MovementClipSetId = 549835433, + MovementModes = 2739474645, + MovementModeUnholsterData = 523961350, + MovementToStrafeClipSet = 4177809469, + moveNetworkFlags = 4273852377, + MP_STATS_DISPLAY_LIST_FILE = 759160086, + MP_STATS_UI_LIST_FILE = 2486889377, + mtlBangPtFxVehicleEvo = 1188575673, + mtlBangPtFxVehicleScale = 2772539357, + mtlScrapePtFxVehicleEvo = 1379406366, + mtlScrapePtFxVehicleScale = 3990432188, + multiples = 1309656778, + multiTxdRelationships = 3649984070, + MustUse = 331851963, + name = 3873537812, + Name = 2901156542, + NamedTuningArray = 2148169260, + NavCapabilitiesName = 3282019215, + NAVMESH_INDEXREMAPPING_FILE = 1431019085, + NAVNODE_INDEXREMAPPING_FILE = 2576484635, + networkPedModifier = 2824520073, + networkPlayerModifier = 3578474195, + Nodes = 804169170, + none = 493038497, + None = 1640121937, + normal = 1330140418, + Normal = 3599348095, + NormalMapName = 2845714814, + NUM_ANCHORS = 665640573, + numCoronas = 2225470999, + OBJ_COVER_TUNING_FILE = 628815953, + offset = 2705095151, + offsetPosition = 3633645315, + offsetRotation = 1389511464, + ON_FOOT = 2976953365, + opacity = 3644411688, + outerConeAngle = 4179134239, + overlay = 943450718, + OVERLAY_INFO_FILE = 3489350694, + overturnedSmokePtFxAngleThresh = 2735995463, + overturnedSmokePtFxEnabled = 1633606873, + overturnedSmokePtFxEngineHealthThresh = 132281413, + overturnedSmokePtFxName = 1978623397, + overturnedSmokePtFxRange = 1730945222, + overturnedSmokePtFxSpeedThresh = 2304473042, + owner = 2349203824, + OwnerName = 1481791743, + Pad = 1592782806, + parent = 2845591121, + parentIndex = 3633459645, + parentName = 2521104825, + PARTITION_0 = 1376468858, + PARTITION_1 = 2621625320, + PARTITION_2 = 2912515733, + patchFiles = 3524138408, + PATH_ZONES_FILE = 884764256, + PED_DAMAGE_APPEND_FILE = 3868325674, + PED_FIRST_PERSON_ALTERNATE_DATA = 143306029, + PED_FIRST_PERSON_ASSET_DATA = 348738744, + PED_METADATA_FILE = 3698391097, + PED_OVERLAY_FILE = 1407571174, + PED_PERSONALITY_FILE = 469479865, + PedCapsuleName = 3605846536, + pedCompExpressionIndex = 656720598, + pedCompExpressions = 4168161021, + pedcompID = 3512253528, + pedCompID = 3337196122, + PedComponentClothName = 2679581144, + PedComponentSetName = 3295015867, + pedCompVarIndex = 2890646891, + PedIKSettingsName = 851100275, + PedLayoutName = 704782517, + PedPersonalities = 2345512339, + pedPropExpressionIndex = 3269764788, + pedPropExpressions = 1538058350, + pedPropID = 1389713939, + pedPropVarIndex = 461768873, + Peds = 4047618778, + PedScale = 3537940146, + PEDSTREAM_FILE = 1358252642, + pedType = 2747160189, + Pedtype = 3052355362, + PedVoiceGroup = 1999554162, + percentage = 2947557653, + PerceptionInfo = 3174726878, + PERMANENT_ITYP_FILE = 2437884080, + persistent = 4183121383, + Personality = 620072928, + petrolTankFirePtFxName = 2162940361, + petrolTankFirePtFxRadius = 2461827139, + petrolTankFirePtFxRange = 165484253, + petrolTankFirePtFxSpeedEvoMax = 2172227529, + petrolTankFirePtFxSpeedEvoMin = 1276446821, + Pistol = 805949221, + Pitch = 4037952930, + PitchChangeRate = 1754758744, + PitchLimits = 1158567006, + PitchOffset = 3015997841, + PLANE = 2676158011, + planeAfterburnerPtFxEnabled = 3213641538, + planeAfterburnerPtFxName = 446218229, + planeAfterburnerPtFxRange = 408793866, + planeAfterburnerPtFxScale = 2145730461, + planeDamageFirePtFxEnabled = 3414165598, + planeDamageFirePtFxName = 1338161444, + planeDamageFirePtFxRange = 2839206294, + planeDamageFirePtFxSpeedEvoMax = 571971263, + planeDamageFirePtFxSpeedEvoMin = 1883098650, + planeGroundDisturbPtFxDist = 4253009632, + planeGroundDisturbPtFxEnabled = 3844975759, + planeGroundDisturbPtFxNameDefault = 648304806, + planeGroundDisturbPtFxNameDirt = 1349328259, + planeGroundDisturbPtFxNameFoliage = 3426743478, + planeGroundDisturbPtFxNameSand = 3528449028, + planeGroundDisturbPtFxNameWater = 253287460, + planeGroundDisturbPtFxRange = 2117069571, + planeGroundDisturbPtFxSpeedEvoMax = 1904205977, + planeGroundDisturbPtFxSpeedEvoMin = 3750053303, + planeWingTipPtFxEnabled = 630564551, + planeWingTipPtFxName = 1116747820, + planeWingTipPtFxRange = 2911605361, + planeWingTipPtFxSpeedEvoMax = 1891037280, + planeWingTipPtFxSpeedEvoMin = 432519559, + plantInfos = 1195126367, + PlantTag = 1119170566, + plateProbabilities = 759151167, + Player = 2751443189, + POPGRP_FILE = 2708681290, + POPSCHED_FILE = 3496245090, + PoseMatcherName = 407450340, + PoseMatcherProneName = 1468409568, + position = 18243940, + Position = 210930065, + PositionOffset = 3553152178, + posn = 967189988, + PovCameraOffset = 3390378580, + PreciseUseTime = 196435285, + priority = 342945216, + Priority = 2673351645, + Probabilities = 4251991726, + probability = 3698534260, + PROC_META_FILE = 3342716104, + PROCOBJ_ALIGN_OBJ = 2620161998, + PROCOBJ_CAST_SHADOW = 1528296021, + PROCOBJ_FILE = 1526130529, + PROCOBJ_IS_FLOATING = 3217678483, + PROCOBJ_NETWORK_GAME = 390676221, + PROCOBJ_USE_SEED = 2229775436, + procObjInfos = 4262901725, + PROCPLANT_CAMERADONOTCULL = 1147935867, + PROCPLANT_FURGRASS = 3729666926, + PROCPLANT_GROUNDSCALE1VERT = 389823981, + PROCPLANT_LOD0 = 1994951555, + PROCPLANT_LOD1 = 4009819058, + PROCPLANT_LOD2 = 72099408, + PROCPLANT_NOGROUNDSKEW_LOD0 = 398505754, + PROCPLANT_NOGROUNDSKEW_LOD1 = 3381598904, + PROCPLANT_NOGROUNDSKEW_LOD2 = 885125404, + PROCPLANT_NOSHADOW = 696619156, + PROCPLANT_UNDERWATER = 882615863, + procTagTable = 2377507684, + PropRestrictions = 465162194, + props = 2287400538, + PropsName = 1179225812, + ptfxAssetDependencyInfos = 493695515, + PTFXASSETINFO_FILE = 1772520447, + ptFxHasTint = 3576542357, + ptFxIsTriggered = 3434402314, + ptFxName = 1203215085, + ptFxProbability = 3448174308, + ptFxScale = 1567144545, + ptFxSize = 1080281337, + ptFxSpeedEvoMax = 320256667, + ptFxSpeedEvoMin = 3884276349, + ptFxTag = 2524903540, + ptFxTintB = 2225110962, + ptFxTintG = 23853287, + ptFxTintR = 1304072655, + pull = 350772507, + pullCoronaIn = 538460876, + PV_COMP_INVALID = 476847607, + PV_COMP_ACCS = 3760011790, + PV_COMP_BERD = 696691459, + PV_COMP_DECL = 3631275576, + PV_COMP_FEET = 2300506577, + PV_COMP_HAIR = 2918472950, + PV_COMP_HAND = 2793296290, + PV_COMP_HEAD = 1159394596, + PV_COMP_JBIB = 2376289126, + PV_COMP_LOWR = 3254995156, + PV_COMP_MAX = 920969818, + PV_COMP_TASK = 1051671594, + PV_COMP_TEEF = 1520752005, + PV_COMP_UPPR = 3707586858, + RADIO_GENRE_CLASSIC_ROCK = 567874491, + RADIO_GENRE_JAZZ = 3210576665, + RADIO_GENRE_MEXICAN = 4058039902, + RADIO_GENRE_MODERN_ROCK = 4200371511, + RADIO_GENRE_MOTOWN = 1526192047, + RADIO_GENRE_OFF = 3820886398, + RADIO_GENRE_PUNK = 2352668725, + RADIO_GENRE_REGGAE = 2059985335, + RADIO_GENRE_RIGHT_WING_TALK = 1758684295, + RADIO_GENRE_SURF = 2495475670, + Radio1 = 3430266395, + Radio2 = 3132297878, + radius = 1337695475, + Radius = 3144350114, + RadiusScale = 3245550474, + rage__fwInstancedMapData = 4048164286, + rage__phVerletClothCustomBounds = 847348117, + rage__spdGrid2D = 2599150383, + range = 332484516, + Rate = 2986741774, + rear = 2243100542, + rearIndicatorCorona = 103408473, + RegionDefs = 3713107563, + RelationshipGroup = 4150596315, + requiredImap = 2090738474, + requiresLoadingScreen = 3135083525, + ResetNoCollisionOnCleanUp = 3362749677, + residentAnims = 2052114030, + residentResources = 82002169, + residentTxd = 1079754329, + Restriction = 26114980, + reversingLight = 242592930, + reversingLightCorona = 3960865135, + RFrontOffset = 1353482245, + RGBI = 194542898, + Rifle = 3187352598, + rimRadius = 1671388815, + Roll = 2579823494, + rooms = 3441481640, + rotate = 3903098393, + rotation = 2010988560, + Rotation = 2371198895, + RotationLimitAngle = 648763416, + RPF_FILE = 81740897, + RPF_FILE_PRE_INSTALL = 31119764, + RumbleDuration = 79170607, + RUpOffset = 3943427752, + SAT_NONE = 836773056, + scale = 1342385372, + Scale = 1018839014, + SCALEFORM_DLC_FILE = 258049916, + ScaleRange = 2691059430, + ScaleRangeXYZ = 4267248400, + ScaleRangeZ = 2934008023, + ScaleVariationXY = 754964759, + ScaleVariationZ = 2602640464, + ScaleXY = 3128382556, + ScaleZ = 712150328, + SCENARIO_INFO_FILE = 2244432863, + SCENARIO_POINTS_PSO_FILE = 1653171061, + SCENARIO_POP_STREAMING_NORMAL = 79175210, + ScenarioPoints = 3966518334, + ScenarioPopStreamingSlot = 3440415111, + ScenarioType = 191322199, + SCRIPTFX_FILE = 3176550718, + SeatIndex = 2604655109, + Seats = 368310011, + sets = 4021164785, + Sets = 778639775, + settings = 2768156407, + Settings = 1654011315, + Sexiness = 867165133, + SF_HOT_PERSON = 3612284555, + SF_JEER_AT_HOT_PED = 213733388, + shaderVariableComponents = 3687287113, + shaderVariableHashString = 490746723, + shadowBlur = 3672716153, + shockingEventAudioRangeOverride = 345540543, + shockingEventVisualRangeOverride = 2220221975, + SHOP_PED_APPAREL_META_FILE = 4189023929, + shortRange = 178074428, + ShouldLatchShut = 1101824832, + SidestepClipSet = 1255368790, + sirenSettings = 2230033165, + Situations = 2546696905, + size = 3226656423, + size_far = 388176731, + sLevelData = 4248020339, + SLOD_HUMAN = 2092589681, + slot = 933689839, + slotNames = 2198312216, + SLOWNESS_ZONES_FILE = 819490736, + Sniper = 3200555378, + SP_Low = 1535176458, + SP_Medium = 1318432000, + SP_MULTIPLAYER_RESIDENT = 330835765, + SP_SINGLEPLAYER_RESIDENT = 2843514243, + SP_STATS_DISPLAY_LIST_FILE = 957687860, + SP_STATS_UI_LIST_FILE = 3848387179, + SP_STREAMING = 1647646833, + spacing = 370899326, + Spacing = 1644991037, + spawnType = 4261247615, + specialAttribute = 1813324772, + speed = 4187447851, + sphere = 953812642, + Spheres = 3873229047, + splashInPtFxEnabled = 2568271272, + splashInPtFxName = 1671048614, + splashInPtFxRange = 424335064, + splashInPtFxSizeEvoMax = 2546557251, + splashInPtFxSpeedDownwardEvoMax = 2719708920, + splashInPtFxSpeedDownwardEvoMin = 1110754284, + splashInPtFxSpeedDownwardThresh = 2861864958, + splashInPtFxSpeedLateralEvoMax = 717627197, + splashInPtFxSpeedLateralEvoMin = 1180941296, + splashOutPtFxEnabled = 265145855, + splashOutPtFxName = 2228265562, + splashOutPtFxRange = 2084717992, + splashOutPtFxSizeEvoMax = 2926629502, + splashOutPtFxSpeedLateralEvoMax = 4269956697, + splashOutPtFxSpeedLateralEvoMin = 976640088, + splashOutPtFxSpeedUpwardEvoMax = 2874671957, + splashOutPtFxSpeedUpwardEvoMin = 340254431, + splashTrailPtFxEnabled = 1540336092, + splashTrailPtFxName = 3437892535, + splashTrailPtFxRange = 496141127, + splashTrailPtFxSizeEvoMax = 2112168390, + splashTrailPtFxSpeedEvoMax = 1320429615, + splashTrailPtFxSpeedEvoMin = 465674370, + splashWadePtFxEnabled = 3946923366, + splashWadePtFxName = 573019250, + splashWadePtFxRange = 2801117501, + splashWadePtFxSizeEvoMax = 230363215, + splashWadePtFxSpeedRiverEvoMax = 3237227592, + splashWadePtFxSpeedRiverEvoMin = 1052618905, + splashWadePtFxSpeedVehicleEvoMax = 1036775998, + splashWadePtFxSpeedVehicleEvoMin = 1176468081, + sStatsMetadataTuning = 3459433883, + StaggerFall = 2002487478, + Standard = 2352402326, + start = 2229020447, + Start = 3073138309, + startHour = 625204231, + StartModel = 226559569, + startPhase = 3221846423, + StationaryReactions = 2620629637, + statMods = 216311195, + STATS_METADATA_PSO_FILE = 1289107292, + StdDoorOpenBothDir = 1469697918, + StdDoorOpenNegDir = 2656051665, + StdDoorRotDir = 1083750337, + steeringwheel = 1325046900, + Stiffness = 294387850, + StillToSitPedalGearApproachRate = 2386385168, + StrafeClipSet = 1514292895, + STREAMING_REQUEST_LISTS_FILE = 2865461394, + streamingPolicy = 827725946, + streamingPriority = 3660169125, + STREET_VEHICLE_ASSOCIATION_FILE = 3243535945, + strength = 4280043047, + Stubble = 2766015245, + SuperlodType = 868617040, + Tag = 2215212623, + tailLight = 1210163367, + tailLightCorona = 4104001094, + tailLightMiddleCorona = 3579298804, + tangent = 2389642153, + Target = 3866136337, + targetAsset = 662555360, + TargetingThreatModifier = 41162556, + TargetOffset = 2175492938, + TargetRadius = 1146856098, + TaskDataName = 653610287, + TATTOO_SHOP_DLC_FILE = 1223910633, + TB_WARM = 1158270414, + TechSavvy = 248494816, + Teeter = 3508388318, + template = 3202639186, + texId = 1785432003, + TEXTFILE_METAFILE = 1142425891, + textureDictionary = 1976702369, + TextureId = 3617584144, + textureName = 440050042, + ThermalBehaviour = 3253990041, + time = 258444835, + TIME_FILE = 1428695449, + TIMECYCLE_FILE = 755616351, + TIMECYCLEMOD_FILE = 2793750187, + timeCycleModifiers = 2946251737, + timeTillPedLeaves = 213640539, + top = 1281216666, + TorqueAngularVelocityLimit = 3539021765, + tracks = 794089857, + TRAILER = 4229025179, + TRAINCONFIGS_FILE = 751887759, + TRAINTRACK_FILE = 680882864, + TriggerBoxMinMax = 2642293346, + TS_LOW = 4290350623, + Tunables = 508571515, + Tuning = 2317966594, + TuningName = 2921576840, + Turn = 3647068299, + turnOffBones = 3764022105, + turnOffExtra = 2892421376, + txdRelationships = 110813075, + txdToLoad = 465628444, + txdToUnload = 2372422677, + type = 828747869, + types = 138573281, + UnholsterClipData = 1235872865, + UnholsterClips = 3511043731, + UnholsterClipSetId = 3278048392, + unregisterResources = 910312539, + Update = 575805931, + UpperBodyFeatheredLeanEnabled = 2028170470, + UpperBodyShadowExpressionEnabled = 1264317859, + UseAutoOpenTriggerBox = 4151971060, + UseLeftHandIk = 1829639529, + UseWeaponAnimsForGrip = 1775814871, + Value = 4108660753, + variationData = 3467549031, + Variations = 1085728185, + VEHGEN_MARKUP_FILE = 2433209284, + VEHICLE_LAYOUTS_FILE = 2004032454, + VEHICLE_METADATA_FILE = 4125139733, + VEHICLE_POPULATION_FILE = 4010054647, + VEHICLE_RESPONSE_ARMY_BASE = 317362887, + VEHICLE_RESPONSE_COUNTRYSIDE = 2467847847, + VEHICLE_SHOP_DLC_FILE = 3203173146, + VEHICLE_VARIATION_FILE = 4226342447, + VEHICLEEXTRAS_FILE = 2814482675, + VehicleScale = 201238485, + Velocity = 3642784282, + version = 1757576755, + VersionNumber = 1292187579, + verts = 120498671, + VFX_SETTINGS_FILE = 1765838387, + VFXFOGVOLUMEINFO_FILE = 895306, + VfxInfoName = 3527474215, + VFXINTERIORINFO_FILE = 354822867, + VFXPEDINFO_FILE = 962370952, + VFXREGIONINFO_FILE = 3633596549, + vfxTagHashName = 1944993828, + VFXVEHICLEINFO_FILE = 1918258814, + vfxVehicleInfos = 1829968483, + VFXWEAPONINFO_FILE = 1215743990, + visibleMods = 33867712, + //vlink87812 = 380604338, + VMCP_DEFAULT = 1688385326, + VMT_ARMOUR = 2031251422, + VMT_BONNET = 1157831199, + VMT_BRAKES = 2354237771, + VMT_BUMPER_F = 3594621894, + VMT_BUMPER_R = 2063293755, + VMT_CHASSIS = 2275972991, + VMT_CHASSIS2 = 2944517492, + VMT_CHASSIS3 = 2694326177, + VMT_CHASSIS4 = 2463042575, + VMT_CHASSIS5 = 2742201586, + VMT_DOOR_L = 3833672138, + VMT_ENGINE = 154537048, + VMT_ENGINEBAY1 = 3358404671, + VMT_ENGINEBAY2 = 4274232691, + VMT_ENGINEBAY3 = 3976067552, + VMT_EXHAUST = 610039613, + VMT_GEARBOX = 2500094337, + VMT_GRILL = 2021558782, + VMT_HORN = 100765382, + VMT_HYDRO = 1330081664, + VMT_ICE = 2442467387, + VMT_INTERIOR1 = 4022516897, + VMT_INTERIOR2 = 1135961221, + VMT_INTERIOR3 = 829865992, + VMT_INTERIOR4 = 675392926, + VMT_INTERIOR5 = 368838931, + VMT_KNOB = 676118374, + VMT_LIVERY_MOD = 2724696322, + VMT_PLAQUE = 671395830, + VMT_PLTHOLDER = 1090914661, + VMT_PLTVANITY = 1166632877, + VMT_ROOF = 908701629, + VMT_SEATS = 4033680966, + VMT_SKIRT = 380480791, + VMT_SPOILER = 1049675683, + VMT_STEERING = 31361425, + VMT_SUSPENSION = 3334458998, + VMT_TRUNK = 514422827, + VMT_WHEELS = 4228473823, + VMT_WHEELS_REAR_OR_HYDRAULICS = 1919950653, + VMT_WING_L = 3535906757, + VMT_WING_R = 2323846985, + vPos = 587040309, + WantedLevel1 = 2416800515, + WantedLevel2 = 1650825140, + WantedLevel3 = 1939323416, + WantedLevel4 = 1171840667, + WantedLevel5 = 1195762037, + WATER_FILE = 2413655090, + Weak = 4041095418, + WEAPON_ANIMATIONS_FILE = 3924289757, + WEAPON_METADATA_FILE = 2179567645, + WEAPON_SHOP_INFO_METADATA_FILE = 3762885521, + WeaponAccuracy = 2027467678, + WeaponAnimations = 4015456176, + WeaponClipFilterId = 671807081, + WeaponClipSetId = 2215753076, + WEAPONCOMPONENTSINFO_FILE = 2246020636, + WEAPONFX_FILE = 1805309100, + WeaponImpulseMultiplier = 86352657, + WEAPONINFO_FILE = 314037850, + WEAPONINFO_FILE_PATCH = 4078051975, + Weapons = 3632627376, + WEATHER_FILE = 1275718771, + WeatherTypes = 2541515394, + weight = 2618193740, + wheelBurnoutPtFxFricMult = 3985640029, + wheelBurnoutPtFxTempMult = 4090549898, + wheelBurstPtFxName = 2298765511, + wheelBurstPtFxRange = 627010713, + wheelDisplacementPtFxDispMult = 1903391014, + wheelFirePtFxName = 1493987177, + wheelFirePtFxRange = 2979062979, + wheelFirePtFxSpeedEvoMax = 2074742492, + wheelFirePtFxSpeedEvoMin = 88414520, + wheelFrictionPtFxFricMult = 3344943153, + WHEELFX_FILE = 797011099, + wheelGenericDecalSet = 42119146, + wheelGenericPtFxSet = 317708598, + wheelGenericRangeMult = 3112058125, + wheelLowLodPtFxScale = 3101484583, + wheelName = 1946665057, + wheelPuncturePtFxName = 3306375051, + wheelPuncturePtFxRange = 1038999289, + Wheels = 3527735923, + wheelSkidmarkPressureMult = 3868991234, + wheelSkidmarkRearOnly = 3924188767, + wheelSkidmarkSlipMult = 1637659302, + wheelVariation = 3934106566, + Width = 2076102628, + WindBendScale = 2639208686, + WindBendVariation = 3427496475, + window_lf = 4283577347, + window_rf = 498851022, + windowsWithExposedEdges = 2852673211, + windscreen_r = 1088105007, + wing_lf = 491509005, + wing_rf = 3902761333, + WORLD_HEIGHTMAP_FILE = 2667598674, + WORLD_WATERHEIGHT_FILE = 2962141595, + wreckedFire2OffsetPos = 3365413657, + wreckedFire2PtFxDurationMax = 3958205758, + wreckedFire2PtFxDurationMin = 934999495, + wreckedFire2PtFxEnabled = 942100204, + wreckedFire2PtFxName = 2665978636, + wreckedFire2PtFxRadius = 1241381211, + wreckedFire2UseOverheatBone = 1005799487, + wreckedFire3OffsetPos = 1884074151, + wreckedFire3PtFxDurationMax = 3291844506, + wreckedFire3PtFxDurationMin = 2778506827, + wreckedFire3PtFxEnabled = 1459332728, + wreckedFire3PtFxName = 4213089658, + wreckedFire3PtFxRadius = 19666915, + wreckedFire3UseOverheatBone = 3745878980, + wreckedFirePtFxDurationMax = 912287935, + wreckedFirePtFxDurationMin = 1608647578, + wreckedFirePtFxEnabled = 1538181140, + wreckedFirePtFxName = 4220065034, + wreckedFirePtFxRadius = 1064003341, + x = 2466489829, + X = 1252398387, + xRotation = 712901235, + y = 2157248776, + Y = 953119110, + yRotation = 3411163434, + z = 3059772574, + Z = 1848695880, + zBias = 4001151357, + ZONEBIND_FILE = 3024721823, + zRotation = 1366235387, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //Shader params - strings converted to lowercase before hashing! + + + _dimensionLOD2 = 2213330743, + _fakedGrassNormal = 3847734030, + _vecCollParams = 1235110448, + _vecVehColl0B = 3443329873, + _vecVehColl0M = 2054776271, + _vecVehColl0R = 3676612388, + _vecVehColl1B = 3338172776, + _vecVehColl1M = 3731892311, + _vecVehColl1R = 1839679119, + _vecVehColl2B = 1542889970, + _vecVehColl2M = 298913216, + _vecVehColl2R = 3503557575, + _vecVehColl3B = 2492173731, + _vecVehColl3M = 2003587933, + _vecVehColl3R = 3129694622, + _vecVehCollB = 4034110113, + _vecVehCollM = 4084115603, + _vecVehCollR = 2902956998, + Acceleration_Delta = 4042077187, + accumulationBufferSampler0 = 8230410, + accumulationBufferSampler1 = 272905623, + activeShadowCascades = 2747556057, + adapDOFProj = 711499858, + AdapLumSampler = 2600073949, + AdaptedLumMax = 735476279, + AdaptedLumMin = 120989687, + AdaptionParams = 994945211, + adaptive = 2577319765, + AdaptiveDofDepthDownSampleParams = 530741887, + adaptiveDOFExposureSampler = 2063861440, + AdaptiveDofFocusDistanceDampingParams1 = 4192702981, + AdaptiveDofFocusDistanceDampingParams2 = 3918393682, + AdaptiveDOFOutputBuffer = 2655767810, + AdaptiveDofParams0 = 1088399132, + AdaptiveDofParams1 = 806028659, + AdaptiveDofParams2 = 1767143429, + AdaptiveDofParams3 = 2870836122, + AdaptiveDOFParamsBuffer = 209455569, + adaptiveDOFSampler = 2098736783, + adaptiveDOFSamplerDepth = 718794333, + AdaptTime = 1514540018, + AirResist = 1208302886, + alphaAdjust = 1287606900, + AlphaMaskMapSampler = 1705051233, + AlphaRange = 1331056747, + AlphaScale = 931055822, + AlphaTest = 950204405, + alphaTestValue = 3310830370, + altRemap = 285573515, + AmbientDecalMask = 3686186843, + AmbientLightingParams = 1614910597, + ambientOcclusionContrast = 633061550, + AmbientOccSampler = 1212577329, + AnimatedNormalMapMask0Sampler = 2630205212, + AnimatedNormalMapMask1Sampler = 1838164585, + AnimatedNormalMapMask2Sampler = 2257753125, + animatedNormalMapMod1 = 96407192, + animatedNormalMapMod2 = 326478341, + AnisoNoiseSpecSampler = 2134197289, + AnisotropicAlphaBias = 363074471, + anisotropicSpecularColour = 1673722929, + anisotropicSpecularExponent = 499953092, + anisotropicSpecularIntensity = 401654871, + APlaneSampler = 1600333029, + ApplyDamageSampler = 1117905904, + approxTangent = 3606611481, + ArmourStrength = 3061795481, + AttenuationSampler = 483360323, + AverageLuminanceOut = 1654447808, + AvgLuminanceTexture = 1087818619, + AzimuthColor = 360934156, + AzimuthColorEast = 1882877478, + azimuthEastColor = 1044876032, + AzimuthHeight = 2649852765, + AzimuthStrength = 2824307566, + azimuthTransitionColor = 2670115477, + azimuthTransitionPosition = 2764855899, + azimuthWestColor = 1874413695, + BackBufferSampler = 3700325701, + BackBufferTexture = 3200056981, + BaseSampler = 2669264211, + baseTextureSampler = 1399472831, + bDebugDisplayDamageMap = 727005071, + bDebugDisplayDamageScale = 1720897181, + Billboard = 552363713, + blitSampler = 4098753311, + BloodSampler = 1970149772, + BloodSamplerVS = 3796090472, + BloodZoneAdjust = 1011740581, + bloomLum = 1959356754, + BloomParams = 1213613006, + BloomSampler = 1613750243, + BloomSamplerG = 2187220839, + BloomTexelSize = 3590118590, + BlueOff = 1614062594, + blurIntensity = 804387779, + BlurSampler = 822703767, + BlurVignettingParams = 871768731, + BokehAlphaCutoff = 1703140281, + BokehBrightnessParams = 1737665654, + BokehEnableVar = 643379889, + BokehGlobalAlpha = 1022881476, + BokehNumAddedToBuckets = 2514924683, + BokehParams1 = 3945388007, + BokehParams2 = 4184896628, + BokehPointBuffer = 2084769495, + BokehSortedIndexBuffer = 1533187666, + BokehSortedListBuffer = 201662228, + BokehSortLevel = 2314931517, + BokehSortLevelMask = 1605336858, + BokehSortTransposeMatHeight = 3470273647, + BokehSortTransposeMatWidth = 821002802, + BokehSpritePointBuffer = 170997925, + bottomSkyColour = 161676916, + BoundRadius = 2230834649, + branchBendPivot = 892666959, + branchBendStiffnessAdjust = 3894262326, + Brightness = 26603225, + BrightnessSetting = 303513935, + BrightTonemapParams0 = 118691255, + BrightTonemapParams1 = 1904208559, + BrokenBumpSampler = 2033191777, + BrokenColor = 2817208061, + BrokenDiffuseColor = 878330249, + BrokenDiffuseSampler = 3349868497, + BrokenGlassTileScale = 1356197901, + BrokenSpecularColor = 1359397883, + BrokenSpecularSampler = 3872409448, + bumpiness = 4134611841, + BumpSampler = 1186448975, + BumpSampler_layer0 = 1073714531, + BumpSampler_layer1 = 1422769919, + BumpSampler_layer2 = 2745359528, + BumpSampler_layer3 = 2975430677, + BumpSampler_layer4 = 2417505683, + BumpSampler_layer5 = 3720106230, + BumpSampler_layer6 = 4091379000, + BumpSampler2 = 1893875305, + BumpSamplerFur = 2030333799, + bumpSelfShadowAmount = 2907460320, + BurnoutLimit = 2048742054, + cBPlaneSampler = 1648690748, + ChromAbParam = 2243268978, + clearcol = 2021704599, + clippingPlane = 1632555383, + ClipPlanes = 4225498643, + ClothDarken = 4285790447, + ClothDarkenColor = 2192646550, + clothParentMatrix = 2335024113, + ClothSweatMapSampler = 1059055951, + ClothSweatSpec = 2469844039, + cloudBaseColour = 2670795993, + cloudBaseMinusMidColour = 207551193, + CloudBias = 1077109597, + cloudBillboardParams = 1372983410, + CloudColor = 3245908258, + cloudConstants1 = 1542931277, + cloudConstants2 = 1848698816, + cloudConstants3 = 3972097247, + cloudDetailConstants = 2178269534, + CloudFadeOut = 1796923256, + CloudInscatteringRange = 1590938598, + cloudLayerAnimScale1 = 2699058131, + cloudLayerAnimScale2 = 2904978527, + cloudLayerAnimScale3 = 1697604722, + cloudMidColour = 3120184161, + cloudShadowColour = 2429466598, + cloudShadowMinusBaseColourTimesShadowStrength = 3681751999, + CloudShadowOffset = 1192276656, + CloudShadowStrength = 3469302040, + CloudThicknessEdgeSmoothDetailScaleStrength = 2448643918, + CloudThreshold = 2011404587, + ClumpBump = 620873514, + COCOutputTexture = 561614071, + ColorCorrect = 1418724964, + ColorCorrectHighLum = 1002641818, + ColorFringeParams1 = 1315010326, + ColorFringeParams2 = 94922157, + colorHighLum = 3178323397, + colorLowLum = 4274011020, + colorLum = 819694290, + ColorSampler = 3918882525, + colorScaler = 2433112487, + ColorShift = 3269836664, + ColorShiftLowLum = 2775271800, + ColorShiftScalar = 2106064165, + ColorTexture = 934209648, + ComboHeightSamplerFur = 455740840, + ComboHeightSamplerFur01 = 1709265783, + ComboHeightSamplerFur2 = 374924583, + ComboHeightSamplerFur23 = 2930074258, + ComboHeightSamplerFur3 = 2760212866, + ComboHeightSamplerFur4 = 4056161278, + ComboHeightSamplerFur45 = 2509158229, + ComboHeightSamplerFur67 = 1396547512, + ComboHeightTexMask = 285679314, + Contrast = 699508084, + ConvertSampler = 4959160, + CoronasDepthMapSampler = 3603235271, + CrackDecalBumpAlphaThreshold = 3343925161, + CrackDecalBumpAmount = 2155296103, + CrackDecalBumpTileScale = 730767419, + CrackEdgeBumpAmount = 3420190257, + CrackEdgeBumpTileScale = 492538267, + crackleIntensity = 1771354266, + CrackleSampler = 1774790613, + CrackMatrix = 2644409350, + CrackOffset = 2214698276, + CrackSampler = 3328498618, + cRPlaneSampler = 3915834095, + cubeFace = 2567801214, + CurLumSampler = 3431586341, + currentDOFTechnique = 3543504858, + currentLum = 968818364, + currentResolution = 4182813263, + curveCoeffs = 2763646717, + DamagedWheelOffsets = 1348413520, + DamageMultiplier = 378227101, + DamageSampler = 3579349756, + damageSpecTextureSampler = 3820652825, + DamageTextureOffset = 4318529, + damageTextureSampler = 4132715990, + DamageVertBuffer = 2811144871, + DarkTonemapParams0 = 1554855265, + DarkTonemapParams1 = 780523795, + deathIntensity = 2219791851, + DeathSampler = 4146990968, + debugCloudsParams = 580885775, + debugLightColour = 227690714, + DecalSampler = 2811948736, + DecalTint = 3092072610, + DecorationFrameInfo = 3729783099, + DecorationTattooAdjust = 1578586549, + DecorationTintPaletteSel = 2448945809, + DecorationTintPaletteTexSampler = 4286164294, + deferredLightDownsampleDepthSampler = 110250107, + deferredLightParams = 1690620309, + deferredLightScreenSize = 3811483225, + deferredLightVolumeParams = 2130744975, + deferredPerspectiveShearParams0 = 3433855881, + deferredPerspectiveShearParams1 = 61303170, + deferredPerspectiveShearParams2 = 4125937165, + deferredProjectionParams = 424764587, + deferredVolumeColour = 2115695095, + deferredVolumeDepthBufferSamp = 3381865158, + deferredVolumeDirection = 3203966112, + deferredVolumePosition = 1009422528, + deferredVolumeShaftCompositeMtx = 3101393666, + deferredVolumeShaftGradient = 404580226, + deferredVolumeShaftGradientColourInv = 1067440921, + deferredVolumeShaftPlanes = 3122758957, + deferredVolumeTangentXAndShaftRadius = 1118228408, + deferredVolumeTangentYAndShaftLength = 4283942594, + DensitySampler = 3828368598, + DepthBlurHalfResSampler = 2333753907, + DepthBlurHalfResTexture = 2638246296, + DepthBlurSampler = 979379647, + DepthBlurTexture = 4038110621, + depthBuffer = 3447665758, + depthBuffer2 = 1908423578, + depthBuffer2_Sampler = 720934291, + DepthBufferSamp = 2492728818, + DepthBufferSampler = 3497598060, + DepthMapPointSampler = 4215380418, + DepthMapSampler = 847477652, + DepthMapTexSampler = 2784473838, + DepthSampler = 383876435, + depthSourceSampler = 2578937463, + depthTexture = 4088842947, + DepthTextureMS = 4134029566, + deSatContrastGamma = 1070958827, + Desaturate = 2639337807, + desaturateTint = 2511699259, + detailBumpiness = 1675037470, + DetailBumpSampler = 143227613, + DetailDensity2Sampler = 2587222892, + DetailDensitySampler = 2270155403, + detailMapOffset = 3032413960, + DetailMapSampler = 1041827691, + detailMapUScale = 489333004, + detailMapVScale = 2830921123, + DetailNormal2Sampler = 2004179855, + DetailNormalSampler = 2903840997, + DetailOffset = 2002782257, + DetailSampler = 3393362404, + detailSettings = 3038654095, + detailUVScale = 3418497265, + diffuse2SpecMod = 1788442252, + diffuseCol = 1517692383, + DiffuseExtraSampler = 58635929, + DiffuseHfSampler = 2946270081, + diffuseMod = 1685953011, + DiffuseNoBorderTexSampler = 1732587965, + DiffuseSampler = 4059966321, + DiffuseSampler2 = 181641832, + DiffuseSamplerFur = 1282320680, + DiffuseSamplerPhase2 = 3227619449, + DiffuseSamplerPoint = 4015001285, + DiffuseSplatterTexSampler = 1412546033, + DiffuseTexSampler = 3004704155, + DiffuseTexSampler01 = 255045494, + DiffuseTexSampler02 = 2707084226, + DiffuseTexSampler03 = 2981196911, + DiffuseTexSampler04 = 3291650421, + DiffuseTexTileUV = 2816002123, + DiffuseWoundTexSampler = 3758481220, + DiffusionRadius = 4024070401, + dimmerSet = 1523312743, + dimmerSetPacked = 4182305072, + DirectionalMotionBlurIterParams = 2777949533, + DirectionalMotionBlurLength = 544111294, + DirectionalMotionBlurParams = 3408424243, + dirtColor = 1146381126, + DirtDecalMask = 1050016400, + dirtLevel = 47191856, + dirtLevelMod = 3961814809, + DirtSampler = 2124031998, + DiskBrakeGlow = 1035405954, + displParams = 1163050293, + distanceMapSampler = 1616890976, + DistEpsilonScaleMin = 1163639717, + DistMapCenterVal = 1612602645, + distortionParams = 2957679312, + DistortionSampler = 342449994, + ditherSampler = 612917610, + dofBlur = 731686132, + DofBlurWeight = 706444485, + dofDist = 3329041621, + dofInten = 3552457075, + dofNoBlurBlendRingSize = 413916545, + dofNoBlurRadius = 108398598, + DOFOutputTexture = 3487236658, + dofProj = 2305108861, + dofProjCompute = 2729164810, + dofRenderTargetSize = 3995371223, + DOFSampler = 2614429576, + dofShear = 1387749709, + dofSkyWeightModifier = 1603770318, + DOFTargetSize = 3565962906, + downsampledDepthSampler = 2057740952, + DownsampleDepthSampler = 498175796, + dpMapFarClip = 3395601267, + dpMapNearClip = 479573217, + drawBucket = 514782960, + dReflectionParams = 153627866, + droopParams = 2926981594, + DruggedEffectColorShift = 4028255612, + DruggedEffectParams = 858398664, + dShadowMatrix = 3423656318, + dShadowOffsetScale = 930807775, + dShadowParam0123 = 3916656767, + dShadowParam4567 = 584100066, + dShadowParam891113 = 1698928349, + DstTextureSize = 45365902, + eaaParams2 = 1422359808, + earlyOut = 3422479905, + earlyOut_Sampler = 2971523439, + earlyOutParams = 141437565, + EastColor = 1417575779, + EdgeMarkParams = 717226593, + EdgeThreshold = 2670218238, + EdgeThresholdMin = 316543927, + effectsConstants = 1179101422, + ElapsedTime = 4152310215, + emissiveMultiplier = 1592520008, + emissiveReflectMultiplier = 1347035993, + EmitterParamLifeAndSpeed = 1295421465, + EmitterParamPos = 2286595424, + EmitterParamPosRange = 3505097448, + EmitterParamProbablityPhase2 = 1652433309, + EmitterTransform = 2216438402, + EmitterVelocityBoxPos = 1027158774, + EmitterVelocityBoxRange = 3202652030, + EnvBloodBinormal = 304838968, + EnvBloodData = 2241230170, + EnvBloodPos = 3704052925, + EnvBloodSampler = 3616483953, + EnvBloodTangent = 1134317228, + envEffFatThickness = 436649803, + envEffScale = 2431974683, + envEffTexTileUV = 3670603239, + envEffThickness = 2702504809, + EnvironmentSampler = 3317411368, + Exposure = 2538078618, + ExposureClampAndHistory = 2911392042, + ExposureCurve = 1836476954, + ExposureParams0 = 2329380491, + ExposureParams1 = 1031924697, + ExposureParams2 = 1253836365, + ExposureParams3 = 301405380, + Exposures = 2947662557, + ExposureSwitches = 1784826898, + faceTextureSampler = 624309278, + facetMask = 4034105764, + Fade_Thickness = 205855514, + fadeAlphaDist = 4164097433, + fadeAlphaDistUmTimer = 3637887135, + fadeAlphaLOD1Dist = 3563207876, + fadeAlphaLOD2Dist = 1294165969, + fadeAlphaLOD2DistFar0 = 4248689351, + fAge = 2063122051, + FallOffAndKernelParam = 1703468999, + fillColor = 3014106266, + Filmic0 = 2611530409, + fIntensity = 847954571, + FlowSampler = 1214194352, + FoamSampler = 3266349336, + FogColor = 3922291195, + FogParams = 1243028310, + FogRayTexSampler = 1487203018, + FogSampler = 2568933054, + fogVolumeColor = 2907231751, + fogVolumeDepthSampler = 1087981784, + fogVolumeInvTransform = 786602411, + fogVolumeParams = 10424280, + fogVolumePosition = 2937842810, + fogVolumeTransform = 1406518664, + foliageBranchBendPivot = 353881103, + foliageBranchBendStiffnessAdjust = 3429332683, + FontNormalSampler = 3140496408, + FontNormalScale = 91417371, + FontSampler = 2048139100, + FontTexture = 3394800319, + fourPlaneDof = 2764191939, + fpvMotionBlurSize = 1677050762, + fpvMotionBlurVelocity = 4116905408, + fpvMotionBlurWeights = 4038439571, + FrameMap = 1835157646, + FrameMapTexSampler = 507369750, + Frequency1 = 2441536523, + Frequency2 = 2219624855, + fresnelRolloff = 3796399242, + FullSampler = 3157511856, + furAlphaClip03 = 290288684, + furAlphaClip47 = 4280570754, + furAlphaDistance = 4141869331, + furAOBlend = 4026629301, + furAttenCoef = 2491165204, + furBendParams = 3489000159, + furDitherAlphaFadeParams = 3407922321, + furGlobalParams = 443249107, + furLayerParams = 1122745807, + furLayerParams2 = 3825466177, + furLayerParams3 = 1668577832, + furLayerStep = 1208356461, + furLength = 1430134069, + FurMaskSampler = 3794875320, + furMaxLayers = 253873259, + furMinLayers = 3007864804, + furNoiseUVScale = 1008743034, + furNumLayers = 110936794, + furSelfShadowMin = 3093266608, + furShadow03 = 1104745269, + furShadow47 = 711397225, + furStiffness = 2137279259, + furUvScales = 897751165, + g_AlphaFade = 1960511459, + g_BloodColor = 985986992, + g_BloodSplatParams = 1621619881, + g_CPQSMix_QSFadeIn = 2799702011, + g_CurrentValue = 1312005277, + g_EdgeHighlightColour = 1596321467, + g_f4RTSize = 4169783008, + g_fBilateralCoefficient = 2015612345, + g_fBilateralEdgeThreshold = 2771898508, + g_fCollisionSqScale = 731874660, + g_fEnableSpringForces = 2189248122, + g_fGrassSpringRigidity = 3152689414, + g_fGrassSpringScale = 2339438728, + g_fRippleRainStrength = 2044767128, + g_fSSAOBilateralCoef = 145680953, + g_fSSAOKernelScale = 3370811738, + g_fVolumetricLightRayIntensityMult = 3709677333, + g_GBufferTexture3Param = 3145202593, + g_GhostLevel = 1563742563, + g_HDAO_Params1 = 1535730194, + g_HDAO_Params2 = 3676889419, + g_HDAOApplyParams = 2705555169, + g_HDAOComputeParams = 2528000437, + g_HDAOExtraParams = 3628503020, + g_HDAOValleyParams = 1466262319, + g_HighlightScale = 1705698884, + g_ImposterSize = 786569893, + g_LightningStrikeNoiseParams = 390679343, + g_LightningStrikeParams = 3780586083, + g_LinearClampSampler = 2261256735, + g_MSAAPointTexture1_Dim = 3319333866, + g_MSAAPointTexture2_Dim = 3715862146, + g_OcclusionTextureParams = 4007914843, + g_PointSampler = 3230386348, + g_projParams = 360593454, + g_projShear = 1833194361, + g_Puddle_ScaleXY_Range = 529156535, + g_PuddleParams = 3536830402, + g_ResultTexture = 3349637075, + g_SSAOStrength = 1519496158, + g_targetSize = 1149055682, + g_TextColour = 3414941892, + g_TextShadowColour = 3326514923, + g_TextShadowScale = 828975922, + g_vCollisionParams = 390873962, + g_vCollisionSpheres = 2187899533, + g_vPlayerPosition = 148353768, + g_vRelativeLuminanceThresholdParams = 1353171807, + g_vRippleAttributes = 1686992389, + g_vRippleTexelSize = 2041279531, + g_vTexelSize = 1568580394, + g_WaveXOffset = 2340128792, + g_WaveXZoom = 1940934038, + g_WaveYZoom = 936340354, + g_WidthScalar = 1482315230, + gActiveUnit = 247068080, + GalaxyOffset = 2261454336, + GalaxySampler = 304699295, + gAlphaCutoffMinMax = 3012586280, + gAlphaTest = 2215224122, + gAlphaToCoverageScale = 955152299, + gAmbientAmount = 862548646, + gAmbientColor = 2502793579, + gAmbientMult = 2621865253, + gAmbientShadow = 1730637860, + Gamma = 1617619096, + GammaCorrection = 2923835982, + gAnimatedNormalMapParams = 1356180523, + gAnimBlendWeights = 3438696362, + gAnimCombine = 4162938569, + gAnimSculpt = 732819097, + GaussianWeights = 3546535582, + gBackgroundDistortionAlphaBooster = 1266153517, + gBackgroundDistortionAmount = 2358946644, + gBackgroundDistortionVisibilityPercentage = 1950755416, + gBiasToCamera = 969255365, + gBlitMatrix = 1903406607, + gBloodData = 2470245206, + gBloodUVBoundsPage = 318462180, + gBlurAmount = 2372939986, + gBoneDamage0 = 493675041, + gBoneDamageEnabled = 3445557846, + gBounceColor = 3285219193, + gBoxCentrePos = 1213320064, + gBoxForward = 2141719324, + gBoxRight = 3950477470, + gBoxSize = 4157270760, + GBufferStencilTextureSampler = 34323572, + gbufferTexture0 = 1370576551, + gbufferTexture2 = 989669695, + gbufferTextureDepth = 3214151316, + GBufferTextureSampler0 = 3101514270, + GBufferTextureSampler1 = 1931628197, + GBufferTextureSampler2 = 1601349446, + GBufferTextureSampler3 = 394499945, + GBufferTextureSamplerDepth = 3001958741, + GBufferTextureSamplerSSAODepth = 566345585, + gCableParams = 3557855020, + gCamAngleLimits = 1391293880, + gCameraBias = 481136556, + gCameraDistanceAtMaxDisplacement = 894396470, + gCameraPos = 130109679, + gCameraPosition = 3861036523, + gCameraShrink = 196757553, + gClipPlanes = 993087185, + gCloudColor = 3349623462, + gCloudViewProj = 1388118204, + gCollisionLifeModifier = 28882798, + gCollisionPositionModifier = 1413333801, + gCollisionVelocityModifier = 2917041400, + gColorTint = 1945696018, + gColorTintPhase2 = 3971978241, + gColour = 819380429, + gColourSplash = 2769897443, + gControlLight = 1458962865, + gCrossFadeDistance = 2123742775, + gCSMParticleShadowSamp = 18467538, + gCSMParticleShadowTexture = 1879733647, + gCSMShaderVars_deferred = 4041368736, + gDayNightScale = 2033466401, + gDecalChannelSelection = 129604674, + gDecalNormalSampler = 353477773, + gDecalSampler = 2317915042, + gDeferredInverseViewProjMatrix = 3129339935, + gDeferredLightColourAndIntensity = 3618208763, + gDeferredLightConeAngle = 1457978794, + gDeferredLightConeAngleI = 3706722404, + gDeferredLightConeOffset = 2681954581, + gDeferredLightConeScale = 3587849890, + gDeferredLightDirection = 3096160936, + gDeferredLightInvSqrRadius = 1076369960, + gDeferredLightPosition = 3515628483, + gDeferredLightRadius = 771816156, + gDeferredLightRadiusProjShearParams = 507484242, + gDeferredLightSampler = 1527752693, + gDeferredLightSampler0P = 3029377315, + gDeferredLightSampler1 = 575604989, + gDeferredLightSampler2 = 1424289320, + gDeferredLightShadowMap0 = 2826529087, + gDeferredLightShadowMap1 = 2589969676, + gDeferredLightShadowMap2 = 2224923016, + gDeferredLightShadowMap3 = 1962213943, + gDeferredLightShaftParams = 2784101259, + gDeferredLightTangent = 3997363695, + gDeferredLightType = 874695930, + gDeferredLightVolumeParams = 371509596, + gDeferredProjParams = 1174638206, + gDeferredVolumeRadiusScale = 3037897088, + gDensityShiftScale = 3043875162, + gDepthViewProjMtx = 512139429, + gDiffuse = 1220611861, + gDirectional = 2203405262, + gDirectionalLightShadowAmount = 3920559848, + gDirectionalMotionBlurLength = 2219759593, + gDirectionalMult = 4000928118, + gDirectionalVelocityAdd = 1608450430, + gDirectionalZOffsetMinRange = 955747368, + gDirNormalBias = 1480114695, + gDispersalSettings = 570820137, + gDistanceScale = 3645463202, + gEastMinusWestColor = 2332609458, + gEdgeSoftness = 867642987, + GeneralParams0 = 3458676571, + GeneralParams1 = 3166540936, + gExtraLightMult = 3645170126, + gExtraLights = 2849007823, + gExtraParams0 = 1363351178, + gExtraParams1 = 3423931440, + gExtraParams2 = 4223069043, + gExtraParams3 = 3907306959, + gExtraParams4 = 2518327352, + gFadeInOut = 1682568218, + gFadeNearFar = 1244256289, + gFadeZBaseLoHi = 542136670, + gFirstTimeUpdate = 92947686, + gFogCompositeAmbientColor = 2918893733, + gFogCompositeDirectionalColor = 646659969, + gFogCompositeParams = 3080532465, + gFogCompositeTexOffset = 1705135815, + gFrustumParameters = 1069442784, + gGrassSkipInstance = 3294601711, + gGravityWindTimeStepCut = 2189578124, + gGustAmplifier = 1813609204, + gGustSpacing = 2572448010, + gHDRExposure = 1986583430, + gHeatHaze = 1822868744, + gHeatHazeRippleLength = 1850681702, + gHeatHazeRippleRate = 3558453078, + gHeatHazeScale = 3312170287, + gHeatHazeSize = 1319873596, + gHeatHazeWidth = 3133152963, + gHeatPhase = 2721110750, + gHitPlane = 3729639013, + ghorizScale = 2467525454, + gHybridAddRatio = 3504408232, + gInstanceVars = 3432648184, + gInstCullParams = 3871720938, + gIntensity = 3311833552, + gInterpolationFactor = 1392131636, + gIsShadowPass = 1999109769, + gLifeFade = 1079477869, + gLifeMinMaxClampToGround = 3942952480, + gLifeTimeScale = 3294686231, + gLightIntensityClamp = 4186188647, + gLightIntensityMult = 1884220195, + gLightSettings = 1029904424, + globalAnimUV0 = 3617324062, + globalAnimUV1 = 3126116752, + globalFogRayFadeParam = 1248095708, + globalFogRayParam = 1620085657, + globalFreeAimDir = 3943027507, + gLocalLightsMultiplier = 4293612306, + gLodFadeControlRange = 4185950307, + gLodFadePower = 2662986932, + gLodFadeRange = 3264171975, + gLodFadeStartDist = 1949054155, + gLodFadeTileScale = 1082098581, + gLodInstantTransition = 596864795, + gLodThresholds = 979130770, + gLowResDepthSampler = 2824212180, + gLowResDepthTexture = 3015483598, + gMaxDisplacement = 1164495840, + gMaxLife = 3970444018, + gMirrorBounds = 1887204037, + gMirrorCrackAmount = 1562064116, + gMirrorCrackSampler = 2984091644, + gMirrorDebugParams = 496893366, + gMirrorDistortionAmount = 987148199, + gMotionBlur = 294407736, + gNearFarQMult = 2513511302, + gNormalArc = 808788377, + gNormalHeight = 3146080364, + gNormalMapMult = 3282331164, + gNormalOffset = 2355039984, + gNormalScale = 2365712398, + gNumClipPlanes = 828848872, + gOffsetParticlePos = 842278893, + gOffsetScale0 = 70492586, + gOffsetScale1 = 428526680, + goldFactor = 358396505, + goldFresnelRolloff = 295546023, + goldReflectColorBase = 2396384524, + goldReflectColorOverlay = 2603016628, + goldReflectivePower = 2990597200, + goldSpecMapIntMask = 1333698176, + goldSpecularFactor = 435211370, + GolfTrailTextureSamp = 241657115, + gooDeferredLightScreenSize = 3073062802, + gOrientToTerrain = 3165461554, + gParticleColorPercentage = 1853363478, + gParticleTextureSize = 2550169896, + gPerspectiveShearParams0 = 2149148446, + gPerspectiveShearParams1 = 509977564, + gPerspectiveShearParams2 = 263128687, + gPiercingLightPower_Strength_NormalStrength_Thickness = 2302032860, + gPositionOffset = 2734209203, + gPositionScale = 4212665338, + gPower = 1384422613, + gPrevViewProj = 1120562824, + gProjParams = 2311871851, + GradientFilterColBottom = 3762433606, + GradientFilterColMiddle = 1794637696, + GradientFilterColTop = 4015194706, + gRadius = 526220184, + gRainDebug = 1247076385, + gravityDroop = 3181978688, + GreenOff = 3283681954, + gReflScales = 1520419346, + gRefParticlePos = 2705128804, + gRefraction = 2643069888, + gRescaleUV1 = 724216589, + gRescaleUV2 = 2046871736, + gRescaleUV3 = 2259804698, + gResetParticles = 2831259018, + gRG_BlendEndDistance = 3347456804, + gRG_BlendStartDistance = 4179423620, + gRotationCenter = 2718167535, + gRotSpeedMinRange = 3733294048, + groundColor = 3169191053, + gScaleDiffuseFillAmbient = 397913198, + gScaleFade = 3144708943, + gScaleRange = 4248652172, + gScatterG_GSquared_PhaseMult_Scale = 987241318, + gShadowAmount = 3297538021, + gSizeMinMax = 1571728947, + gSizeMinRange = 3419056622, + gSkyColor = 3328933361, + gSoftness = 2874180382, + gSoftnessCurve = 2667435005, + gSoftnessShadowMult = 2718764463, + gSoftnessShadowOffset = 2710273761, + gSoftParticleRange = 3901093204, + gSpecularExponent = 3204977572, + gSpecularIntensity = 247886295, + gSplashFrames = 944333453, + gSplashSizeMinMax = 4062424283, + gSunColor = 3007207522, + gSunDirection = 2009439163, + gSuperAlpha = 1225534059, + gSurfaceSettings = 3834090438, + gtaSkyDomeClip = 964033580, + gtaSkyDomeFade = 826009472, + gtaWaterColor = 4280744704, + gTexCoordScaleOffset0 = 3099617970, + gTexCoordScaleOffset1 = 2745647232, + gTexCoordScaleOffset2 = 2499388197, + gTexCoordScaleOffset3 = 2456002041, + gTextureAngleRads = 241993590, + gTextureAnimation = 20918084, + gTextureAnimRateScaleOverLifeStart2End2 = 3412279679, + gTextureRowsCols = 1276450911, + gTextureRowsColsStartEnd = 1241308942, + gTotalLifeTimeScale = 2824822244, + gUseComputeShaderOutputBuffer = 1009029736, + gUseDirectional = 1281964389, + gUseShadows = 345674786, + gUVOffset = 3300015766, + gUVOffset1 = 2565276602, + gUVOffset2 = 2325899053, + gUVOffset3 = 3510465638, + gVelocityMax = 3037552071, + gVelocityMin = 507774218, + gvertScale = 1074904593, + gViewProj = 4124209033, + gVolumeLightsSampler = 1687175937, + gVolumeLightsTexture = 2884407863, + gWaterHeight = 446050918, + gWestColor = 3223173913, + gWindBaseVel = 3813992546, + gWindBendingGlobals = 709598663, + gWindBendScaleVar = 2552738797, + gWindGustVel = 2099280216, + gWindMultParams = 982613925, + gWindParams = 3536772057, + gWindVarianceVel = 2216170969, + gWorldBinormal = 2267341197, + gWorldInstanceInverseTranspose = 1914807, + gWorldInstanceMatrix = 981286173, + gWorldTangent = 1317093162, + gWrapBias = 1858190163, + gWrapLighting = 75905342, + gWrapLighting_MSAARef = 833328952, + gWrapScale = 3087563039, + gZdampen = 2165766204, + HardAlphaBlend = 3913511942, + HDRColorTexture = 2362960420, + HDRExposure = 3039323892, + HDRExposureClamp = 1487577326, + hdrIntensity = 4136287658, + HDRIntensityMultiplier = 1498595219, + HDRPointSampler = 3702694755, + HDRSampler = 1709735268, + HDRSunExposure = 81989056, + HDRTextureAA = 2769796592, + HeatHazeOffsetParams = 234272229, + HeatHazeParams = 3041693270, + HeatHazeSampler = 2900829390, + HeatHazeTex1Params = 157461750, + HeatHazeTex2Params = 3686416465, + heightBias = 330974467, + heightBias0 = 537974167, + heightBias1 = 820082484, + heightBias2 = 3378489398, + heightBias3 = 3161525849, + HeightFogParams = 4202365273, + HeightMapSampler = 1008099585, + heightMapSamplerLayer0 = 781078585, + heightMapSamplerLayer1 = 2570495372, + heightMapSamplerLayer2 = 2346748640, + heightMapSamplerLayer3 = 2242969217, + HeightMapTransformMtx = 1556799447, + HeightOpacity = 2935469584, + heightSampler = 4049987115, + heightScale = 947222050, + heightScale0 = 2807156689, + heightScale1 = 1898472319, + heightScale2 = 2178811114, + heightScale3 = 1536800866, + heightTexture = 4152773162, + hemi_bias = 3477916617, + hemi_near = 4068871657, + hemi_params = 3188015657, + hemi_range = 2843854391, + hemi_res = 3411758646, + HemiCubeSampler = 145567721, + hiDofMiscParams = 851407070, + hiDofParams = 3302089350, + HighDetailNoiseBumpSampler = 1044331566, + HighDetailNoiseSampler = 3822359214, + highDetailSampler = 860147427, + highLum = 737146002, + history = 2023011857, + HmdWarpParam = 4161661017, + horizonLevel = 403229780, + HybridAdd = 4234023609, + HybridAddRatio = 1902453223, + ImageFXParams = 3775812724, + importanceBufferSampler = 1983941369, + imposterDir = 15105794, + imposterSampler = 4013138833, + imposterWorldX = 3187870439, + imposterWorldY = 3495145352, + imposterWorldZ = 4037865530, + InitPositionTexSampler = 867916958, + InitVelocityTexSampler = 3796043845, + InputTex = 2352384719, + InstanceBuffer = 571392628, + InterlaceIndex = 92545662, + InterlaceMapSampler = 4281682490, + InterlaceTotalNum = 1200425084, + intermediateTarget = 2216618306, + intermediateTarget_Sampler = 1179275796, + intermediateTargetAA = 2580729000, + JitterSampler = 887426944, + kernelParam = 348424870, + kernelRadius = 1819724113, + KillFlashCol = 1705946031, + KillFlashUVOff = 1449898229, + LaserSampler = 3973852449, + LaserVisibilityMinMax = 2050561467, + LastBufferSize = 878694393, + LensArtefactsParams0 = 1487316152, + LensArtefactsParams1 = 870406958, + LensArtefactsParams2 = 1165295189, + LensArtefactsParams3 = 263361233, + LensArtefactsParams4 = 2409501354, + LensArtefactsParams5 = 1794558296, + LensCenter = 163655085, + LensDistortionParams = 705844615, + LetterIndex1 = 1794007338, + LetterIndex2 = 865825409, + LetterSize = 1497980819, + LicensePlateFontExtents = 3015810411, + LicensePlateFontTint = 1846736030, + LightColor = 1945364554, + LightDir = 1608210580, + LightOcclusionSampler = 3039301469, + lightrayParams = 912013868, + lightrayParams2 = 3575716412, + LightStreaksBlurDir = 2085391682, + LightStreaksColorShift0 = 4082051348, + LinearSampler = 2135833848, + LinearSampler1 = 4052371224, + LinearSampler2 = 2627575128, + LinearWrapSampler = 681732347, + LinearWrapSampler2 = 1379901712, + LinearWrapTexture3 = 4011882001, + lookupSampler = 2295086480, + lowLum = 2175272747, + LowResDepthMapPointSampler = 1894550764, + LowResDepthPointMap = 4131434726, + LumFilterParams = 2120745528, + LuminanceConstants = 2215984599, + LuminanceDownsampleOOSrcDstSize = 1869154352, + lunarCycle = 3166975708, + manualDepthTest = 2024632841, + MaskAlphaReverse = 3046988116, + maskTextureSampler = 2110569141, + matDiffuseColor = 408880252, + matDiffuseColor2 = 1577977996, + matDiffuseColorTint = 99676333, + materialDiffuse = 424198508, + materialIdSampler = 892830080, + materialWetnessMultiplier = 3170143313, + matGrassTransform = 72771513, + matMaterialColorScale = 2492093682, + matWheelTransform = 2829072482, + matWheelWorld = 3178367768, + matWheelWorldViewProj = 2078334811, + MBPerspectiveShearParams0 = 1033188477, + MBPerspectiveShearParams1 = 2555242989, + MBPerspectiveShearParams2 = 2292140688, + MBPrevViewProjMatrixW = 556540040, + MBPrevViewProjMatrixX = 2198692937, + MBPrevViewProjMatrixY = 2433876050, + MipMapLod = 482766300, + mirrorIntensity = 2215660639, + mirrorNormalIntensity = 1531688027, + mirrorParams = 2538518895, + mirrorReflectionSkyIntensity = 3525553109, + mirrorSpecMaskIntensity = 2901241109, + MLAAAreaLUTSampler = 2609019681, + MLAALinearSampler = 655764451, + MLAAPointSampler = 1645524956, + moonColor = 2213576281, + MoonColorConstant = 2616626323, + moonDirection = 3484629706, + MoonGlow = 2037987613, + MoonGlowSampler = 2151873246, + moonIntensity = 2342189917, + MoonLight = 2593156215, + moonPosition = 124803246, + moonSampler = 1534106922, + moonTexConvert = 1796762296, + MoonTexPosition = 1128557715, + MoonVisiblity = 3257982346, + MoonXVector = 1764174018, + MoonYVector = 3157759019, + motionBlurMatrix = 2950235179, + MotionBlurSampler = 3974544708, + MP_BulletTimeParams = 51894946, + MSAAPointSampler1 = 3816347419, + MSAAPointTexture1 = 750933622, + MSAAPointTexture2 = 989590249, + nearFarClip = 1899734512, + Noise1Sampler = 3941892287, + Noise2Sampler = 215717268, + noiseDensityOffset = 3780934309, + NoiseFilterArea = 1418684055, + noiseFrequency = 1364176943, + noiseHighLum = 3113827561, + noiseLowLum = 3302331435, + noiseLum = 1493025892, + NoiseMapSampler = 2678081716, + NoiseParams = 2296796634, + noisePhase = 1916643725, + NoiseSampler = 2461808165, + noiseScale = 4186750186, + noiseSoftness = 984327287, + NoiseTexSampler = 651303591, + noiseTexture = 1661149109, + NoiseTextureSampler = 4127640691, + noiseThreshold = 188180875, + NoiseWarp = 1708817206, + normalBuffer = 3727614344, + normalBufferSamp = 3334794412, + normalMapBlendRatio = 432051653, + normalMapMod = 1363116819, + NormalMapSampler = 860923645, + NormalMapSampler1 = 225912280, + NormalMapSampler2 = 4224746123, + NormalMapTexSampler = 2007347265, + normalSampler = 2327911600, + NormalSpecMapTexSampler = 2275171214, + normalTexture = 3453458978, + NormalTextureSampler = 53266845, + NormBufferSampler = 2450983583, + normFresnelRolloff = 469438475, + normReflectivePower = 99909810, + normSpecMapIntMask = 4286481776, + normSpecularFactor = 106090312, + normTable = 478874367, + numActiveShadowCascades = 2608506194, + NumLetters = 1303240218, + occlusionSampler = 50748941, + occlusionTexture = 2967810622, + OceanLocalParams0 = 2333080707, + offsetHighLum = 3768233024, + offsetLowLum = 1745892694, + offsetLum = 3139368420, + orderNumber = 1617153586, + paletteColor0 = 2390234167, + paletteColor1 = 345546874, + paletteColor2 = 650331343, + paletteColor3 = 1102019239, + paletteIndex = 2499973182, + PaletteSampler = 2950395616, + paletteSelector = 2636279676, + paletteSelector2 = 588791948, + ParabSampler = 2604688681, + parallaxScaleBias = 2178632789, + parallaxSelfShadowAmount = 242286661, + param0 = 3022832690, + param1 = 1630936646, + param2 = 2407332563, + param3 = 2110904189, + param4 = 739161080, + param5 = 411995384, + param6 = 1178691677, + param7 = 947113154, + params_ = 890816472, + ParticleCollisionSampler = 3713958763, + ParticlePosTexSampler = 2603657112, + ParticlePosXYTexSampler = 2279694207, + ParticlePosZWTexSampler = 1408622679, + particleShadowsParams = 2589755661, + ParticleVelTexSampler = 1792971393, + ParticleVelXYTexSampler = 3377719961, + ParticleVelZWTexSampler = 572101329, + PedBrightness = 2965570322, + PerlinNoiseSampler = 2192344499, + perlinSampler = 3428612092, + Persistance = 319450804, + perspectiveShearParam = 686675449, + Phase = 2726250539, + plantColor = 1360494706, + PlateBgBumpSampler = 1709116366, + PlateBgSampler = 1342317448, + PLAYER_MASK = 2584097651, + PlayerBrightness = 1987993393, + playerLFootPos = 1466936, + playerRFootPos = 982297002, + PointSampler = 1728781698, + PointSampler1 = 857651826, + PointSampler2 = 2186729701, + PointTexture1 = 3319640342, + PointTexture2 = 463756450, + PointTexture3 = 715389601, + PointTexture4 = 4030629335, + PointTexture5 = 4280230808, + poisson12 = 3700554683, + polyRejectThreshold = 3669125377, + PositionTexSampler = 124136329, + PostFXAdaptiveDofCustomPlanesParams = 2921923875, + PostFXAdaptiveDofEnvBlurParams = 383528417, + PostFxSampler2 = 3640527007, + PostFxSampler3 = 1268084184, + postProcess_FlipDepth_NearPlaneFade_Params = 1212194473, + projectionParams = 4041985547, + PRTOccSampler = 3756087939, + PtfxAlphaMapSampler = 2528190781, + PtfxDepthMapSampler = 3549846349, + PuddleBumpSampler = 644999851, + PuddleMaskSampler = 1899494261, + PuddlePlayerBumpSampler = 375060758, + QuadAlpha = 319478650, + QuadPosition = 4152407657, + QuadScale = 876246817, + QuadTexCoords = 2382487901, + QualitySubpix = 1192820550, + radialBlurCenter = 265875256, + RadialBlurSampler = 6871558, + radialBlurSampleScale = 1978511676, + radialBlurScale = 847338530, + radialBlurTextureStep = 3637740945, + RadialFadeArea = 3417034203, + RadialFadeTime = 820208297, + RadialWaveParam = 4020440334, + //radius = 1337695475, + RainNormalControls = 2413728713, + RainNormalSampler = 205121072, + RawInstanceBuffer = 2533822745, + rcpFrame = 3616804746, + RedOff = 550595403, + reductionDepthTexture = 156102219, + ReductionOutputTexture = 3090928251, + RefBlurMapSampler = 553137719, + ReflectanceSampler = 2024624668, + reflectivePower = 1002989215, + reflectivePowerED = 680514554, + ReflectTextureSampler = 2975449189, + refMipBlurParams = 309170118, + RefMipBlurSampler = 3559513422, + RefractionMapTexSampler = 3189040505, + RefractSampler = 2398824821, + RenderCubeMapSampler = 3123859691, + RenderMapPointSampler = 1552806584, + RenderMapPointSamplerMSAA = 840576025, + RenderPointMapINT = 3218359854, + RenderPointMapINTParam = 945456412, + RenderTargetSize = 2592035668, + RenderTexArray = 183558417, + RenderTexArraySampler = 1776075411, + RenderTexFmask = 334637039, + RenderTexMSAA = 2388364099, + RenderTexMSAAINT = 1120019968, + RenderTexMSAAParam = 445950974, + RESERVE_VS_CONST_c253 = 888979958, + RESERVE_VS_CONST_c254 = 572824646, + RESERVE_VS_CONST_c255 = 3578071436, + ResolvedDepthSampler = 870591330, + ResolvedDepthTexture = 1168394501, + Result = 1204638111, + rimAmount = 3950947166, + rimPower = 1017175370, + RippleBumpiness = 3108440880, + RippleData = 1154845288, + RippleScale = 3553443429, + RippleScaleOffset = 1931187426, + RippleSpeed = 1172914979, + ropeColor = 3402942199, + samp = 4292969706, + sampFiltered = 200703167, + sampleAngle = 1030071922, + sampleScale = 65527032, + Scale_ = 1342385372, + ScaleIn = 1489667163, + scalerLum = 1241172112, + ScanlineFilterParams = 3994711222, + ScreenBlurFade = 337464727, + ScreenCenter = 2855930302, + screenRes = 2982944708, + ScreenRez = 1216400687, + ScreenSizeHalfScale = 3116016449, + SeamTextureSampler = 1888072213, + seeThroughColorFar = 3831201608, + seeThroughColorNear = 3012901639, + seeThroughColorVisibleBase = 2159046948, + seeThroughColorVisibleWarm = 3370209405, + seeThroughParams = 4084639067, + SegmentSize = 2511004421, + SelfShadowing = 1840833647, + SfxWindSampler3D = 2060224441, + shader_cableAmbient = 2538368771, + shader_cableDiffuse = 1793087594, + shader_cableDiffuse2 = 115414613, + shader_cableEmissive = 132015748, + shader_fadeExponent = 2415019593, + shader_radiusScale = 2225356731, + shader_windAmount = 33262047, + shaderVariables = 2308502112, + ShadowFacingOffset = 2069856698, + ShadowFalloff = 1293272419, + shadowmap_res = 4230725802, + shadowMapSamp = 4212336983, + shadowParams2 = 2293499745, + skinColourTweak = 2856526403, + SkinParams = 441924618, + SkyColor = 1706854363, + SkyMapSampler = 2000097477, + skyPlaneColor = 3575965978, + skyPlaneParams = 2005428036, + smallCloudColorHdr = 1741381730, + smallCloudColorXHdrIntensity = 2180964324, + smallCloudConstants = 376734756, + SmartBlitCubeMapSampler = 4204135808, + SmartBlitCubeMapTexture = 712004116, + SmartBlitSampler = 909202272, + SmartBlitTexture = 4234899854, + SmokeParams = 2945162076, + SmokeSampler = 2479196183, + SnowSampler = 3153629680, + SnowSampler0 = 43291740, + SnowSampler1 = 296170113, + SoakFrameInfo = 2322806119, + //Softness = 187712958, //softness is already in the list, used by types other than shaders! + source = 572563616, + SpecDesaturateExponent = 3019471088, + SpecDesaturateIntensity = 716647240, + SpecExp = 191070201, + specFalloffAdjust = 227128491, + specFresnelExp = 1058370591, + specFresnelMax = 4192555480, + specFresnelMin = 1243102889, + SpecIntensity = 3710484485, + specIntensityAdjust = 4171608282, + specMapExpMask = 1709596004, + specMapIntMask = 4279333149, + specMapReflectMask = 3348420270, + SpecSampler = 1619499462, + SpecSampler_layer01 = 2048257998, + SpecSampler_layer23 = 3596135066, + specTexTileUV = 1430901041, + specular2Color = 685871723, + specular2Color_DirLerp = 2732605880, + specular2ColorIntensity = 3929351910, + specular2ColorIntensityED = 1998056897, + specular2ColorIntensityRE = 4172410899, + specular2Factor = 629012244, + specular2FactorED = 3425067163, + specularColorFactor = 1212833469, + specularColorFactor1 = 475502710, + specularColorFactor2 = 1361248780, + specularColorFactor3 = 1060953664, + specularColorFactorED = 1250428158, + specularFactor = 376311761, + specularFactor1 = 1627805193, + specularFactor2 = 2405249722, + specularFactor3 = 3075146389, + specularFactorED = 2497120655, + SpecularFalloff = 3957040118, + specularFalloffMult = 2272544384, + specularFalloffMultSpecMap = 2748867194, + specularFresnel = 666481402, + SpecularIntensity = 2841625909, + specularIntensityMult = 4095226703, + specularIntensityMultSpecMap = 1058366663, + specularNoiseMapUVScaleFactor = 3472765508, + SpecularPower = 2313518026, + speedConstants = 4031543803, + sphereReflectionSkyIntensity = 798112437, + SplatterFrameInfo = 1795230185, + srcTextureSize = 2371438916, + sslrCenter = 2233700119, + sslrParams = 2393555267, + SSLRSampler = 362115574, + StarFieldBrightness = 257351982, + starfieldIntensity = 1720801864, + StarFieldSampler = 4148544921, + StarFieldUVRepeat = 2211182669, + StarThreshold = 2069166037, + StencilCopy = 2849038798, + StencilCopySampler = 2084502919, + StencilCopyTexture = 526908546, + StencilTech = 471113370, + StippleSampler = 3178703610, + StubbleControl = 3996109161, + SubColor = 3318550136, + SubScatWidth = 993622972, + SubScatWrap = 511449331, + SubsurfaceColor = 1759569064, + SubsurfaceIntensity = 1096960668, + SubsurfaceRollOff = 3870878664, + SubViewportParams = 2820867500, + SunAxias = 2561150543, + SunCentre = 240054980, + sunColor = 891485471, + sunColorHdr = 1049428866, + sunColour = 1204497173, + sunConstants = 1546824331, + sunDirection = 2607379178, + sunDiscColor = 3557539369, + sunDiscColorHdr = 1079908950, + SunElevation = 569130658, + sunHdrIntensity = 3152536124, + sunPosition = 2950046911, + SunRaysParams = 291571442, + SunsetColor = 2702399089, + SunSize = 1478210724, + SurfaceTextureSampler = 3864743319, + SweatMapSampler = 2330958813, + switchOn = 3150944317, + targetSize = 1880392259, + targetSizeParam = 1053269285, + TearGasParams = 1288904305, + TerrainGridCentrePos = 3625956620, + TerrainGridForward = 1519085164, + TerrainGridHighHeightCol = 580500403, + TerrainGridLowHeightCol = 2936084960, + TerrainGridMidHeightCol = 2606299729, + TerrainGridParams = 1298168495, + TerrainGridParams2 = 3179684830, + TerrainGridRight = 1294931141, + tessellationMultiplier = 1934793340, + TexelSize = 3160646551, + Texm = 169731954, + TextureClamp = 812052183, + TextureGrassSampler = 4087226378, + TextureNoWrapSampler = 2957556365, + textureSamp = 485865047, + TextureSampler = 726757629, + TextureSampler_layer0 = 3576369631, + TextureSampler_layer1 = 606121937, + TextureSampler_layer2 = 831736502, + TextureSampler_layer3 = 2025281789, + TextureSampler_layer4 = 235963313, + TextureSampler_layer5 = 1429049834, + TextureSampler_layer6 = 1784855636, + TextureSampler2 = 90460676, + TextureSamplerDiffPal = 2878898974, + TextureSize = 3986548189, + TiledLightingSampler = 3579496475, + TimeOfDay = 1778950238, + TintBlendAmount = 481228442, + tintBlendLayer0 = 549865893, + tintBlendLayer1 = 3618355041, + tintBlendLayer2 = 3305181708, + tintBlendLayer3 = 4225662918, + tintBumpiness = 3412667425, + tintBumpSampler = 3461703736, + TintIntensity = 3676759262, + TintPaletteSampler = 4131954791, + tintPaletteSelector = 4258764495, + tintSampler = 1530343050, + tonemapColorFilterParams0 = 324960120, + tonemapColorFilterParams1 = 48979602, + TonemapParams = 2402343587, + TopCloudBiasDetailThresholdHeight = 2470194715, + TopCloudColor = 2654156795, + TopCloudDetail = 3891329052, + TopCloudHeight = 1826174990, + TopCloudLight = 1738437051, + TopCloudThreshold = 1907493970, + topLum = 2532426199, + TotalElapsedTime = 3838297418, + TrackAnimUV = 3759799674, + TransColor = 2460231751, + TransparentDstMapSampler = 2450925918, + TransparentSrcMap = 2768420156, + TransparentSrcMapSampler = 3675757750, + TransPos = 3580147959, + TransTex0 = 719147892, + TransTex1 = 1023997899, + TransTex2 = 88705101, + treeLod2Normal = 1105633214, + treeLod2Params = 1951298816, + txABC_Texture = 737921561, + txCOC_Texture = 849209715, + txX_Texture = 2443058410, + txYn_Texture = 314367857, + tyreDeformParams = 1573146290, + tyreDeformParams2 = 4085683888, + tyreDeformSwitchOn = 1318515464, + UIColor = 2438354415, + UIColorXformOffset = 805638785, + UIColorXformScale = 1696850869, + UIPosMtx = 2371642382, + UIPremultiplyAlpha = 653605664, + UITex0Mtx = 1320157902, + UITex1Mtx = 2219459259, + UITexture0 = 3890278027, + UITexture1 = 3587000932, + umGlobalOverrideParams = 3341722211, + umGlobalParams = 570415642, + uMovementParams = 3156484982, + umTriWave1Params = 1002429420, + umTriWave2Params = 1181853954, + umTriWave3Params = 2191838184, + UnderLightStrength = 618284065, + unsharpAmount = 982234565, + UpdateOffset = 1690179723, + UpdateParams0 = 1210532871, + UpdateParams1 = 1947442147, + useTessellation = 1176544093, + UseTreeNormals = 3771895108, + UVScalar = 2343745306, + uvScales = 2395163223, + vBoneVelocitiesX = 58804251, + vBoneVelocitiesY = 2266287952, + vCustomData = 2809044919, + vecBatchAabbDelta = 2709975619, + vecBatchAabbMin = 1568822605, + vecCameraPos = 3890753729, + vecPlayerPos = 2050268192, + vehglassCrackTextureParams = 3043112491, + vehglassCrackTextureSampler = 3541769459, + Velocity1 = 1362920836, + Velocity2 = 1853341690, + VelocityBufferSampler = 415075366, + VelocityMapSampler = 3944176109, + VelocityTexSampler = 2305380067, + vHairParams = 4131157628, + viewProj = 1758764692, + viewToWorldProjectionParam = 3809745575, + VignettingColor = 587686680, + VignettingParams = 2870132669, + VisibleInstanceBuffer0 = 3815124047, + VisibleInstanceBuffer1 = 774685147, + VisibleInstanceBuffer2 = 443193943, + VisibleInstanceBuffer3 = 2592414350, + vNoiseParams = 1120961721, + vol_offsets = 2154022121, + VolumeSampler = 789275230, + vSkinSweat = 3181015961, + vSweatParams = 3596190507, + WaterBumpParams = 126236009, + waterColor = 4201563883, + WaterColorSampler = 1938107181, + waterColour = 217812784, + WaterFogFadeColor = 93338982, + waterfogPtfxParams = 1185901400, + WaterHeight = 276101176, + waterIntensity = 3098236963, + waterReflectionScale = 386931249, + waterReflectionSkyIntensity = 4202734524, + waterRenderSimParam = 3115418423, + WaterRippleSampler = 3870579404, + waterSimParam = 1441798312, + waterSimParams1 = 764072840, + waterSimParams2 = 2978995088, + WaterSurfaceSampler = 4239336251, + waterTexResValue = 1128648105, + WaveMovement = 683816830, + WaveOffset = 2296487471, + WestColor = 2977103135, + WetAnisotropicSpecular = 1297501138, + WetAnisotropicSpecularColour = 4244410187, + WetDarken = 3170546064, + wetnessMultiplier = 853385205, + WindGlobalParams = 208642390, + WindStr = 3237952635, + WoundFrameInfo = 2347313451, + wrapAmount = 477869607, + wrapLigthtingTerm = 850731621, + WrinkleMaskSampler_0 = 2261465245, + WrinkleMaskSampler_1 = 3567506505, + WrinkleMaskSampler_2 = 2959477710, + WrinkleMaskSampler_3 = 3181913682, + WrinkleMaskSampler_4 = 199377605, + WrinkleMaskSampler_5 = 498853496, + wrinkleMaskStrengths0 = 3696993600, + wrinkleMaskStrengths1 = 3993356436, + wrinkleMaskStrengths2 = 9399719, + wrinkleMaskStrengths3 = 1226342076, + WrinkleSampler_A = 2285332697, + WrinkleSampler_B = 163310560, + YPlaneSampler = 2291309475, + YUVtoRGB = 361269406, + zenithColor = 1379881353, + zenithConstants = 2801684, + zenithTransitionColor = 3025743240, + ZoomBlurMaskSize = 1914884772, + ZoomFocusDistance = 2687037299, + zShift = 2743864906, + zShiftScale = 273550094, + + + + + + + + + + + + //CEntityDef = 0xce501483, + //CMapData = 0xd3593fa6, + //CBaseArchetypeDef = 0x82d6fc83, + //CTimeArchetypeDef = 0x76B0C56C, + //CTimeCycleModifier = 0x674f9350, + //CExtensionDefAudioCollisionSettings = 0x15deda27, + //CExtensionDefAudioEmitter = 0x2604683b, + //CExtensionDefParticleEffect = 0x3a26e5e1, + //CMapTypes = 0xd98bb561, + //CExtensionDefLadder = 0x821d5421, + //CExtensionDefBuoyancy = 0x2CB3D4E3, + //CExtensionDefSpawnPoint = 0xC4B2F638, + //CCarGen = 1860713439, + //CExtensionDefExplosionEffect = 104349545, + //CMloInstanceDef = 164374718, + //CMloRoomDef = 186126833, + //CExtensionDefDoor = 1965932561, + //CExtensionDefProcObject = 2565191912, + //CMloPortalDef = 2572186314, + //CExtensionDefSpawnPointOverride = 2716862120, + //CExtensionDefLightShaft = 2718997053, + //CMloArchetypeDef = 273704021, + //CMloEntitySet = 3601308153, + //CExtensionDefExpression = 3870521079, + //CLightAttrDef = 4115341947, + //CExtensionDefWindDisturbance = 569228403, + //CExtensionDefLightEffect = 663891011, + //CMloTimeCycleModifier = 807246248, + //rage__phVerletClothCustomBounds = 847348117, + + //SectionUNKNOWN1 = 1701774085, //cloth CollisionData (child of rage__phVerletClothCustomBounds) + ////SectionUNKNOWN2 = 1185771007, //CCompositeEntityType + //SectionUNKNOWN3 = 1980345114, + ////SectionUNKNOWN4 = 2085051229, + //SectionUNKNOWN5 = 2741784237, //occludeModels + ////SectionUNKNOWN6 = 3985044770, + //SectionUNKNOWN7 = 975711773, //boxOccluders + //SectionUNKNOWN8 = 3430328684,//0xCC76A96C, + VECTOR3 = 3805007828,//0xe2cbcfd4, //this hash isn't correct, but is used in CDistantLODLight + + HASH = 0x4a, + STRING = 0x10, + POINTER = 0x7, + USHORT = 0x13, + UINT = 0x15, + ARRAYINFO = 0x100, + + BYTE = 17, + FLOAT = 33, //0x21 + + VECTOR4 = 0x33, //(was SectionUNKNOWN12) + + + PsoPOINTER = 12, + + + + CCompositeEntityType = 1185771007, + scaleXY = 2627937847, + scaleZ = 284916802, + numChildren = 2793909385, + childLodDist = 3398912973, + portals = 2314725778, + entitySets = 1169996080, + timeFlags = 2248791340, + rage__spdAABB = 4084721864, + rage__fwGrassInstanceListDef = 2085051229, + rage__fwGrassInstanceListDef__InstanceData = 3985044770, + rage__fwPropInstanceListDef = 3120863088, + NormalX = 3138065392, + NormalY = 273792636, + + CImapDependency = 3501026914, + CImapDependencies = 3240050401, + CItypDependencies = 1515605584, + CMapDataGroup = 3260758307, //PSO/YMF + Bounds = 3298223272, + HoursOnOff = 4190815249, + itypName = 2890158180, + packFileName = 4216494073, + itypDepArray = 2410949350, + + + + + + //dexyfex manual guessing + CScenarioPointRegion = 1492970064, + CScenarioPointContainer = 2380938603, + CScenarioPoint = 4103049490, + CScenarioChain = 871314709, + CScenarioChainingNode = 3340683255, + CScenarioChainingEdge = 4255409560, + Points = 702683191, + Chains = 3254907796, + rage__spdSphere = 1062159465, + EdgeIds = 934700563, + TypeNames = 3057471271, + GroupNames = 2506712617, + PedModelSetNames = 3020866217, + VehicleModelSetNames = 3827910541, + ModelSetId = 3361647288, + LookUps = 1097626284, + RequiredIMapNames = 1767860162, + + vPositionAndDirection = 4685037, + CScenarioEntityOverride = 4213733800, + EntityOverrides = 697469539, + EntityPosition = 642078041, + CScenarioPointCluster = 750308016, + Clusters = 3587988394, + ClusterSphere = 352461053, + iInterior = 1975994103, + iRequiredIMapId = 1229525587, + iTimeTillPedLeaves = 2296188475, + + + CPopGroupList = 738910261, + + CStreamingRequestFrame = 999226379, + + CVehicleWheel = 2964364979, + + + + + + //dav90 suggestions + AccelGrid = 3053155275, + NavMode = 859022269, + NavSpeed = 1419316113, + NodeIndexTo = 2851806039, + NodeIndexFrom = 3236798246, + CScenarioPointLookUps = 3019621867, + ANCHOR_MOUTH = 2032023579, + ANCHOR_LEFT_HAND = 100074042, + ANCHOR_RIGHT_HAND = 3693638868, + ANCHOR_HIP = 2778755006, + ANCHOR_LEFT_FOOT = 1100801960, + ANCHOR_RIGHT_FOOT = 1776231225, + mloFlags = 3590839912, + floorId = 2187650609, + timecycleName = 2724323497, + secondaryTimecycleName = 3255324828, + portalCount = 1105339827, + //exteriorVisibiltyDepth = 552849982, //not correct = spelling error? + attachedObjects = 2382704940, + roomFrom = 4101034749, + roomTo = 2607060513, + mirrorPriority = 1185490713, + audioOcclusion = 1093790004, + dataSize = 2442753371, + iCenterX = 48026296, + iCenterY = 896907229, + iCenterZ = 1597508449, + iLength = 2854610661, + iWidth = 168013536, + iHeight = 3485277993, + explosionName = 3301388915, + explosionTag = 2653034051, + explosionType = 3379115010, + cornerA = 3302595027, + cornerB = 2393877884, + cornerC = 2692731164, + cornerD = 4250372814, + directionAmount = 1441249296, + densityType = 235100599, + volumeType = 4021175589, + softness = 187712958, + disturbanceType = 3802708370, + radiusInner = 406390660, + radiusOuter = 1814053978, + minScale = 3662913353, + maxScale = 803384552, + objectHash = 1951307499, + LoadSavePoints = 3016741991, + MyPoints = 1170781136, + iProbability = 2974610960, + iScenarioGroup = 2180252673, + EntityType = 1374199246, + CStreamingRequestRecord = 135915278, + Frames = 419044527, + CommonSets = 4248405899, + NewStyle = 2333392588, + AddList = 327274266, + RemoveList = 3372321331, + CamPos = 357008256, + CamDir = 210316193, + Requests = 2743119154, + compInfos = 592652859, + propInfo = 2240851416, + propMask = 2932859459, + aTexData = 1251090986, + clothData = 2464583091, + distribution = 914976023, + inclusions = 2172318933, + aAnchors = 162345210, + expressionMods = 942761829, + texData = 4088935562, + renderFlags = 4239582912, + propFlags = 1066841901, + anchorId = 2731224028, + propId = 3817142252, + inclusionId = 1938349561, + exclusionId = 3819522186, + weaponSlot = 1912311826, + disableProjectileDriveby = 531190847, + disableDriveby = 3038752585, + NoSpawn = 2321493392, //scenario point flags enum values + TerritorialScenario = 763077056, + InWater = 3157896680, + OpenDoor = 2382141124, + ExtendedRange = 324643703, + ShortRange = 3717016373, + HighPriority = 3426447659, + IgnoreLoitering = 626032513, + //ZoomTransformInformations = 3304563391, //this one doesn't make sense + kOnlySp = 4171042740, //scenario spawn point availability enum + kOnlyMp = 549935372, + Direct = 1129153779, //scenario chain edge nav mode enum + NavMesh = 4272634460, + Roads = 177164187, + //METAL_SOLID_LADDER = 1101797524, + METAL_LIGHT_LADDER = 846330484, + CComponentInfo = 1866571721, + CAnchorProps = 2170383875, + CBlockDesc = 3072355914, + CClassNameOfItemType = 440716365, //array type for (PSO) MAP fields + + + + + //dilapidated list - from dav90 hash collider + ActivateVehicleSiren = 3401359988, + AerialVehiclePoint = 1653545417, + MoveFollowMaster = 3724117664, + + + + + //from junctions.xml -dexy + CJunctionTemplateArray = 313816480, + CJunctionTemplate = 2985578477, + Entries = 3580294544, + iFlags = 1490815345, + iNumJunctionNodes = 3730457984, + iNumEntrances = 3629382379, + iNumPhases = 4284697782, + iNumTrafficLightLocations = 2024774002, + fSearchDistance = 3543631740, + fPhaseOffset = 33051442, //from dav90 + vJunctionMin = 4254986313, + vJunctionMax = 2705763988, + vJunctionNodePositions = 1140501121, + Entrances = 2079778626, + PhaseTimings = 970330902, + TrafficLightLocations = 3688283693, + vNodePosition = 137333670, + iPhase = 1580401081, + fStoppingDistance = 4131936721, + fOrientation = 2674216667, + fAngleFromCenter = 253800508, + bCanTurnRightOnRedLight = 4189109284, + bLeftLaneIsAheadOnly = 15530841, + bRightLaneIsRightOnly = 1190125928, + iLeftFilterLanePhase = 478748718, + fStartTime = 1971943265, + fDuration = 3674620953, + iPosX = 681100199, + iPosY = 1574841905, + iPosZ = 176392061, + + + //from openIV + dependencies = 1013942340, + hdTextureDist = 2908576588, + clipDictionary = 424089489, + physicsDictionary = 3553040380, + priorityLevel = 647098393, + ambientOcclusionMultiplier = 415356295, + artificialAmbientOcclusion = 599844163, + tintValue = 1015358759, + contentFlags = 1785155637, + streamingExtentsMin = 3710026271, + streamingExtentsMax = 2720965429, + entitiesExtentsMin = 477478129, + entitiesExtentsMax = 1829192759, + containerLods = 2935983381, + boxOccluders = 3983590932, + occludeModels = 2132383965, + physicsDictionaries = 949589348, + instancedData = 2569067561, + carGenerators = 3254823756, + LODLightsSOA = 1774371066, + DistantLODLightsSOA = 2954466641, + Ao = 2996378564, + BatchAABB = 1859041902, + InstanceList = 470289337, + LodFadeStartDist = 2216273066, + LodInstFadeRange = 1405992723, + OrientToTerrain = 3341475578, + ImapLink = 2142127586, + PropInstanceList = 3551474528, + GrassInstanceList = 255292381, + numStreetLights = 3708891211, + category = 2052871693, + exportedBy = 1983184981, + StartImapFile = 2462971690, + EndImapFile = 2059586669, + PtFxAssetName = 2497993358, + punchInPhase = 3142377407, + punchOutPhase = 2164219370, + + AvailabilityInMpSp = 2932681318, + iTimeStartOverride = 591476992, + iTimeEndOverride = 2688038523, + TimeTillPedLeaves = 4073598194, + instances = 274177522, + flashiness = 3829693202, + lightType = 482065968, + groupId = 2501631252, + cullingPlane = 1689591312, + padding1 = 3180641850, + padding2 = 2346113727, + padding3 = 3521603295, + volIntensity = 689780512, + volSizeScale = 2029533327, + volOuterColour = 2283994062, + lightHash = 643049222, + volOuterIntensity = 3008198647, + coronaSize = 1705000075, + volOuterExponent = 2758849250, + lightFadeDistance = 1307926275, + shadowFadeDistance = 1944267876, + specularFadeDistance = 4150887048, + volumetricFadeDistance = 2066998816, + shadowNearClip = 954647178, + coronaIntensity = 2292363771, + coronaZBias = 2520359283, + coneInnerAngle = 1163671864, + coneOuterAngle = 4175029060, + extents = 759134656, + projectedTextureKey = 1076718994, + timeAndStateFlags = 3112418278, + coneOuterAngleOrCapExt = 3161894080, + + minExtents = 1731020657, + maxExtents = 2554806840, + + orientX = 735213009, + orientY = 979440342, + perpendicularLength = 124715667, + bodyColorRemap1 = 1429703670, + bodyColorRemap2 = 1254848286, + bodyColorRemap3 = 1880965569, + bodyColorRemap4 = 1719152247, + popGroup = 911358791, + + enableLimitAngle = 1979299226, + startsLocked = 3204572347, + canBreak = 2756786344, + doorTargetRatio = 770433283, + audioHash = 224069936, + + effectHash = 2982223448, + materialType = 932754174, + canGetOffAtTop = 564839673, + canGetOffAtBottom = 923729576, + + manifestFlags = 1683136603, + + AT_DRB = 1956121915, + AT_FRG = 2872363693, + AT_DWD = 474212588, + INTERIOR_DATA = 559321238, + + METAL_SOLID_LADDER = 1101797524, + + PRI_REQUIRED = 1943361227, + PRI_OPTIONAL_HIGH = 3993616791, + PRI_OPTIONAL_MEDIUM = 515598709, + PRI_OPTIONAL_LOW = 329627604, + + + ASSET_TYPE_UNINITIALIZED = 189734893, + ASSET_TYPE_FRAGMENT = 571047911, + ASSET_TYPE_DRAWABLE = 130075505, + ASSET_TYPE_DRAWABLEDICTIONARY = 1580165652, + ASSET_TYPE_ASSETLESS = 4161085041, + + + //openIV carcols.ymt + VehiclePlates = 593302648, + Textures = 1767854039, + TextureSetName = 539384795, + DiffuseMapName = 1085051633, + //NormalMapName = 2845714814, //already present + FontExtents = 1008020858, + MaxLettersOnPlate = 1247956775, + FontColor = 1707432934, + FontOutlineColor = 2386115193, + IsFontOutlineEnabled = 3610161521, + FontOutlineMinMaxDepth = 1248154675, + DefaultTexureIndex = 3080794991, + NumericOffset = 4285827253, + AlphabeticOffset = 1050521113, + SpaceOffset = 1314537973, + RandomCharOffset = 2935763181, + NumRandomChar = 3588975658, + Colors = 721554909, + metallicID = 2578478329, + audioColor = 1773594779, + audioPrefix = 2369251831, + audioColorHash = 2318773127, + audioPrefixHash = 319619186, + colorName = 3636206675, + MetallicSettings = 1425754958, + specInt = 583457853, + specFalloff = 4263701895, + specFresnel = 3304136448, + WindowColors = 923621137, + Sirens = 2599949557, + timeMultiplier = 1771951321, + lightFalloffMax = 154568665, + lightFalloffExponent = 1650161522, + lightInnerConeAngle = 1576817313, + lightOuterConeAngle = 3797248043, + lightOffset = 1620490850, + //textureName = 440050042, + sequencerBpm = 1335282710, + sequencer = 3240773244, + leftHeadLight = 649479127, + rightHeadLight = 1381853174, + leftTailLight = 1551657213, + rightTailLight = 3049986329, + leftHeadLightMultiples = 3399909735, + rightHeadLightMultiples = 3461946667, + leftTailLightMultiples = 4275157148, + rightTailLightMultiples = 2310746177, + useRealLights = 804083006, + delta = 1117510170, + syncToBpm = 43887647, + corona = 3191162493, + faceCamera = 992261783, + lightGroup = 2689509391, + scaleFactor = 3961827348, + light = 1118124053, + spotLight = 1568651848, + castShadows = 3640997727, + livery2Names = 3280812844, + GlobalVariationData = 4171652890, + xenonLightColor = 4198188279, + xenonCoronaColor = 4113209874, + xenonLightIntensityModifier = 849227792, + xenonCoronaIntensityModifier = 3145775573, + + + + + + + + } + + +} diff --git a/GameFiles/MetaTypes/MetaTypes.cs b/GameFiles/MetaTypes/MetaTypes.cs new file mode 100644 index 0000000..fcea455 --- /dev/null +++ b/GameFiles/MetaTypes/MetaTypes.cs @@ -0,0 +1,5459 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Xml; + +using TC = System.ComponentModel.TypeConverterAttribute; +using EXP = System.ComponentModel.ExpandableObjectConverter; +using CodeWalker.World; + +namespace CodeWalker.GameFiles +{ + + //this is a helper class for parsing the data. + public static class MetaTypes + { + + public static Dictionary EnumDict = new Dictionary(); + public static Dictionary StructDict = new Dictionary(); + + public static void Clear() + { + StructDict.Clear(); + } + + public static void EnsureMetaTypes(Meta meta) + { + + if (meta.EnumInfos != null) + { + foreach (MetaEnumInfo mei in meta.EnumInfos) + { + if (!EnumDict.ContainsKey(mei.EnumKey)) + { + EnumDict.Add(mei.EnumKey, mei); + } + else + { + MetaEnumInfo oldei = EnumDict[mei.EnumKey]; + if (!CompareMetaEnumInfos(oldei, mei)) + { + } + } + } + } + + if (meta.StructureInfos != null) + { + foreach (MetaStructureInfo msi in meta.StructureInfos) + { + if (!StructDict.ContainsKey(msi.StructureKey)) + { + StructDict.Add(msi.StructureKey, msi); + } + else + { + MetaStructureInfo oldsi = StructDict[msi.StructureKey]; + if (!CompareMetaStructureInfos(oldsi, msi)) + { + } + } + } + } + + } + + public static bool CompareMetaEnumInfos(MetaEnumInfo a, MetaEnumInfo b) + { + //returns true if they are the same. + + if (a.Entries.Length != b.Entries.Length) + { + return false; + } + + for (int i = 0; i < a.Entries.Length; i++) + { + if ((a.Entries[i].EntryNameHash != b.Entries[i].EntryNameHash) || + (a.Entries[i].EntryValue != b.Entries[i].EntryValue)) + { + return false; + } + } + + return true; + } + public static bool CompareMetaStructureInfos(MetaStructureInfo a, MetaStructureInfo b) + { + //returns true if they are the same. + + if (a.Entries.Length != b.Entries.Length) + { + return false; + } + + for (int i = 0; i < a.Entries.Length; i++) + { + if ((a.Entries[i].EntryNameHash != b.Entries[i].EntryNameHash) || + (a.Entries[i].DataOffset != b.Entries[i].DataOffset) || + (a.Entries[i].DataType != b.Entries[i].DataType)) + { + return false; + } + } + + return true; + } + + + public static string GetTypesString() + { + StringBuilder sbe = new StringBuilder(); + StringBuilder sbs = new StringBuilder(); + + sbe.AppendLine("//Enum infos"); + sbs.AppendLine("//Struct infos"); + + + foreach (var kvp in EnumDict) + { + var mei = kvp.Value; + string name = GetSafeName(mei.EnumNameHash, mei.EnumKey); + sbe.AppendLine("public enum " + name + " //Key:" + mei.EnumKey.ToString()); + sbe.AppendLine("{"); + foreach (var entry in mei.Entries) + { + string eename = GetSafeName(entry.EntryNameHash, (uint)entry.EntryValue); + sbe.AppendFormat(" {0} = {1},", eename, entry.EntryValue); + sbe.AppendLine(); + } + sbe.AppendLine("}"); + sbe.AppendLine(); + } + + foreach (var kvp in StructDict) + { + var msi = kvp.Value; + string name = GetSafeName(msi.StructureNameHash, msi.StructureKey); + sbs.AppendLine("public struct " + name + " //" + msi.StructureSize.ToString() + " bytes, Key:" + msi.StructureKey.ToString()); + sbs.AppendLine("{"); + for (int i = 0; i < msi.Entries.Length; i++) + { + var entry = msi.Entries[i]; + + if ((entry.DataOffset == 0) && (entry.EntryNameHash == MetaName.ARRAYINFO)) //referred to by array + { + } + else + { + string sename = GetSafeName(entry.EntryNameHash, (uint)entry.ReferenceKey); + string fmt = " public {0} {1}; //{2} {3}"; + + if (entry.DataType == MetaStructureEntryDataType.Array) + { + if (entry.ReferenceTypeIndex >= msi.Entries.Length) + { + } + else + { + var structentry = msi.Entries[entry.ReferenceTypeIndex]; + var typename = "Array_" + MetaStructureEntryDataTypes.GetCSharpTypeName(structentry.DataType); + sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry.ToString() + " {" + structentry.ToString() + "}"); + sbs.AppendLine(); + } + } + else if (entry.DataType == MetaStructureEntryDataType.Structure) + { + var typename = GetSafeName(entry.ReferenceKey, (uint)entry.ReferenceTypeIndex); + sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry.ToString()); + sbs.AppendLine(); + } + else + { + var typename = MetaStructureEntryDataTypes.GetCSharpTypeName(entry.DataType); + sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry); + sbs.AppendLine(); + } + + } + + + } + sbs.AppendLine("}"); + sbs.AppendLine(); + } + + + sbe.AppendLine(); + sbe.AppendLine(); + sbe.AppendLine(); + sbe.AppendLine(); + sbe.AppendLine(); + sbe.Append(sbs.ToString()); + + string result = sbe.ToString(); + + return result; + } + + + public static string GetTypesInitString(Meta meta) + { + StringBuilder sb = new StringBuilder(); + + foreach (var si in meta.StructureInfos) + { + sb.AppendFormat("return new MetaStructureInfo(MetaName.{0}, {1}, {2}, {3},", si.StructureNameHash, si.StructureKey, si.Unknown_8h, si.StructureSize); + sb.AppendLine(); + for (int i = 0; i < si.Entries.Length; i++) + { + var e = si.Entries[i]; + string refkey = "0"; + if (e.ReferenceKey != 0) + { + refkey = "MetaName." + e.ReferenceKey.ToString(); + } + sb.AppendFormat("new MetaStructureEntryInfo_s(MetaName.{0}, {1}, MetaStructureEntryDataType.{2}, {3}, {4}, {5})", e.EntryNameHash, e.DataOffset, e.DataType, e.Unknown_9h, e.ReferenceTypeIndex, refkey); + if (i < si.Entries.Length - 1) sb.Append(","); + sb.AppendLine(); + } + sb.AppendFormat(");"); + sb.AppendLine(); + } + + sb.AppendLine(); + + foreach (var ei in meta.EnumInfos) + { + sb.AppendFormat("return new MetaEnumInfo(MetaName.{0}, {1},", ei.EnumNameHash, ei.EnumKey); + sb.AppendLine(); + for (int i = 0; i < ei.Entries.Length; i++) + { + var e = ei.Entries[i]; + sb.AppendFormat("new MetaEnumEntryInfo_s(MetaName.{0}, {1})", e.EntryNameHash, e.EntryValue); + if (i < ei.Entries.Length - 1) sb.Append(","); + sb.AppendLine(); + } + sb.AppendFormat(");"); + sb.AppendLine(); + } + + + string str = sb.ToString(); + return str; + } + + + public static MetaStructureInfo GetStructureInfo(MetaName name) + { + //to generate structinfos + switch (name) + { + + /* YMAP types */ + case MetaName.rage__fwInstancedMapData: + return new MetaStructureInfo(MetaName.rage__fwInstancedMapData, 1836780118, 768, 48, + new MetaStructureEntryInfo_s(MetaName.ImapLink, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.rage__fwPropInstanceListDef), + new MetaStructureEntryInfo_s(MetaName.PropInstanceList, 16, MetaStructureEntryDataType.Array, 0, 1, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.rage__fwGrassInstanceListDef), + new MetaStructureEntryInfo_s(MetaName.GrassInstanceList, 32, MetaStructureEntryDataType.Array, 0, 3, 0) + ); + case MetaName.CLODLight: + return new MetaStructureInfo(MetaName.CLODLight, 2325189228, 768, 136, + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.VECTOR3), + new MetaStructureEntryInfo_s(MetaName.direction, 8, MetaStructureEntryDataType.Array, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.falloff, 24, MetaStructureEntryDataType.Array, 0, 2, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.falloffExponent, 40, MetaStructureEntryDataType.Array, 0, 4, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.timeAndStateFlags, 56, MetaStructureEntryDataType.Array, 0, 6, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.hash, 72, MetaStructureEntryDataType.Array, 0, 8, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.coneInnerAngle, 88, MetaStructureEntryDataType.Array, 0, 10, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.coneOuterAngleOrCapExt, 104, MetaStructureEntryDataType.Array, 0, 12, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.coronaIntensity, 120, MetaStructureEntryDataType.Array, 0, 14, 0) + ); + case MetaName.CDistantLODLight: + return new MetaStructureInfo(MetaName.CDistantLODLight, 2820908419, 768, 48, + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.VECTOR3), + new MetaStructureEntryInfo_s(MetaName.position, 8, MetaStructureEntryDataType.Array, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.RGBI, 24, MetaStructureEntryDataType.Array, 0, 2, 0), + new MetaStructureEntryInfo_s(MetaName.numStreetLights, 40, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.category, 42, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0) + ); + case MetaName.CBlockDesc: + return new MetaStructureInfo(MetaName.CBlockDesc, 2015795449, 768, 72, + new MetaStructureEntryInfo_s(MetaName.version, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.flags, 4, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.CharPointer, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.exportedBy, 24, MetaStructureEntryDataType.CharPointer, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.owner, 40, MetaStructureEntryDataType.CharPointer, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.time, 56, MetaStructureEntryDataType.CharPointer, 0, 0, 0) + ); + case MetaName.CMapData: + return new MetaStructureInfo(MetaName.CMapData, 3448101671, 1024, 512, + new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.parent, 12, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.flags, 16, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.contentFlags, 20, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.streamingExtentsMin, 32, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.streamingExtentsMax, 48, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.entitiesExtentsMin, 64, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.entitiesExtentsMax, 80, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.StructurePointer, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.entities, 96, MetaStructureEntryDataType.Array, 0, 8, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)372253349), + new MetaStructureEntryInfo_s(MetaName.containerLods, 112, MetaStructureEntryDataType.Array, 0, 10, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)975711773/*.SectionUNKNOWN7*/), + new MetaStructureEntryInfo_s(MetaName.boxOccluders, 128, MetaStructureEntryDataType.Array, 4, 12, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)2741784237/*.SectionUNKNOWN5*/), + new MetaStructureEntryInfo_s(MetaName.occludeModels, 144, MetaStructureEntryDataType.Array, 4, 14, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.physicsDictionaries, 160, MetaStructureEntryDataType.Array, 0, 16, 0), + new MetaStructureEntryInfo_s(MetaName.instancedData, 176, MetaStructureEntryDataType.Structure, 0, 0, MetaName.rage__fwInstancedMapData), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CTimeCycleModifier), + new MetaStructureEntryInfo_s(MetaName.timeCycleModifiers, 224, MetaStructureEntryDataType.Array, 0, 19, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CCarGen), + new MetaStructureEntryInfo_s(MetaName.carGenerators, 240, MetaStructureEntryDataType.Array, 0, 21, 0), + new MetaStructureEntryInfo_s(MetaName.LODLightsSOA, 256, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CLODLight), + new MetaStructureEntryInfo_s(MetaName.DistantLODLightsSOA, 392, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CDistantLODLight), + new MetaStructureEntryInfo_s(MetaName.block, 440, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CBlockDesc) + ); + case MetaName.CEntityDef: + return new MetaStructureInfo(MetaName.CEntityDef, 1825799514, 1024, 128, + new MetaStructureEntryInfo_s(MetaName.archetypeName, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.flags, 12, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.guid, 16, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.position, 32, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.rotation, 48, MetaStructureEntryDataType.Float_XYZW, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.scaleXY, 64, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.scaleZ, 68, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.parentIndex, 72, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.lodDist, 76, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.childLodDist, 80, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.lodLevel, 84, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)1264241711), + new MetaStructureEntryInfo_s(MetaName.numChildren, 88, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.priorityLevel, 92, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)648413703), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.StructurePointer, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.extensions, 96, MetaStructureEntryDataType.Array, 0, 13, 0), + new MetaStructureEntryInfo_s(MetaName.ambientOcclusionMultiplier, 112, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.artificialAmbientOcclusion, 116, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.tintValue, 120, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0) + ); + case MetaName.CTimeCycleModifier: + return new MetaStructureInfo(MetaName.CTimeCycleModifier, 2683420777, 1024, 64, + new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.minExtents, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.maxExtents, 32, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.percentage, 48, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.range, 52, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.startHour, 56, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.endHour, 60, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0) + ); + case MetaName.CCarGen: + return new MetaStructureInfo(MetaName.CCarGen, 2345238261, 1024, 80, + new MetaStructureEntryInfo_s(MetaName.position, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.orientX, 32, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.orientY, 36, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.perpendicularLength, 40, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.carModel, 44, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.flags, 48, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.bodyColorRemap1, 52, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.bodyColorRemap2, 56, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.bodyColorRemap3, 60, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.bodyColorRemap4, 64, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.popGroup, 68, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.livery, 72, MetaStructureEntryDataType.SignedByte, 0, 0, 0) + ); + case MetaName.CExtensionDefLightEffect: + return new MetaStructureInfo(MetaName.CExtensionDefLightEffect, 2436199897, 1024, 48, + new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.offsetPosition, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CLightAttrDef), + new MetaStructureEntryInfo_s(MetaName.instances, 32, MetaStructureEntryDataType.Array, 0, 2, 0) + ); + case MetaName.CLightAttrDef: + return new MetaStructureInfo(MetaName.CLightAttrDef, 2363260268, 768, 160, + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.posn, 8, MetaStructureEntryDataType.ArrayOfBytes, 0, 0, (MetaName)3), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.colour, 20, MetaStructureEntryDataType.ArrayOfBytes, 0, 2, (MetaName)3), + new MetaStructureEntryInfo_s(MetaName.flashiness, 23, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.intensity, 24, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.flags, 28, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.boneTag, 32, MetaStructureEntryDataType.SignedShort, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.lightType, 34, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.groupId, 35, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.timeFlags, 36, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.falloff, 40, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.falloffExponent, 44, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.cullingPlane, 48, MetaStructureEntryDataType.ArrayOfBytes, 0, 13, (MetaName)4), + new MetaStructureEntryInfo_s(MetaName.shadowBlur, 64, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.padding1, 65, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.padding2, 66, MetaStructureEntryDataType.SignedShort, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.padding3, 68, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.volIntensity, 72, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.volSizeScale, 76, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.volOuterColour, 80, MetaStructureEntryDataType.ArrayOfBytes, 0, 21, (MetaName)3), + new MetaStructureEntryInfo_s(MetaName.lightHash, 83, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.volOuterIntensity, 84, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.coronaSize, 88, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.volOuterExponent, 92, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.lightFadeDistance, 96, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.shadowFadeDistance, 97, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.specularFadeDistance, 98, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.volumetricFadeDistance, 99, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.shadowNearClip, 100, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.coronaIntensity, 104, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.coronaZBias, 108, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.direction, 112, MetaStructureEntryDataType.ArrayOfBytes, 0, 34, (MetaName)3), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.tangent, 124, MetaStructureEntryDataType.ArrayOfBytes, 0, 36, (MetaName)3), + new MetaStructureEntryInfo_s(MetaName.coneInnerAngle, 136, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.coneOuterAngle, 140, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.extents, 144, MetaStructureEntryDataType.ArrayOfBytes, 0, 40, (MetaName)3), + new MetaStructureEntryInfo_s(MetaName.projectedTextureKey, 156, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0) + ); + case MetaName.CExtensionDefSpawnPointOverride: + return new MetaStructureInfo(MetaName.CExtensionDefSpawnPointOverride, 2551875873, 1024, 64, + new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.offsetPosition, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ScenarioType, 32, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iTimeStartOverride, 36, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iTimeEndOverride, 37, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.Group, 40, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ModelSet, 44, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.AvailabilityInMpSp, 48, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)3573596290), + new MetaStructureEntryInfo_s(MetaName.Flags, 52, MetaStructureEntryDataType.IntFlags2, 0, 32, (MetaName)700327466), + new MetaStructureEntryInfo_s(MetaName.Radius, 56, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.TimeTillPedLeaves, 60, MetaStructureEntryDataType.Float, 0, 0, 0) + ); + case MetaName.CExtensionDefDoor: + return new MetaStructureInfo(MetaName.CExtensionDefDoor, 2671601385, 1024, 48, + new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.offsetPosition, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.enableLimitAngle, 32, MetaStructureEntryDataType.Boolean, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.startsLocked, 33, MetaStructureEntryDataType.Boolean, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.canBreak, 34, MetaStructureEntryDataType.Boolean, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.limitAngle, 36, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.doorTargetRatio, 40, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.audioHash, 44, MetaStructureEntryDataType.Hash, 0, 0, 0) + ); + case MetaName.rage__phVerletClothCustomBounds: + return new MetaStructureInfo(MetaName.rage__phVerletClothCustomBounds, 2075461750, 768, 32, + new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)1701774085/*.SectionUNKNOWN1*/), + new MetaStructureEntryInfo_s(MetaName.CollisionData, 16, MetaStructureEntryDataType.Array, 0, 1, 0) + ); + case (MetaName)1701774085/*.SectionUNKNOWN1*/: + return new MetaStructureInfo((MetaName)1701774085/*.SectionUNKNOWN1*/, 2859775340, 1024, 96, + new MetaStructureEntryInfo_s(MetaName.OwnerName, 0, MetaStructureEntryDataType.CharPointer, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.Rotation, 16, MetaStructureEntryDataType.Float_XYZW, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.Position, 32, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.Normal, 48, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.CapsuleRadius, 64, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.CapsuleLen, 68, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.CapsuleHalfHeight, 72, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.CapsuleHalfWidth, 76, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.Flags, 80, MetaStructureEntryDataType.IntFlags2, 0, 32, (MetaName)3044470860) + ); + + + + /* SCENARIO types */ + case MetaName.CScenarioPointContainer: + return new MetaStructureInfo(MetaName.CScenarioPointContainer, 2489654897, 768, 48, + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CExtensionDefSpawnPoint), + new MetaStructureEntryInfo_s(MetaName.LoadSavePoints, 0, MetaStructureEntryDataType.Array, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioPoint), + new MetaStructureEntryInfo_s(MetaName.MyPoints, 16, MetaStructureEntryDataType.Array, 0, 2, 0) + ); + case (MetaName)4023740759: + return new MetaStructureInfo((MetaName)4023740759, 88255871, 768, 88, + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioChainingNode), + new MetaStructureEntryInfo_s(MetaName.Nodes, 0, MetaStructureEntryDataType.Array, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioChainingEdge), + new MetaStructureEntryInfo_s(MetaName.Edges, 16, MetaStructureEntryDataType.Array, 0, 2, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioChain), + new MetaStructureEntryInfo_s(MetaName.Chains, 32, MetaStructureEntryDataType.Array, 0, 4, 0) + ); + case MetaName.rage__spdGrid2D: + return new MetaStructureInfo(MetaName.rage__spdGrid2D, 894636096, 768, 64, + new MetaStructureEntryInfo_s((MetaName)860552138, 12, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)3824598937, 16, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)496029782, 20, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)3374647798, 24, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)2690909759, 44, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)3691675019, 48, MetaStructureEntryDataType.Float, 0, 0, 0) + ); + case MetaName.CScenarioPointLookUps: + return new MetaStructureInfo(MetaName.CScenarioPointLookUps, 2669361587, 768, 96, + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.TypeNames, 0, MetaStructureEntryDataType.Array, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.PedModelSetNames, 16, MetaStructureEntryDataType.Array, 0, 2, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.VehicleModelSetNames, 32, MetaStructureEntryDataType.Array, 0, 4, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.GroupNames, 48, MetaStructureEntryDataType.Array, 0, 6, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.InteriorNames, 64, MetaStructureEntryDataType.Array, 0, 8, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.RequiredIMapNames, 80, MetaStructureEntryDataType.Array, 0, 10, 0) + ); + case MetaName.CScenarioPointRegion: + return new MetaStructureInfo(MetaName.CScenarioPointRegion, 3501351821, 768, 376, + new MetaStructureEntryInfo_s(MetaName.VersionNumber, 0, MetaStructureEntryDataType.SignedInt, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.Points, 8, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioPointContainer), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioEntityOverride), + new MetaStructureEntryInfo_s(MetaName.EntityOverrides, 72, MetaStructureEntryDataType.Array, 0, 2, 0), + new MetaStructureEntryInfo_s((MetaName)3696045377, 96, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)4023740759), + new MetaStructureEntryInfo_s(MetaName.AccelGrid, 184, MetaStructureEntryDataType.Structure, 0, 0, MetaName.rage__spdGrid2D), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)3844724227, 248, MetaStructureEntryDataType.Array, 0, 6, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioPointCluster), + new MetaStructureEntryInfo_s(MetaName.Clusters, 264, MetaStructureEntryDataType.Array, 0, 8, 0), + new MetaStructureEntryInfo_s(MetaName.LookUps, 280, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioPointLookUps) + ); + case MetaName.CScenarioPoint: + return new MetaStructureInfo(MetaName.CScenarioPoint, 402442150, 1024, 64, + new MetaStructureEntryInfo_s(MetaName.iType, 21, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ModelSetId, 22, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iInterior, 23, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iRequiredIMapId, 24, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iProbability, 25, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)717991212, 26, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iTimeStartOverride, 27, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iTimeEndOverride, 28, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iRadius, 29, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iTimeTillPedLeaves, 30, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.iScenarioGroup, 32, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.Flags, 36, MetaStructureEntryDataType.IntFlags2, 0, 32, (MetaName)700327466), + new MetaStructureEntryInfo_s(MetaName.vPositionAndDirection, 48, MetaStructureEntryDataType.Float_XYZW, 0, 0, 0) + ); + case MetaName.CScenarioEntityOverride: + return new MetaStructureInfo(MetaName.CScenarioEntityOverride, 1271200492, 1024, 80, + new MetaStructureEntryInfo_s(MetaName.EntityPosition, 0, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.EntityType, 16, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CExtensionDefSpawnPoint), + new MetaStructureEntryInfo_s(MetaName.ScenarioPoints, 24, MetaStructureEntryDataType.Array, 0, 2, 0), + new MetaStructureEntryInfo_s((MetaName)538733109, 64, MetaStructureEntryDataType.Boolean, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)1035513142, 65, MetaStructureEntryDataType.Boolean, 0, 0, 0) + ); + case MetaName.CExtensionDefSpawnPoint: + return new MetaStructureInfo(MetaName.CExtensionDefSpawnPoint, 3077340721, 1024, 96, + new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.offsetPosition, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.offsetRotation, 32, MetaStructureEntryDataType.Float_XYZW, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.spawnType, 48, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.pedType, 52, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.group, 56, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.interior, 60, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.requiredImap, 64, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.availableInMpSp, 68, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)3573596290), + new MetaStructureEntryInfo_s(MetaName.probability, 72, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.timeTillPedLeaves, 76, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.radius, 80, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.start, 84, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.end, 85, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.flags, 88, MetaStructureEntryDataType.IntFlags2, 0, 32, (MetaName)700327466), + new MetaStructureEntryInfo_s(MetaName.highPri, 92, MetaStructureEntryDataType.Boolean, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.extendedRange, 93, MetaStructureEntryDataType.Boolean, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.shortRange, 94, MetaStructureEntryDataType.Boolean, 0, 0, 0) + ); + case MetaName.CScenarioChainingNode: + return new MetaStructureInfo(MetaName.CScenarioChainingNode, 1811784424, 1024, 32, + new MetaStructureEntryInfo_s(MetaName.Position, 0, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)2602393771, 16, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ScenarioType, 20, MetaStructureEntryDataType.Hash, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)407126079, 24, MetaStructureEntryDataType.Boolean, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)1308720135, 25, MetaStructureEntryDataType.Boolean, 0, 0, 0) + ); + case MetaName.CScenarioChainingEdge: + return new MetaStructureInfo(MetaName.CScenarioChainingEdge, 2004985940, 256, 8, + new MetaStructureEntryInfo_s(MetaName.NodeIndexFrom, 0, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.NodeIndexTo, 2, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.Action, 4, MetaStructureEntryDataType.ByteEnum, 0, 0, (MetaName)3609807418), + new MetaStructureEntryInfo_s(MetaName.NavMode, 5, MetaStructureEntryDataType.ByteEnum, 0, 0, (MetaName)3971773454), + new MetaStructureEntryInfo_s(MetaName.NavSpeed, 6, MetaStructureEntryDataType.ByteEnum, 0, 0, (MetaName)941086046) + ); + case MetaName.CScenarioChain: + return new MetaStructureInfo(MetaName.CScenarioChain, 2751910366, 768, 40, + new MetaStructureEntryInfo_s((MetaName)1156691834, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0), + new MetaStructureEntryInfo_s(MetaName.EdgeIds, 8, MetaStructureEntryDataType.Array, 0, 1, 0) + ); + case MetaName.rage__spdSphere: + return new MetaStructureInfo(MetaName.rage__spdSphere, 1189037266, 1024, 16, + new MetaStructureEntryInfo_s(MetaName.centerAndRadius, 0, MetaStructureEntryDataType.Float_XYZW, 0, 0, 0) + ); + case MetaName.CScenarioPointCluster: + return new MetaStructureInfo(MetaName.CScenarioPointCluster, 3622480419, 1024, 80, + new MetaStructureEntryInfo_s(MetaName.Points, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CScenarioPointContainer), + new MetaStructureEntryInfo_s(MetaName.ClusterSphere, 48, MetaStructureEntryDataType.Structure, 0, 0, MetaName.rage__spdSphere), + new MetaStructureEntryInfo_s((MetaName)1095875445, 64, MetaStructureEntryDataType.Float, 0, 0, 0), + new MetaStructureEntryInfo_s((MetaName)3129415068, 68, MetaStructureEntryDataType.Boolean, 0, 0, 0) + ); + + + + default: + return null; + } + } + public static MetaEnumInfo GetEnumInfo(MetaName name) + { + //to generate enuminfos + switch (name) + { + case (MetaName)1264241711: + return new MetaEnumInfo((MetaName)1264241711, 1856311430, + new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_HD, 0), + new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_LOD, 1), + new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_SLOD1, 2), + new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_SLOD2, 3), + new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_SLOD3, 4), + new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_ORPHANHD, 5), + new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_SLOD4, 6) + ); + case (MetaName)648413703: + return new MetaEnumInfo((MetaName)648413703, 2200357711, + new MetaEnumEntryInfo_s(MetaName.PRI_REQUIRED, 0), + new MetaEnumEntryInfo_s(MetaName.PRI_OPTIONAL_HIGH, 1), + new MetaEnumEntryInfo_s(MetaName.PRI_OPTIONAL_MEDIUM, 2), + new MetaEnumEntryInfo_s(MetaName.PRI_OPTIONAL_LOW, 3) + ); + case (MetaName)3573596290: + return new MetaEnumInfo((MetaName)3573596290, 671739257, + new MetaEnumEntryInfo_s(MetaName.kBoth, 0), + new MetaEnumEntryInfo_s(MetaName.kOnlySp, 1), + new MetaEnumEntryInfo_s(MetaName.kOnlyMp, 2) + ); + case (MetaName)700327466: + return new MetaEnumInfo((MetaName)700327466, 2814596095, + new MetaEnumEntryInfo_s(MetaName.IgnoreMaxInRange, 0), + new MetaEnumEntryInfo_s(MetaName.NoSpawn, 1), + new MetaEnumEntryInfo_s(MetaName.StationaryReactions, 2), + new MetaEnumEntryInfo_s((MetaName)3257836369, 3), + new MetaEnumEntryInfo_s((MetaName)2165609255, 4), + new MetaEnumEntryInfo_s(MetaName.ActivateVehicleSiren, 5), + new MetaEnumEntryInfo_s((MetaName)2626064871, 6), + new MetaEnumEntryInfo_s((MetaName)2004780781, 7), + new MetaEnumEntryInfo_s((MetaName)536864854, 8), + new MetaEnumEntryInfo_s((MetaName)3441065168, 9), + new MetaEnumEntryInfo_s(MetaName.AerialVehiclePoint, 10), + new MetaEnumEntryInfo_s(MetaName.TerritorialScenario, 11), + new MetaEnumEntryInfo_s((MetaName)3690227693, 12), + new MetaEnumEntryInfo_s((MetaName)1601179199, 13), + new MetaEnumEntryInfo_s((MetaName)2583152330, 14), + new MetaEnumEntryInfo_s((MetaName)3490317520, 15), + new MetaEnumEntryInfo_s(MetaName.InWater, 16), + new MetaEnumEntryInfo_s((MetaName)1269249358, 17), + new MetaEnumEntryInfo_s(MetaName.OpenDoor, 18), + new MetaEnumEntryInfo_s(MetaName.PreciseUseTime, 19), + new MetaEnumEntryInfo_s((MetaName)2247631388, 20), + new MetaEnumEntryInfo_s((MetaName)4100708934, 21), + new MetaEnumEntryInfo_s(MetaName.ExtendedRange, 22), + new MetaEnumEntryInfo_s(MetaName.ShortRange, 23), + new MetaEnumEntryInfo_s(MetaName.HighPriority, 24), + new MetaEnumEntryInfo_s(MetaName.IgnoreLoitering, 25), + new MetaEnumEntryInfo_s((MetaName)1524211135, 26), + new MetaEnumEntryInfo_s(MetaName.ResetNoCollisionOnCleanUp, 27), + new MetaEnumEntryInfo_s((MetaName)3304563391, 28), + new MetaEnumEntryInfo_s((MetaName)1111379709, 29), + new MetaEnumEntryInfo_s((MetaName)176469077, 30) + ); + case (MetaName)3044470860: + return new MetaEnumInfo((MetaName)3044470860, 1585854303, + new MetaEnumEntryInfo_s((MetaName)997866013, 0) + ); + + + case (MetaName)3609807418: + return new MetaEnumInfo((MetaName)3609807418, 3326075799, + new MetaEnumEntryInfo_s(MetaName.Move, 0), + new MetaEnumEntryInfo_s((MetaName)7865678, 1), + new MetaEnumEntryInfo_s(MetaName.MoveFollowMaster, 2) + ); + case (MetaName)3971773454: + return new MetaEnumInfo((MetaName)3971773454, 3016128742, + new MetaEnumEntryInfo_s(MetaName.Direct, 0), + new MetaEnumEntryInfo_s(MetaName.NavMesh, 1), + new MetaEnumEntryInfo_s(MetaName.Roads, 2) + ); + case (MetaName)941086046: + return new MetaEnumInfo((MetaName)941086046, 1112851290, + new MetaEnumEntryInfo_s((MetaName)3279574318, 0), + new MetaEnumEntryInfo_s((MetaName)2212923970, 1), + new MetaEnumEntryInfo_s((MetaName)4022799658, 2), + new MetaEnumEntryInfo_s((MetaName)1425672334, 3), + new MetaEnumEntryInfo_s((MetaName)957720931, 4), + new MetaEnumEntryInfo_s((MetaName)3795195414, 5), + new MetaEnumEntryInfo_s((MetaName)2834622009, 6), + new MetaEnumEntryInfo_s((MetaName)1876554076, 7), + new MetaEnumEntryInfo_s((MetaName)698543797, 8), + new MetaEnumEntryInfo_s((MetaName)1544199634, 9), + new MetaEnumEntryInfo_s((MetaName)2725613303, 10), + new MetaEnumEntryInfo_s((MetaName)4033265820, 11), + new MetaEnumEntryInfo_s((MetaName)3054809929, 12), + new MetaEnumEntryInfo_s((MetaName)3911005380, 13), + new MetaEnumEntryInfo_s((MetaName)3717649022, 14), + new MetaEnumEntryInfo_s((MetaName)3356026130, 15) + ); + + + default: + return null; + } + } + + + + + private static string GetSafeName(MetaName namehash, uint key) + { + string name = namehash.ToString(); + if (string.IsNullOrEmpty(name)) + { + name = "Unk_" + key; + } + if (!char.IsLetter(name[0])) + { + name = "Unk_" + name; + } + return name; + } + + + + + + public static byte[] ConvertToBytes(T item) where T : struct + { + int size = Marshal.SizeOf(typeof(T)); + int offset = 0; + byte[] arr = new byte[size]; + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(item, ptr, true); + Marshal.Copy(ptr, arr, 0, size); + Marshal.FreeHGlobal(ptr); + offset += size; + return arr; + } + public static byte[] ConvertArrayToBytes(params T[] items) where T : struct + { + if (items == null) return null; + int size = Marshal.SizeOf(typeof(T)); + int sizetot = size * items.Length; + byte[] arrout = new byte[sizetot]; + int offset = 0; + for (int i = 0; i < items.Length; i++) + { + byte[] arr = new byte[size]; + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(items[i], ptr, true); + Marshal.Copy(ptr, arr, 0, size); + Marshal.FreeHGlobal(ptr); + Buffer.BlockCopy(arr, 0, arrout, offset, size); + offset += size; + } + return arrout; + } + + + public static T ConvertData(byte[] data) where T : struct + { + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var h = handle.AddrOfPinnedObject(); + var r = Marshal.PtrToStructure(h); + handle.Free(); + return r; + } + public static T ConvertData(byte[] data, int offset) where T : struct + { + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var h = handle.AddrOfPinnedObject(); + var r = Marshal.PtrToStructure(h + offset); + handle.Free(); + return r; + } + public static T[] ConvertDataArray(byte[] data, int offset, int count) where T : struct + { + T[] items = new T[count]; + int itemsize = Marshal.SizeOf(typeof(T)); + for (int i = 0; i < count; i++) + { + int off = offset + i * itemsize; + items[i] = ConvertData(data, off); + } + return items; + } + public static T[] ConvertDataArray(Meta meta, MetaName name, Array_StructurePointer array) where T : struct + { + //return ConvertDataArray(meta, name, array.Pointer, array.Count1); + uint count = array.Count1; + if (count == 0) return null; + MetaPOINTER[] ptrs = GetPointerArray(meta, array); + if (ptrs == null) return null; + if (ptrs.Length < count) + { return null; } + + T[] items = new T[count]; + int itemsize = Marshal.SizeOf(typeof(T)); + int itemsleft = (int)count; //large arrays get split into chunks... + + //MetaName blocktype = 0; + for (int i = 0; i < count; i++) + { + var sptr = ptrs[i]; + int blocki = sptr.BlockID - 1; + int offset = sptr.ItemOffset * 16;//block data size... + if (blocki >= meta.DataBlocks.Count) + { continue; } + var block = meta.DataBlocks[blocki]; + + //if (blocktype == 0) + //{ blocktype = block.StructureNameHash; } + //else if (block.StructureNameHash != blocktype) + //{ } //not all the same type..! + + if (block.StructureNameHash != name) + { return null; } //type mismatch - don't return anything... + if ((offset < 0) || (block.Data == null) || (offset >= block.Data.Length)) + { continue; } + items[i] = ConvertData(block.Data, offset); + } + + return items; + } + public static T[] ConvertDataArray(Meta meta, MetaName name, Array_Structure array) where T : struct + { + return ConvertDataArray(meta, name, array.Pointer, array.Count1); + } + public static T[] ConvertDataArray(Meta meta, MetaName name, uint pointer, uint count) where T : struct + { + if (count == 0) return null; + + T[] items = new T[count]; + int itemsize = Marshal.SizeOf(typeof(T)); + int itemsleft = (int)count; //large arrays get split into chunks... + + uint ptrindex = (pointer & 0xFFF) - 1; + uint ptroffset = ((pointer >> 12) & 0xFFFFF); + var ptrblock = (ptrindex < meta.DataBlocks.Count) ? meta.DataBlocks[(int)ptrindex] : null; + if ((ptrblock == null) || (ptrblock.Data == null) || (ptrblock.StructureNameHash != name)) + { return null; } //no block or wrong block? shouldn't happen! + + int byteoffset = (int)ptroffset;// (ptroffset * 16 + ptrunkval); + int itemoffset = byteoffset / itemsize; + + int curi = 0; + while (itemsleft > 0) + { + int blockcount = ptrblock.DataLength / itemsize; + int itemcount = blockcount - itemoffset; + if (itemcount > itemsleft) + { itemcount = itemsleft; } //don't try to read too many items.. + for (int i = 0; i < itemcount; i++) + { + int offset = (itemoffset + i) * itemsize; + int index = curi + i; + items[index] = ConvertData(ptrblock.Data, offset); + } + itemoffset = 0; //start at beginning of next block.. + curi += itemcount; + itemsleft -= itemcount; + if (itemsleft <= 0) + { return items; }//all done! + ptrindex++; + ptrblock = (ptrindex < meta.DataBlocks.Count) ? meta.DataBlocks[(int)ptrindex] : null; + if ((ptrblock == null) || (ptrblock.Data == null)) + { break; } //not enough items..? + if (ptrblock.StructureNameHash != name) + { break; } //type mismatch.. + } + + return null; + + + + + + + + + + + #region old version + /* + //old version + + int currentp = (int)pointer - 1; + var datablock = ((currentp>=0)&&(currentp < meta.DataBlocks.Count)) ? meta.DataBlocks[currentp] : null; + if ((datablock == null) || (datablock.StructureNameHash != name)) //no match. look for the first match + { + currentp = -1; + for (int i = 0; i < meta.DataBlocks.Count; i++) + { + if (meta.DataBlocks[i].StructureNameHash == name) + { + currentp = i; + break; + } + } + if (currentp < 0) //couldn't find the right type. + { + return null; + } + } + + int curindex = 0; + while (itemsleft > 0) + { + if ((currentp >= meta.DataBlocks.Count) || (meta.DataBlocks[currentp].StructureNameHash != name)) + { + //wasn't enough data to read... problem.. (no next block to read from), just return whatever we got + T[] newitems = new T[curindex]; //have to return a smaller array.. + for (int n = 0; n < curindex; n++) newitems[n] = items[n]; + return newitems; + } + datablock = meta.DataBlocks[currentp]; + int curitemcount = datablock.DataLength / itemsize; + int totusedbytes = curitemcount * itemsize; + if (totusedbytes < datablock.DataLength) + { + //didn't use all the bytes in the block... potential problem! + if (totusedbytes == 0) + { + //not big enough for one item.. + if (curindex == 0) return null; //nothing read if on first iteration. + T[] newitems = new T[curindex]; //have to return a smaller array.. just return whatever we got + for (int n = 0; n < curindex; n++) newitems[n] = items[n]; + return newitems; + } + else //there was something... how to know if it's right though?? + { + //break; //just keep going.. at least parse what we got + } + } + + for (int i = 0; i < curitemcount; i++) + { + int offset = i * itemsize; + int index = curindex + i; + if (index >= items.Length) + { + //too much data! grow the output? + break; + } + items[index] = ConvertData(datablock.Data, offset); + } + + itemsleft -= curitemcount; + curindex += curitemcount; + currentp++; + } + + + + return items; + + */ + #endregion + } + + public static MetaPOINTER[] GetPointerArray(Meta meta, Array_StructurePointer array) + { + uint count = array.Count1; + if (count == 0) return null; + + MetaPOINTER[] ptrs = new MetaPOINTER[count]; + int ptrsize = Marshal.SizeOf(typeof(MetaPOINTER)); + //int itemsleft = (int)count; //large arrays get split into chunks... + uint ptr = array.Pointer; + int ptrindex = (int)(ptr & 0xFFF) - 1; + int ptroffset = (int)((ptr >> 12) & 0xFFFFF); + var ptrblock = (ptrindex < meta.DataBlocks.Count) ? meta.DataBlocks[ptrindex] : null; + if ((ptrblock == null) || (ptrblock.Data == null) || (ptrblock.StructureNameHash != MetaName.POINTER)) + { return null; } + + for (int i = 0; i < count; i++) + { + int offset = ptroffset + (i * ptrsize); + if (offset >= ptrblock.Data.Length) + { break; } + ptrs[i] = ConvertData(ptrblock.Data, offset); + } + + return ptrs; + } + + public static MetaHash[] GetHashArray(Meta meta, Array_uint array) + { + return ConvertDataArray(meta, MetaName.HASH, array.Pointer, array.Count1); + } + public static uint[] GetUintArray(Meta meta, Array_uint array) + { + return ConvertDataArray(meta, MetaName.UINT, array.Pointer, array.Count1); + } + public static ushort[] GetUshortArray(Meta meta, Array_ushort array) + { + return ConvertDataArray(meta, MetaName.USHORT, array.Pointer, array.Count1); + } + public static short[] GetShortArray(Meta meta, Array_ushort array) + { + return ConvertDataArray(meta, MetaName.USHORT, array.Pointer, array.Count1); + } + public static float[] GetFloatArray(Meta meta, Array_float array) + { + return ConvertDataArray(meta, MetaName.FLOAT, array.Pointer, array.Count1); + } + public static byte[] GetByteArray(Meta meta, Array_byte array) + { + var pointer = array.Pointer; + uint ptrindex = (pointer & 0xFFF) - 1; + uint ptroffset = ((pointer >> 12) & 0xFFFFF); + var ptrblock = (ptrindex < meta.DataBlocks.Count) ? meta.DataBlocks[(int)ptrindex] : null; + if ((ptrblock == null) || (ptrblock.Data == null))// || (ptrblock.StructureNameHash != name)) + { return null; } //no block or wrong block? shouldn't happen! + var count = array.Count1; + if ((ptroffset + count) > ptrblock.Data.Length) + { return null; } + byte[] data = new byte[count]; + Buffer.BlockCopy(ptrblock.Data, (int)ptroffset, data, 0, count); + return data; + } + + + public static T[] GetTypedDataArray(Meta meta, MetaName name) where T : struct + { + if ((meta == null) || (meta.DataBlocks == null)) return null; + + var datablocks = meta.DataBlocks.Data; + + MetaDataBlock startblock = null; + int startblockind = -1; + for (int i = 0; i < datablocks.Count; i++) + { + var block = datablocks[i]; + if (block.StructureNameHash == name) + { + startblock = block; + startblockind = i; + break; + } + } + if (startblock == null) + { + return null; //couldn't find the data. + } + + int count = 0; //try figure out how many items there are, from the block size(s). + int itemsize = Marshal.SizeOf(typeof(T)); + var currentblock = startblock; + int currentblockind = startblockind; + while (currentblock != null) + { + int blockitems = currentblock.DataLength / itemsize; + count += blockitems; + currentblockind++; + if (currentblockind >= datablocks.Count) break; //last block, can't go any further + currentblock = datablocks[currentblockind]; + if (currentblock.StructureNameHash != name) break; //not the right block type, can't go further + } + + if (count <= 0) + { + return null; //didn't find anything... + } + + return ConvertDataArray(meta, name, (uint)startblockind + 1, (uint)count); + } + public static T GetTypedData(Meta meta, MetaName name) where T : struct + { + foreach (var block in meta.DataBlocks) + { + if (block.StructureNameHash == name) + { + return MetaTypes.ConvertData(block.Data); + } + } + throw new Exception("Couldn't find " + name.ToString() + " block."); + } + public static string[] GetStrings(Meta meta) + { + //look for strings in the sectionSTRINGS data block(s) + + if ((meta == null) || (meta.DataBlocks == null)) return null; + + var datablocks = meta.DataBlocks.Data; + + MetaDataBlock startblock = null; + int startblockind = -1; + for (int i = 0; i < datablocks.Count; i++) + { + var block = datablocks[i]; + if (block.StructureNameHash == MetaName.STRING) + { + startblock = block; + startblockind = i; + break; + } + } + if (startblock == null) + { + return null; //couldn't find the strings data section. + } + + List strings = new List(); + StringBuilder sb = new StringBuilder(); + var currentblock = startblock; + int currentblockind = startblockind; + while (currentblock != null) + { + //read strings from the block. + + sb.Clear(); + int startindex = 0; + int endindex = 0; + var data = currentblock.Data; + for (int b = 0; b < data.Length; b++) + { + if (data[b] == 0) + { + startindex = endindex; + endindex = b; + if (endindex > startindex) + { + string str = Encoding.ASCII.GetString(data, startindex, endindex - startindex); + strings.Add(str); + endindex++; //start next string after the 0. + } + } + } + if (endindex != data.Length - 1) + { + startindex = endindex; + endindex = data.Length - 1; + if (endindex > startindex) + { + string str = Encoding.ASCII.GetString(data, startindex, endindex - startindex); + strings.Add(str); + } + } + + currentblockind++; + if (currentblockind >= datablocks.Count) break; //last block, can't go any further + currentblock = datablocks[currentblockind]; + if (currentblock.StructureNameHash != MetaName.STRING) break; //not the right block type, can't go further + } + + + if (strings.Count <= 0) + { + return null; //don't return empty array... + } + return strings.ToArray(); + } + public static string GetString(Meta meta, CharPointer ptr) + { + var blocki = (int)ptr.PointerDataIndex;// (ptr.Pointer & 0xFFF) - 1; + var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF; + if ((blocki < 0) || (blocki >= meta.DataBlocks.BlockLength)) + { return null; } + var block = meta.DataBlocks[blocki]; + if (block.StructureNameHash != MetaName.STRING) + { return null; } + //var byteoffset = offset * 16 + offset2; + var length = ptr.Count1; + var lastbyte = offset + length; + if (lastbyte >= block.DataLength) + { return null; } + string s = Encoding.ASCII.GetString(block.Data, offset, length); + + //if (meta.Strings == null) return null; + //if (offset < 0) return null; + //if (offset >= meta.Strings.Length) return null; + //string s = meta.Strings[offset]; + + return s; + } + + public static MetaWrapper[] GetExtensions(Meta meta, Array_StructurePointer ptr) + { + if (ptr.Count1 == 0) return null; + var result = new MetaWrapper[ptr.Count1]; + var extptrs = GetPointerArray(meta, ptr); + if (extptrs != null) + { + for (int i = 0; i < extptrs.Length; i++) + { + var extptr = extptrs[i]; + MetaWrapper ext = null; + var block = GetDataBlock(meta, extptr); + var h = block.StructureNameHash; + switch (h) + { + //archetype extension types + case MetaName.CExtensionDefParticleEffect: + ext = new MCExtensionDefParticleEffect();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefAudioCollisionSettings: + ext = new MCExtensionDefAudioCollisionSettings();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefAudioEmitter: + ext = new MCExtensionDefAudioEmitter();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefSpawnPoint: + ext = new MCExtensionDefSpawnPoint();// new MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefExplosionEffect: + ext = new MCExtensionDefExplosionEffect();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefLadder: + ext = new MCExtensionDefLadder();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefBuoyancy: + ext = new MCExtensionDefBuoyancy();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefExpression: + ext = new MCExtensionDefExpression();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefLightShaft: + ext = new MCExtensionDefLightShaft();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefWindDisturbance: + ext = new MCExtensionDefWindDisturbance();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefProcObject: + ext = new MCExtensionDefProcObject();// MetaExtension(h, GetData(block, extptr)); + break; + + //entity extension types + case MetaName.CExtensionDefLightEffect: + ext = new MCExtensionDefLightEffect();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefSpawnPointOverride: + ext = new MCExtensionDefSpawnPointOverride();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.CExtensionDefDoor: + ext = new MCExtensionDefDoor();// MetaExtension(h, GetData(block, extptr)); + break; + case MetaName.rage__phVerletClothCustomBounds: //rage__phVerletClothCustomBounds + ext = new Mrage__phVerletClothCustomBounds();// MetaExtension(h, GetData(block, extptr)); + break; + + default: + break; + } + + //string ts = GetTypesInitString(meta); + + if (ext != null) + { + ext.Load(meta, extptr); + } + if (i < result.Length) + { + result[i] = ext; + } + } + } + return result; + } + + public static MetaDataBlock GetDataBlock(Meta meta, MetaPOINTER ptr) + { + int blocki = ptr.BlockID - 1; + if ((blocki < 0) || (blocki >= meta.DataBlocks.Count)) + { return null; } + var block = meta.DataBlocks[blocki]; + return block; + } + public static int GetDataOffset(MetaDataBlock block, MetaPOINTER ptr) + { + if (block == null) return -1; + int offset = ptr.ItemOffset * 16;//block data size... + if (ptr.ExtraOffset != 0) + { } + //offset += (int)ptr.ExtraOffset; + if ((offset < 0) || (block.Data == null) || (offset >= block.Data.Length)) + { return -1; } + return offset; + } + public static T GetData(Meta meta, MetaPOINTER ptr) where T : struct + { + var block = GetDataBlock(meta, ptr); + var offset = GetDataOffset(block, ptr); + if (offset < 0) return new T(); + return ConvertData(block.Data, offset); + } + public static T GetData(MetaDataBlock block, MetaPOINTER ptr) where T : struct + { + var offset = GetDataOffset(block, ptr); + if (offset < 0) return new T(); + return ConvertData(block.Data, offset); + } + + + public static ushort SwapBytes(ushort x) + { + return (ushort)(((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8)); + } + public static uint SwapBytes(uint x) + { + // swap adjacent 16-bit blocks + x = (x >> 16) | (x << 16); + // swap adjacent 8-bit blocks + return ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8); + } + public static int SwapBytes(int x) + { + return (int)SwapBytes((uint)x); + } + public static ulong SwapBytes(ulong x) + { + // swap adjacent 32-bit blocks + x = (x >> 32) | (x << 32); + // swap adjacent 16-bit blocks + x = ((x & 0xFFFF0000FFFF0000) >> 16) | ((x & 0x0000FFFF0000FFFF) << 16); + // swap adjacent 8-bit blocks + return ((x & 0xFF00FF00FF00FF00) >> 8) | ((x & 0x00FF00FF00FF00FF) << 8); + } + public static float SwapBytes(float f) + { + var a = BitConverter.GetBytes(f); + Array.Reverse(a); + return BitConverter.ToSingle(a, 0); + } + public static Vector2 SwapBytes(Vector2 v) + { + var x = SwapBytes(v.X); + var y = SwapBytes(v.Y); + return new Vector2(x, y); + } + public static Vector3 SwapBytes(Vector3 v) + { + var x = SwapBytes(v.X); + var y = SwapBytes(v.Y); + var z = SwapBytes(v.Z); + return new Vector3(x, y, z); + } + public static Vector4 SwapBytes(Vector4 v) + { + var x = SwapBytes(v.X); + var y = SwapBytes(v.Y); + var z = SwapBytes(v.Z); + var w = SwapBytes(v.W); + return new Vector4(x, y, z, w); + } + } + + + + + [TC(typeof(EXP))] public abstract class MetaWrapper + { + public virtual string Name { get { return ToString(); } } + public abstract void Load(Meta meta, MetaPOINTER ptr); + public abstract MetaPOINTER Save(MetaBuilder mb); + } + + + + + + + //derived types - manually created (array & pointer structs) + + [TC(typeof(EXP))] public struct Array_StructurePointer //16 bytes - pointer for a structure pointer array + { + public uint Pointer { get; set; } + public uint Unk0 { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unk1 { get; set; } + + public uint PointerDataId { get { return (Pointer & 0xFFF); } } + public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } } + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Count1 = MetaTypes.SwapBytes(Count1); + Count2 = MetaTypes.SwapBytes(Count2); + Unk1 = MetaTypes.SwapBytes(Unk1); + } + public override string ToString() + { + return "Array_StructurePointer: " + PointerDataIndex.ToString() + " (" + Count1.ToString() + "/" + Count2.ToString() + ")"; + } + } + [TC(typeof(EXP))] public struct Array_Structure //16 bytes - pointer for a structure array + { + public uint Pointer { get; set; } + public uint Unk0 { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unk1 { get; set; } + + public uint PointerDataId { get { return (Pointer & 0xFFF); } } + public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } } + + + + public Array_Structure(uint ptr, int cnt) + { + Pointer = ptr; + Unk0 = 0; + Count1 = (ushort)cnt; + Count2 = Count1; + Unk1 = 0; + } + public Array_Structure(MetaBuilderPointer ptr) + { + Pointer = ptr.Pointer; + Unk0 = 0; + Count1 = (ushort)ptr.Length; + Count2 = Count1; + Unk1 = 0; + } + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Unk0 = MetaTypes.SwapBytes(Unk0); + Count1 = MetaTypes.SwapBytes(Count1); + Count2 = MetaTypes.SwapBytes(Count2); + Unk1 = MetaTypes.SwapBytes(Unk1); + } + public override string ToString() + { + return "Array_Structure: " + PointerDataIndex.ToString() + " (" + Count1.ToString() + "/" + Count2.ToString() + ")"; + } + } + [TC(typeof(EXP))] public struct Array_uint //16 bytes - pointer for a uint array + { + public uint Pointer { get; set; } + public uint Unk0 { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unk1 { get; set; } + + public uint PointerDataId { get { return (Pointer & 0xFFF); } } + public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } } + + + public Array_uint(uint ptr, int cnt) + { + Pointer = ptr; + Unk0 = 0; + Count1 = (ushort)cnt; + Count2 = Count1; + Unk1 = 0; + } + public Array_uint(MetaBuilderPointer ptr) + { + Pointer = ptr.Pointer; + Unk0 = 0; + Count1 = (ushort)ptr.Length; + Count2 = Count1; + Unk1 = 0; + } + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Unk0 = MetaTypes.SwapBytes(Unk0); + Count1 = MetaTypes.SwapBytes(Count1); + Count2 = MetaTypes.SwapBytes(Count2); + Unk1 = MetaTypes.SwapBytes(Unk1); + } + public override string ToString() + { + return "Array_uint: " + PointerDataIndex.ToString() + " (" + Count1.ToString() + "/" + Count2.ToString() + ")"; + } + } + [TC(typeof(EXP))] public struct Array_ushort //16 bytes - pointer for a ushort array + { + public uint Pointer { get; set; } + public uint Unk0 { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unk1 { get; set; } + + public uint PointerDataId { get { return (Pointer & 0xFFF); } } + public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } } + + + public Array_ushort(uint ptr, int cnt) + { + Pointer = ptr; + Unk0 = 0; + Count1 = (ushort)cnt; + Count2 = Count1; + Unk1 = 0; + } + public Array_ushort(MetaBuilderPointer ptr) + { + Pointer = ptr.Pointer; + Unk0 = 0; + Count1 = (ushort)ptr.Length; + Count2 = Count1; + Unk1 = 0; + } + + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Unk0 = MetaTypes.SwapBytes(Unk0); + Count1 = MetaTypes.SwapBytes(Count1); + Count2 = MetaTypes.SwapBytes(Count2); + Unk1 = MetaTypes.SwapBytes(Unk1); + } + public override string ToString() + { + return "Array_ushort: " + PointerDataIndex.ToString() + " (" + Count1.ToString() + "/" + Count2.ToString() + ")"; + } + } + [TC(typeof(EXP))] public struct Array_byte //16 bytes - pointer for a byte array + { + public uint Pointer { get; set; } + public uint Unk0 { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unk1 { get; set; } + + public uint PointerDataId { get { return (Pointer & 0xFFF); } } + public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } } + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Unk0 = MetaTypes.SwapBytes(Unk0); + Count1 = MetaTypes.SwapBytes(Count1); + Count2 = MetaTypes.SwapBytes(Count2); + Unk1 = MetaTypes.SwapBytes(Unk1); + } + public override string ToString() + { + return "Array_byte: " + PointerDataIndex.ToString() + " (" + Count1.ToString() + "/" + Count2.ToString() + ")"; + } + } + [TC(typeof(EXP))] public struct Array_float //16 bytes - pointer for a float array + { + public uint Pointer { get; set; } + public uint Unk0 { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unk1 { get; set; } + + public uint PointerDataId { get { return (Pointer & 0xFFF); } } + public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } } + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Unk0 = MetaTypes.SwapBytes(Unk0); + Count1 = MetaTypes.SwapBytes(Count1); + Count2 = MetaTypes.SwapBytes(Count2); + Unk1 = MetaTypes.SwapBytes(Unk1); + } + public override string ToString() + { + return "Array_float: " + PointerDataIndex.ToString() + " (" + Count1.ToString() + "/" + Count2.ToString() + ")"; + } + } + [TC(typeof(EXP))] public struct Array_Vector3 //16 bytes - pointer for a Vector3 array + { + public uint Pointer { get; set; } + public uint Unk0 { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unk1 { get; set; } + + public uint PointerDataId { get { return (Pointer & 0xFFF); } } + public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } } + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Unk0 = MetaTypes.SwapBytes(Unk0); + Count1 = MetaTypes.SwapBytes(Count1); + Count2 = MetaTypes.SwapBytes(Count2); + Unk1 = MetaTypes.SwapBytes(Unk1); + } + public override string ToString() + { + return "Array_Vector3: " + PointerDataIndex.ToString() + " (" + Count1.ToString() + "/" + Count2.ToString() + ")"; + } + } + [TC(typeof(EXP))] public struct CharPointer //16 bytes - pointer for a char array + { + public uint Pointer { get; set; } + public uint Unk0 { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unk1 { get; set; } + + public uint PointerDataId { get { return (Pointer & 0xFFF); } } + public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } } + + public CharPointer(uint ptr, int len) + { + Pointer = ptr; + Unk0 = 0; + Count1 = (ushort)len; + Count2 = Count1; + Unk1 = 0; + } + public CharPointer(MetaBuilderPointer ptr) + { + Pointer = ptr.Pointer; + Unk0 = 0; + Count1 = (ushort)ptr.Length; + Count2 = Count1; + Unk1 = 0; + } + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Unk0 = MetaTypes.SwapBytes(Unk0); + Count1 = MetaTypes.SwapBytes(Count1); + Count2 = MetaTypes.SwapBytes(Count2); + Unk1 = MetaTypes.SwapBytes(Unk1); + } + public override string ToString() + { + return "CharPointer: " + Pointer.ToString() + " (" + Count1.ToString() + "/" + Count2.ToString() + ")"; + } + } + [TC(typeof(EXP))] public struct DataBlockPointer //8 bytes - pointer to data block + { + public uint Ptr0 { get; set; } + public uint Ptr1 { get; set; } + + public uint PointerDataId { get { return (Ptr0 & 0xFFF); } } + public uint PointerDataIndex { get { return (Ptr0 & 0xFFF) - 1; } } + public uint PointerDataOffset { get { return ((Ptr0 >> 12) & 0xFFFFF); } } + + public override string ToString() + { + return "DataBlockPointer: " + Ptr0.ToString() + ", " + Ptr1.ToString(); + } + + public void SwapEnd() + { + Ptr0 = MetaTypes.SwapBytes(Ptr0); + Ptr1 = MetaTypes.SwapBytes(Ptr1); + } + } + + public struct ArrayOfUshorts3 //array of 3 bytes + { + public ushort u0, u1, u2; + public override string ToString() + { + return u0.ToString() + ", " + u1.ToString() + ", " + u2.ToString(); + } + } + public struct ArrayOfBytes3 //array of 3 bytes + { + public byte b0,b1,b2; + public override string ToString() + { + return b0.ToString() + ", " + b1.ToString() + ", " + b2.ToString(); + } + } + public struct ArrayOfBytes4 //array of 4 bytes + { + public byte b0,b1,b2,b3; + public override string ToString() + { + return b0.ToString() + ", " + b1.ToString() + ", " + b2.ToString() + ", " + b3.ToString(); + } + } + public struct ArrayOfBytes5 //array of 5 bytes + { + public byte b0, b1, b2, b3, b4; + } + public struct ArrayOfBytes6 //array of 6 bytes + { + public byte b0, b1, b2, b3, b4, b5; + } + public struct ArrayOfBytes12 //array of 12 bytes + { + public byte b00, b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11; + } + public struct ArrayOfChars64 //array of 64 chars (bytes) + { + public byte + b00, b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, + b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33, b34, b35, b36, b37, b38, b39, + b40, b41, b42, b43, b44, b45, b46, b47, b48, b49, b50, b51, b52, b53, b54, b55, b56, b57, b58, b59, + b60, b61, b62, b63; + public override string ToString() + { + byte[] bytes = + { + b00, b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, + b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33, b34, b35, b36, b37, b38, b39, + b40, b41, b42, b43, b44, b45, b46, b47, b48, b49, b50, b51, b52, b53, b54, b55, b56, b57, b58, b59, + b60, b61, b62, b63 + }; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + if (bytes[i] == 0) break; + sb.Append((char)bytes[i]); + } + return sb.ToString(); + } + } + + public struct MetaVECTOR3 //12 bytes, Key:2751397072 + { + public float x { get; set; } //0 0: Float: 0: x + public float y { get; set; } //4 4: Float: 0: y + public float z { get; set; } //8 8: Float: 0: z + + public override string ToString() + { + return x.ToString() + ", " + y.ToString() + ", " + z.ToString(); + } + + public Vector3 ToVector3() + { + return new Vector3(x, y, z); + } + } + + public struct MetaPOINTER //8 bytes - pointer to data item //SectionUNKNOWN10 + { + public ushort BlockID { get; set; } //1-based ID + public ushort ItemOffset { get; set; } //byte offset / 16 + public uint ExtraOffset { get; set; } + + public MetaPOINTER(ushort blockID, ushort itemOffset, uint extra) + { + BlockID = blockID; + ItemOffset = itemOffset; + ExtraOffset = extra; + } + + public override string ToString() + { + return BlockID.ToString() + ", " + ItemOffset.ToString() + ", " + ExtraOffset.ToString(); + } + } + + + + //generated enums + + //Enum infos + + [Flags] public enum Unk_700327466 //SCENARIO point flags / extension spawn point flags + : int //Key:2814596095 + { + IgnoreMaxInRange = 1,//0, + NoSpawn = 2,//1, + StationaryReactions = 4,//2, + Unk_3257836369 = 8,//3, + Unk_2165609255 = 16,//4, + ActivateVehicleSiren = 32,//5, + Unk_2626064871 = 64,//6, // AggressiveVehicleDriving ? + Unk_2004780781 = 128,//7, + Unk_536864854 = 256,//8, + Unk_3441065168 = 512,//9, + AerialVehiclePoint = 1024,//10, + TerritorialScenario = 2048,//11, + Unk_3690227693 = 4096,//12, + Unk_1601179199 = 8192,//13, + Unk_2583152330 = 16384,//14, + Unk_3490317520 = 32768,//15, + InWater = 65536,//16, + Unk_1269249358 = 131072,//17, // AllowInvestigation ? + OpenDoor = 262144,//18, + PreciseUseTime = 524288,//19, + Unk_2247631388 = 1048576,//20, + Unk_4100708934 = 2097152,//21, + ExtendedRange = 4194304,//22, + ShortRange = 8388608,//23, + HighPriority = 16777216,//24, + IgnoreLoitering = 33554432,//25, + Unk_1524211135 = 67108864,//26, // UseSearchlight ? + ResetNoCollisionOnCleanUp = 134217728,//27, + Unk_3304563391 = 268435456,//28, + Unk_1111379709 = 536870912,//29, + Unk_176469077 = 1073741824,//30, // IgnoreWeatherRestrictions ? + } + + public enum Unk_3573596290 //SCENARIO Spawn point availability availableInMpSp + : int //Key:671739257 + { + kBoth = 0, + kOnlySp = 1, + kOnlyMp = 2, + } + + public enum Unk_3609807418 //SCENARIO (Path) Edge Action + : byte //Key:3326075799 + { + Move = 0, + Unk_7865678 = 1, + MoveFollowMaster = 2, + } + + public enum Unk_3971773454 //SCENARIO (Path) Edge nav mode + : byte //Key:3016128742 + { + Direct = 0, + NavMesh = 1, + Roads = 2, + } + + public enum Unk_941086046 //SCENARIO (Path) Edge nav speed + : byte //Key:1112851290 + { + Unk_00_3279574318 = 0, + Unk_01_2212923970 = 1, + Unk_02_4022799658 = 2, + Unk_03_1425672334 = 3, + Unk_04_957720931 = 4, + Unk_05_3795195414 = 5, + Unk_06_2834622009 = 6, + Unk_07_1876554076 = 7, + Unk_08_698543797 = 8, + Unk_09_1544199634 = 9, + Unk_10_2725613303 = 10, + Unk_11_4033265820 = 11, + Unk_12_3054809929 = 12, + Unk_13_3911005380 = 13, + Unk_14_3717649022 = 14, + Unk_15_3356026130 = 15, + } + + public enum Unk_1991964615 //archetype assetType + : int //Key:1866031916 + { + ASSET_TYPE_UNINITIALIZED = 0, //189734893 + ASSET_TYPE_FRAGMENT = 1, //571047911 + ASSET_TYPE_DRAWABLE = 2, //130075505 + ASSET_TYPE_DRAWABLEDICTIONARY = 3, //1580165652 + ASSET_TYPE_ASSETLESS = 4, //4161085041 + } + + public enum Unk_1264241711 //entity lodLevel + : int //Key:1856311430 + { + LODTYPES_DEPTH_HD = 0, + LODTYPES_DEPTH_LOD = 1, + LODTYPES_DEPTH_SLOD1 = 2, + LODTYPES_DEPTH_SLOD2 = 3, + LODTYPES_DEPTH_SLOD3 = 4, //thanks Tadden :D + LODTYPES_DEPTH_ORPHANHD = 5, + LODTYPES_DEPTH_SLOD4 = 6, + } + + public enum Unk_648413703 //entity priorityLevel + : int //Key:2200357711 + { + PRI_REQUIRED = 0, //1943361227 + PRI_OPTIONAL_HIGH = 1, //3993616791 + PRI_OPTIONAL_MEDIUM = 2, //515598709 + PRI_OPTIONAL_LOW = 3, //329627604 + } + + public enum Unk_1294270217 //archetype CExtensionDefLadder materialType + : int //Key:3514570158 + { + METAL_SOLID_LADDER = 0, //Unk_1101797524 = 0, + METAL_LIGHT_LADDER = 1, + Unk_3202617440 = 2, + } + + public enum Unk_1931949281 //archetype CExtensionDefLightShaft densityType + : int //Key:3539601182 + { + Unk_676250331 = 0, + Unk_2399586564 = 1, + Unk_2057886646 = 2, + Unk_1816804348 = 3, + Unk_152140774 = 4, + Unk_2088805984 = 5, + Unk_1098824079 = 6, + Unk_1492299290 = 7, + } + + public enum Unk_2266515059 //archetype CExtensionDefLightShaft volumeType + : int //Key:4287472345 + { + Unk_665241531 = 0, + Unk_462992848 = 1, + } + + public enum Unk_884254308 //component peds CComponentInfo ped accessory / variations slot + : short //Key:3472084374 + { + PV_COMP_INVALID = -1, + PV_COMP_HEAD = 0, + PV_COMP_BERD = 1, + PV_COMP_HAIR = 2, + PV_COMP_UPPR = 4,//3, + PV_COMP_LOWR = 8,//4, + PV_COMP_HAND = 16,//5, + PV_COMP_FEET = 32,//6, + PV_COMP_TEEF = 64,//7, + PV_COMP_ACCS = 128,//8, + PV_COMP_TASK = 256,//9, + PV_COMP_DECL = 512,//10, + PV_COMP_JBIB = 1024,//11, + PV_COMP_MAX = 2048,//12, + } + + public enum Unk_4212977111 //component peds Unk_94549140 renderFlags + : int //Key:1551913633 + { + Unk_3757767268 = 0, + Unk_3735238938 = 1, + Unk_3395845123 = 2, + } + + public enum Unk_2834549053 //component peds CAnchorProps anchor + : int //Key:1309372691 + { + ANCHOR_HEAD = 0, + ANCHOR_EYES = 1, + ANCHOR_EARS = 2, + ANCHOR_MOUTH = 3, + ANCHOR_LEFT_HAND = 4, + ANCHOR_RIGHT_HAND = 5, + ANCHOR_LEFT_WRIST = 6, + ANCHOR_RIGHT_WRIST = 7, + ANCHOR_HIP = 8, + ANCHOR_LEFT_FOOT = 9, + ANCHOR_RIGHT_FOOT = 10, + Unk_604819740 = 11, + Unk_2358626934 = 12, + NUM_ANCHORS = 13, + } + + public enum Unk_3044470860 //cloth collision data SectionUNKNOWN1/1701774085 Flags + : int //Key:1585854303 + { + Unk_997866013 = 0, + } + + + + + + + //generated + adjusted structs code (UnusedX padding vars manually added) from here down + + //Struct infos + + [TC(typeof(EXP))] public struct CMapTypes //80 bytes, Key:2608875220 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public Array_StructurePointer extensions { get; set; } //8 8: Array: 0: extensions {0: StructurePointer: 0: 256} + public Array_StructurePointer archetypes { get; set; } //24 24: Array: 0: archetypes {0: StructurePointer: 0: 256} + public MetaHash name { get; set; } //40 40: Hash: 0: name + public uint Unused2 { get; set; }//44 + public Array_uint dependencies { get; set; } //48 48: Array: 0: dependencies//1013942340 {0: Hash: 0: 256} + public Array_Structure compositeEntityTypes { get; set; } //64 64: Array: 0: compositeEntityTypes {0: Structure: SectionUNKNOWN2: 256} + + public override string ToString() + { + return name.ToString(); + } + } + + [TC(typeof(EXP))] public struct CBaseArchetypeDef //144 bytes, Key:2411387556 + { + public uint Unused00 { get; set; }//0 + public uint Unused01 { get; set; }//4 + public float lodDist { get; set; } //8 8: Float: 0: lodDist + public uint flags { get; set; } //12 12: UnsignedInt: 0: flags + public uint specialAttribute { get; set; } //16 16: UnsignedInt: 0: specialAttribute + public uint Unused02 { get; set; }//20 + public uint Unused03 { get; set; }//24 + public uint Unused04 { get; set; }//28 + public Vector3 bbMin { get; set; } //32 32: Float_XYZ: 0: bbMin + public float Unused05 { get; set; }//44 + public Vector3 bbMax { get; set; } //48 48: Float_XYZ: 0: bbMax + public float Unused06 { get; set; }//60 + public Vector3 bsCentre { get; set; } //64 64: Float_XYZ: 0: bsCentre + public float Unused07 { get; set; }//76 + public float bsRadius { get; set; } //80 80: Float: 0: bsRadius + public float hdTextureDist { get; set; } //84 84: Float: 0: hdTextureDist//2908576588 + public MetaHash name { get; set; } //88 88: Hash: 0: name + public MetaHash textureDictionary { get; set; } //92 92: Hash: 0: textureDictionary + public MetaHash clipDictionary { get; set; } //96 96: Hash: 0: clipDictionary//424089489 + public MetaHash drawableDictionary { get; set; } //100 100: Hash: 0: drawableDictionary + public MetaHash physicsDictionary { get; set; } //104 104: Hash: 0: physicsDictionary//3553040380 + public Unk_1991964615 assetType { get; set; } //108 108: IntEnum: 1991964615: assetType + public MetaHash assetName { get; set; } //112 112: Hash: 0: assetName + public uint Unused08 { get; set; }//116 + public Array_StructurePointer extensions { get; set; } //120 120: Array: 0: extensions {0: StructurePointer: 0: 256} + public uint Unused09 { get; set; }//136 + public uint Unused10 { get; set; }//140 + + + public override string ToString() + { + return name.ToString() + ", " + + assetName.ToString() + ", " + + drawableDictionary.ToString() + ", " + + textureDictionary.ToString(); + } + } + + [TC(typeof(EXP))] public struct CTimeArchetypeDef //160 bytes, Key:2520619910 + { + public CBaseArchetypeDef CBaseArchetypeDef { get; set; } + public uint timeFlags { get; set; } //144 144: UnsignedInt: 0: timeFlags//2248791340 + public uint Unused11 { get; set; }//148 + public uint Unused12 { get; set; }//152 + public uint Unused13 { get; set; }//156 + + public override string ToString() + { + return CBaseArchetypeDef.ToString(); + } + } + + [TC(typeof(EXP))] public struct CMloArchetypeDef //240 bytes, Key:937664754 + { + public CBaseArchetypeDef CBaseArchetypeDef { get; set; } + public uint mloFlags { get; set; } //144 144: UnsignedInt: 0: mloFlags//3590839912 + public uint Unused11 { get; set; }//148 + public Array_StructurePointer entities { get; set; } //152 152: Array: 0: entities {0: StructurePointer: 0: 256} + public Array_Structure rooms { get; set; } //168 168: Array: 0: rooms {0: Structure: CMloRoomDef: 256} + public Array_Structure portals { get; set; } //184 184: Array: 0: portals//2314725778 {0: Structure: CMloPortalDef: 256} + public Array_Structure entitySets { get; set; } //200 200: Array: 0: entitySets//1169996080 {0: Structure: CMloEntitySet: 256} + public Array_Structure timeCycleModifiers { get; set; } //216 216: Array: 0: timeCycleModifiers {0: Structure: CMloTimeCycleModifier: 256} + public uint Unused12 { get; set; }//232 + public uint Unused13 { get; set; }//236 + + public override string ToString() + { + return CBaseArchetypeDef.ToString(); + } + } + + [TC(typeof(EXP))] public struct CLODLight //136 bytes, Key:2325189228 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public Array_Structure direction { get; set; } //8 8: Array: 0: direction {0: Structure: SectionUNKNOWN9: 256} + public Array_float falloff { get; set; } //24 24: Array: 0: falloff {0: Float: 0: 256} + public Array_float falloffExponent { get; set; } //40 40: Array: 0: falloffExponent {0: Float: 0: 256} + public Array_uint timeAndStateFlags { get; set; } //56 56: Array: 0: timeAndStateFlags=3112418278 {0: UnsignedInt: 0: 256} + public Array_uint hash { get; set; } //72 72: Array: 0: hash {0: UnsignedInt: 0: 256} + public Array_byte coneInnerAngle { get; set; } //88 88: Array: 0: coneInnerAngle//1163671864 {0: UnsignedByte: 0: 256} + public Array_byte coneOuterAngleOrCapExt { get; set; } //104 104: Array: 0: coneOuterAngleOrCapExt=3161894080 {0: UnsignedByte: 0: 256} + public Array_byte coronaIntensity { get; set; } //120 120: Array: 0: coronaIntensity//2292363771 {0: UnsignedByte: 0: 256} + } + + [TC(typeof(EXP))] public struct CDistantLODLight //48 bytes, Key:2820908419 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public Array_Structure position { get; set; } //8 8: Array: 0: position {0: Structure: SectionUNKNOWN9: 256} + public Array_uint RGBI { get; set; } //24 24: Array: 0: RGBI {0: UnsignedInt: 0: 256} + public ushort numStreetLights { get; set; } //40 40: UnsignedShort: 0: numStreetLights//3708891211 + public ushort category { get; set; } //42 42: UnsignedShort: 0: category//2052871693 + public uint Unused2 { get; set; }//44 + } + + [TC(typeof(EXP))] public struct CBlockDesc //72 bytes, Key:2015795449 + { + public uint version { get; set; } //0 0: UnsignedInt: 0: version + public uint flags { get; set; } //4 4: UnsignedInt: 0: flags + public CharPointer name { get; set; } //8 8: CharPointer: 0: name + public CharPointer exportedBy { get; set; } //24 24: CharPointer: 0: exportedBy//1983184981 + public CharPointer owner { get; set; } //40 40: CharPointer: 0: owner + public CharPointer time { get; set; } //56 56: CharPointer: 0: time + } + + [TC(typeof(EXP))] public struct CMapData //512 bytes, Key:3448101671 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public MetaHash parent { get; set; } //12 12: Hash: 0: parent + public uint flags { get; set; } //16 16: UnsignedInt: 0: flags + public uint contentFlags { get; set; } //20 20: UnsignedInt: 0: contentFlags//1785155637 + public uint Unused2 { get; set; }//24 + public uint Unused3 { get; set; }//28 + public Vector3 streamingExtentsMin { get; set; } //32 32: Float_XYZ: 0: streamingExtentsMin//3710026271 + public float Unused4 { get; set; }//44 + public Vector3 streamingExtentsMax { get; set; } //48 48: Float_XYZ: 0: streamingExtentsMax//2720965429 + public float Unused5 { get; set; }//60 + public Vector3 entitiesExtentsMin { get; set; } //64 64: Float_XYZ: 0: entitiesExtentsMin//477478129 + public float Unused6 { get; set; }//76 + public Vector3 entitiesExtentsMax { get; set; } //80 80: Float_XYZ: 0: entitiesExtentsMax//1829192759 + public float Unused7 { get; set; }//92 + public Array_StructurePointer entities { get; set; } //96 96: Array: 0: entities {0: StructurePointer: 0: 256} + public Array_Structure containerLods { get; set; } //112 112: Array: 0: containerLods//2935983381 {0: Structure: 372253349: 256} + public Array_Structure boxOccluders { get; set; } //128 128: Array: 0: boxOccluders//3983590932 {0: Structure: SectionUNKNOWN7: 256} + public Array_Structure occludeModels { get; set; } //144 144: Array: 0: occludeModels//2132383965 {0: Structure: SectionUNKNOWN5: 256} + public Array_uint physicsDictionaries { get; set; } //160 160: Array: 0: physicsDictionaries//949589348 {0: Hash: 0: 256} + public rage__fwInstancedMapData instancedData { get; set; } //176 176: Structure: rage__fwInstancedMapData: instancedData//2569067561 + public Array_Structure timeCycleModifiers { get; set; } //224 224: Array: 0: timeCycleModifiers {0: Structure: CTimeCycleModifier: 256} + public Array_Structure carGenerators { get; set; } //240 240: Array: 0: carGenerators//3254823756 {0: Structure: CCarGen: 256} + public CLODLight LODLightsSOA { get; set; } //256 256: Structure: CLODLight: LODLightsSOA//1774371066 + public CDistantLODLight DistantLODLightsSOA { get; set; } //392 392: Structure: CDistantLODLight: DistantLODLightsSOA//2954466641 + public CBlockDesc block { get; set; } //440 440: Structure: CBlockDesc//3072355914: block + + + //notes: + //CMapData.flags: + // flag 1 = SCRIPTED flag (eg destruction) + // flag 2 = LOD flag? reflection proxy flag? + + + public override string ToString() + { + return name.ToString() + ": " + parent.ToString(); + } + } + + [TC(typeof(EXP))] public struct CEntityDef //128 bytes, Key:1825799514 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash archetypeName { get; set; } //8 8: Hash: 0: archetypeName + public uint flags { get; set; } //12 12: UnsignedInt: 0: flags + public uint guid { get; set; } //16 16: UnsignedInt: 0: guid + public uint Unused2 { get; set; }//20 + public uint Unused3 { get; set; }//24 + public uint Unused4 { get; set; }//28 + public Vector3 position { get; set; } //32 32: Float_XYZ: 0: position + public float Unused5 { get; set; }//44 + public Vector4 rotation { get; set; } //48 48: Float_XYZW: 0: rotation + public float scaleXY { get; set; } //64 64: Float: 0: 2627937847 + public float scaleZ { get; set; } //68 68: Float: 0: 284916802 + public int parentIndex { get; set; } //72 72: SignedInt: 0: parentIndex + public float lodDist { get; set; } //76 76: Float: 0: lodDist + public float childLodDist { get; set; } //80 80: Float: 0: childLodDist//3398912973 + public Unk_1264241711 lodLevel { get; set; } //84 84: IntEnum: 1264241711: lodLevel //LODTYPES_DEPTH_ + public uint numChildren { get; set; } //88 88: UnsignedInt: 0: numChildren//2793909385 + public Unk_648413703 priorityLevel { get; set; } //92 92: IntEnum: 648413703: priorityLevel//647098393 + public Array_StructurePointer extensions { get; set; } //96 96: Array: 0: extensions {0: StructurePointer: 0: 256} + public int ambientOcclusionMultiplier { get; set; } //112 112: SignedInt: 0: ambientOcclusionMultiplier//415356295 + public int artificialAmbientOcclusion { get; set; } //116 116: SignedInt: 0: artificialAmbientOcclusion//599844163 + public uint tintValue { get; set; } //120 120: UnsignedInt: 0: tintValue//1015358759 + public uint Unused6 { get; set; }//124 + + + public override string ToString() + { + return JenkIndex.GetString(archetypeName) + ": " + JenkIndex.GetString(guid) + ": " + position.ToString(); + } + } + + [TC(typeof(EXP))] public struct CTimeCycleModifier //64 bytes, Key:2683420777 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 minExtents { get; set; } //16 16: Float_XYZ: 0: minExtents=1731020657 + public float Unused3 { get; set; }//28 + public Vector3 maxExtents { get; set; } //32 32: Float_XYZ: 0: maxExtents=2554806840 + public float Unused4 { get; set; }//44 + public float percentage { get; set; } //48 48: Float: 0: percentage + public float range { get; set; } //52 52: Float: 0: range + public uint startHour { get; set; } //56 56: UnsignedInt: 0: startHour + public uint endHour { get; set; } //60 60: UnsignedInt: 0: endHour + + + //regarding name in OpenIV: + //2633803310 = NoAmbientmult + //2003616884 = INT_NoAmbientMult + + + + public override string ToString() + { + return name.ToString() + ": startHour " + startHour.ToString() + ", endHour " + endHour.ToString() + ", range " + range.ToString() + ", percentage " + percentage.ToString(); + } + } + + [TC(typeof(EXP))] public struct CMloInstanceDef //160 bytes, Key:2151576752 + { + public CEntityDef CEntityDef { get; set; } + public uint groupId { get; set; } //128 128: UnsignedInt: 0: 2501631252 + public uint floorId { get; set; } //132 132: UnsignedInt: 0: floorId//2187650609 + public Array_uint Unk_1407157833 { get; set; } //136 136: Array: 0: 1407157833 {0: Hash: 0: 256} + public uint Unk_528711607 { get; set; } //152 152: UnsignedInt: 0: 528711607 + public uint Unk_3761966250 { get; set; } //156 156: UnsignedInt: 0: 3761966250 + } + + [TC(typeof(EXP))] public struct CMloRoomDef //112 bytes, Key:3885428245 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public CharPointer name { get; set; } //8 8: CharPointer: 0: name + public uint Unused2 { get; set; }//24 + public uint Unused3 { get; set; }//28 + public Vector3 bbMin { get; set; } //32 32: Float_XYZ: 0: bbMin + public float Unused4 { get; set; }//44 + public Vector3 bbMax { get; set; } //48 48: Float_XYZ: 0: bbMax + public float Unused5 { get; set; }//60 + public float blend { get; set; } //64 64: Float: 0: blend + public MetaHash timecycleName { get; set; } //68 68: Hash: 0: timecycleName//2724323497 + public MetaHash secondaryTimecycleName { get; set; } //72 72: Hash: 0: secondaryTimecycleName//3255324828 + public uint flags { get; set; } //76 76: UnsignedInt: 0: flags + public uint portalCount { get; set; } //80 80: UnsignedInt: 0: portalCount//1105339827 + public int floorId { get; set; } //84 84: SignedInt: 0: floorId//2187650609 + public int Unk_552849982 { get; set; } //88 88: SignedInt: 0: exteriorVisibiltyDepth//552849982 + public uint Unused6 { get; set; }//92 + public Array_uint attachedObjects { get; set; } //96 96: Array: 0: attachedObjects//2382704940 {0: UnsignedInt: 0: 256} + } + + [TC(typeof(EXP))] public struct CMloPortalDef //64 bytes, Key:1110221513 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public uint roomFrom { get; set; } //8 8: UnsignedInt: 0: 4101034749 + public uint roomTo { get; set; } //12 12: UnsignedInt: 0: 2607060513 + public uint flags { get; set; } //16 16: UnsignedInt: 0: flags + public uint mirrorPriority { get; set; } //20 20: UnsignedInt: 0: 1185490713 + public uint opacity { get; set; } //24 24: UnsignedInt: 0: opacity + public uint audioOcclusion { get; set; } //28 28: UnsignedInt: 0: 1093790004 + public Array_Vector3 corners { get; set; } //32 32: Array: 0: corners {0: Float_XYZ: 0: 256} + public Array_uint attachedObjects { get; set; } //48 48: Array: 0: attachedObjects//2382704940 {0: UnsignedInt: 0: 256} + } + + [TC(typeof(EXP))] public struct CMloTimeCycleModifier //48 bytes, Key:838874674 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector4 sphere { get; set; } //16 16: Float_XYZW: 0: sphere + public float percentage { get; set; } //32 32: Float: 0: percentage + public float range { get; set; } //36 36: Float: 0: range + public uint startHour { get; set; } //40 40: UnsignedInt: 0: startHour + public uint endHour { get; set; } //44 44: UnsignedInt: 0: vlink87812 + } + + [TC(typeof(EXP))] public struct CMloEntitySet //48 bytes, Key:4180211587 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Array_uint locations { get; set; } //16 16: Array: 0: locations {0: UnsignedInt: 0: 256} + public Array_StructurePointer entities { get; set; } //32 32: Array: 0: entities {0: StructurePointer: 0: 256} + } + + [TC(typeof(EXP))] public struct rage__spdGrid2D //64 bytes, Key:894636096 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public uint Unused2 { get; set; }//8 + public int Unk_MinX_860552138 { get; set; } //12 12: SignedInt: 0: 860552138 //MIN X + public int Unk_MaxX_3824598937 { get; set; } //16 16: SignedInt: 0: 3824598937 //MAX X + public int Unk_MinY_496029782 { get; set; } //20 20: SignedInt: 0: 496029782 //MIN Y + public int Unk_MaxY_3374647798 { get; set; } //24 24: SignedInt: 0: 3374647798 //MAX Y + public uint Unused3 { get; set; }//28 + public uint Unused4 { get; set; }//32 + public uint Unused5 { get; set; }//36 + public uint Unused6 { get; set; }//40 + public float Unk_X_2690909759 { get; set; } //44 44: Float: 0: 2690909759 //grid scale X (cell size) + public float Unk_Y_3691675019 { get; set; } //48 48: Float: 0: 3691675019 //grid scale Y (cell size) + public uint Unused7 { get; set; }//52 + public uint Unused8 { get; set; }//56 + public uint Unused9 { get; set; }//60 + + + public Vector2I Dimensions + { + get + { + return new Vector2I((Unk_MaxX_3824598937 - Unk_MinX_860552138)+1, (Unk_MaxY_3374647798 - Unk_MinY_496029782)+1); + } + } + public Vector2 Scale + { + get + { + return new Vector2(Unk_X_2690909759, Unk_Y_3691675019); + } + set + { + Unk_X_2690909759 = value.X; + Unk_Y_3691675019 = value.Y; + } + } + public Vector2 Min + { + get + { + return new Vector2(Unk_MinX_860552138, Unk_MinY_496029782) * Scale; + } + set + { + var gv = value / Scale; + Unk_MinX_860552138 = (int)Math.Floor(gv.X); + Unk_MinY_496029782 = (int)Math.Floor(gv.Y); + } + } + public Vector2 Max + { + get + { + return new Vector2(Unk_MaxX_3824598937, Unk_MaxY_3374647798) * Scale; + } + set + { + var gv = value / Scale; + Unk_MaxX_3824598937 = (int)Math.Floor(gv.X); + Unk_MaxY_3374647798 = (int)Math.Floor(gv.Y); + } + } + } + + [TC(typeof(EXP))] public struct rage__spdAABB //32 bytes, Key:1158138379 //WAS: Unk_4084721864 + { + public Vector4 min { get; set; } //0 0: Float_XYZW: 0: min + public Vector4 max { get; set; } //16 16: Float_XYZW: 0: max + + public override string ToString() + { + return "min: " + min.ToString() + ", max: " + max.ToString(); + } + public void SwapEnd() + { + min = MetaTypes.SwapBytes(min); + max = MetaTypes.SwapBytes(max); + } + } + + [TC(typeof(EXP))] public struct rage__spdSphere //16 bytes, Key:1189037266 //Sphere - used in scenario parts + { + public Vector4 centerAndRadius { get; set; } //0 0: Float_XYZW: 0: centerAndRadius + + public override string ToString() + { + return centerAndRadius.ToString(); + } + } + + [TC(typeof(EXP))] public struct rage__phVerletClothCustomBounds //32 bytes, Key:2075461750 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Array_Structure CollisionData { get; set; } //16 16: Array: 0: CollisionData {0: Structure: SectionUNKNOWN1: 256} + } + [TC(typeof(EXP))] public class Mrage__phVerletClothCustomBounds : MetaWrapper + { + public rage__phVerletClothCustomBounds _Data; + public rage__phVerletClothCustomBounds Data { get { return _Data; } } + + public MUnk_1701774085[] CollisionData { get; set; } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + + var cdata = MetaTypes.ConvertDataArray(meta, (MetaName)1701774085/*.SectionUNKNOWN1*/, _Data.CollisionData); + if (cdata != null) + { + CollisionData = new MUnk_1701774085[cdata.Length]; + for (int i = 0; i < cdata.Length; i++) + { + CollisionData[i] = new MUnk_1701774085(meta, cdata[i]); + } + } + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + if (CollisionData != null) + { + _Data.CollisionData = mb.AddWrapperArray(CollisionData); + } + + mb.AddStructureInfo(MetaName.rage__phVerletClothCustomBounds); + return mb.AddItemPtr(MetaName.rage__phVerletClothCustomBounds, _Data); + } + + public override string ToString() + { + return "rage__phVerletClothCustomBounds - " + _Data.name.ToString() + " (" + (CollisionData?.Length ?? 0).ToString() + " CollisionData)"; + } + } + + [TC(typeof(EXP))] public struct rage__fwInstancedMapData //48 bytes, Key:1836780118 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash ImapLink { get; set; } //8 8: Hash: 0: ImapLink//2142127586 + public uint Unused2 { get; set; }//12 + public Array_Structure PropInstanceList { get; set; } //16 16: Array: 0: PropInstanceList//3551474528 {0: Structure: rage__fwPropInstanceListDef: 256} + public Array_Structure GrassInstanceList { get; set; } //32 32: Array: 0: GrassInstanceList//255292381 {0: Structure: rage__fwGrassInstanceListDef: 256} + + public override string ToString() + { + return ImapLink.ToString() + ", " + PropInstanceList.Count1.ToString() + " props, " + GrassInstanceList.Count1.ToString() + " grasses"; + } + } + + [TC(typeof(EXP))] public struct rage__fwGrassInstanceListDef //96 bytes, Key:941808164 rage__fwGrassInstanceListDef//2085051229 + { + public rage__spdAABB BatchAABB { get; set; } //0 0: Structure: 4084721864: BatchAABB//1859041902 + public Vector3 ScaleRange { get; set; } //32 32: Float_XYZ: 0: ScaleRange + public float Unused0 { get; set; }//44 + public MetaHash archetypeName { get; set; } //48 48: Hash: 0: archetypeName + public uint lodDist { get; set; } //52 52: UnsignedInt: 0: lodDist + public float LodFadeStartDist { get; set; } //56 56: Float: 0: LodFadeStartDist//2216273066 + public float LodInstFadeRange { get; set; } //60 60: Float: 0: LodInstFadeRange//1405992723 + public float OrientToTerrain { get; set; } //64 64: Float: 0: OrientToTerrain//3341475578 + public uint Unused1 { get; set; }//68 + public Array_Structure InstanceList { get; set; } //72 72: Array: 0: InstanceList//470289337 {0: Structure: rage__fwGrassInstanceListDef__InstanceData: 256} + public uint Unused2 { get; set; }//88 + public uint Unused3 { get; set; }//92 + + public override string ToString() + { + return archetypeName.ToString() + " (" + InstanceList.Count1.ToString() + " instances)"; + } + } + + [TC(typeof(EXP))] public struct rage__fwGrassInstanceListDef__InstanceData //16 bytes, Key:2740378365 rage__fwGrassInstanceListDef__InstanceData//3985044770 // Tom: Something to do with placing foliage + { + public ArrayOfUshorts3 Position { get; set; } //0 0: ArrayOfBytes: 3: Position - Ushorts + public byte NormalX { get; set; } //6 6: UnsignedByte: 0: NormalX//3138065392 + public byte NormalY { get; set; } //7 7: UnsignedByte: 0: NormalY//273792636 + public ArrayOfBytes3 Color { get; set; } //8 8: ArrayOfBytes: 3: Color + public byte Scale { get; set; } //11 11: UnsignedByte: 0: Scale + public byte Ao { get; set; } //12 12: UnsignedByte: 0: Ao//2996378564 + public ArrayOfBytes3 Pad { get; set; } //13 13: ArrayOfBytes: 3: Pad + + public override string ToString() + { + return Position.ToString() + " : " + Color.ToString() + " : " + Scale.ToString(); + } + } + + public struct CBaseArchetypeDef_v2 //128 bytes, Key:2352343492 + { + public uint Unused00 { get; set; }//0 + public uint Unused01 { get; set; }//4 + public float lodDist { get; set; } //8 8: Float: 0: lodDist + public uint flags { get; set; } //12 12: UnsignedInt: 0: flags + public uint specialAttribute { get; set; } //16 16: UnsignedInt: 0: specialAttribute + public uint Unused02 { get; set; }//20 + public uint Unused03 { get; set; }//24 + public uint Unused04 { get; set; }//28 + public Vector3 bbMin { get; set; } //32 32: Float_XYZ: 0: bbMin + public float Unused05 { get; set; }//44 + public Vector3 bbMax { get; set; } //48 48: Float_XYZ: 0: bbMax + public float Unused06 { get; set; }//60 + public Vector3 bsCentre { get; set; } //64 64: Float_XYZ: 0: bsCentre + public float Unused07 { get; set; }//76 + public float bsRadius { get; set; } //80 80: Float: 0: bsRadius + public float hdTextureDist { get; set; } //84 84: Float: 0: hdTextureDist//2908576588 + public MetaHash name { get; set; } //88 88: Hash: 0: name + public MetaHash textureDictionary { get; set; } //92 92: Hash: 0: textureDictionary + public MetaHash clipDictionary { get; set; } //96 96: Hash: 0: clipDictionary//424089489 + public MetaHash drawableDictionary { get; set; } //100 100: Hash: 0: drawableDictionary + public MetaHash physicsDictionary { get; set; } //104 104: Hash: 0: physicsDictionary//3553040380 + public uint Unused08 { get; set; }//108 + public Array_StructurePointer extensions { get; set; } //112 112: Array: 0: extensions {0: StructurePointer: 0: 256} + } + + public struct CCreatureMetaData //56 bytes, Key:2181653572 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public Array_Structure shaderVariableComponents { get; set; } //8 8: Array: 0: shaderVariableComponents {0: Structure: CShaderVariableComponent: 256} + public Array_Structure pedPropExpressions { get; set; } //24 24: Array: 0: pedPropExpressions {0: Structure: CPedPropExpressionData: 256} + public Array_Structure pedCompExpressions { get; set; } //40 40: Array: 0: pedCompExpressions {0: Structure: CPedCompExpressionData: 256} + } + + public struct CShaderVariableComponent //72 bytes, Key:3085831725 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public uint pedcompID { get; set; } //8 8: UnsignedInt: 0: pedcompID + public uint maskID { get; set; } //12 12: UnsignedInt: 0: maskID + public uint shaderVariableHashString { get; set; } //16 16: Hash: 0: shaderVariableHashString + public uint Unused2 { get; set; }//20 + public Array_byte tracks { get; set; } //24 24: Array: 0: tracks {0: UnsignedByte: 0: 256} + public Array_ushort ids { get; set; } //40 40: Array: 0: ids {0: UnsignedShort: 0: 256} + public Array_byte components { get; set; } //56 56: Array: 0: components {0: UnsignedByte: 0: 256} + } + + public struct CPedPropExpressionData //88 bytes, Key:1355135810 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public uint pedPropID { get; set; } //8 8: UnsignedInt: 0: pedPropID + public int pedPropVarIndex { get; set; } //12 12: SignedInt: 0: pedPropVarIndex + public uint pedPropExpressionIndex { get; set; } //16 16: UnsignedInt: 0: pedPropExpressionIndex + public uint Unused2 { get; set; }//20 + public Array_byte tracks { get; set; } //24 24: Array: 0: tracks {0: UnsignedByte: 0: 256} + public Array_ushort ids { get; set; } //40 40: Array: 0: ids {0: UnsignedShort: 0: 256} + public Array_byte types { get; set; } //56 56: Array: 0: types {0: UnsignedByte: 0: 256} + public Array_byte components { get; set; } //72 72: Array: 0: components {0: UnsignedByte: 0: 256} + } + + public struct CPedCompExpressionData //88 bytes, Key:3458164745 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public uint pedCompID { get; set; } //8 8: UnsignedInt: 0: pedCompID + public int pedCompVarIndex { get; set; } //12 12: SignedInt: 0: pedCompVarIndex + public uint pedCompExpressionIndex { get; set; } //16 16: UnsignedInt: 0: pedCompExpressionIndex + public uint Unused2 { get; set; }//20 + public Array_byte tracks { get; set; } //24 24: Array: 0: tracks {0: UnsignedByte: 0: 256} + public Array_ushort ids { get; set; } //40 40: Array: 0: ids {0: UnsignedShort: 0: 256} + public Array_byte types { get; set; } //56 56: Array: 0: types {0: UnsignedByte: 0: 256} + public Array_byte components { get; set; } //72 72: Array: 0: components {0: UnsignedByte: 0: 256} + } + + [TC(typeof(EXP))] public struct CLightAttrDef //160 bytes, Key:2363260268 + { + public uint Unused00 { get; set; }//0 + public uint Unused01 { get; set; }//4 + public Vector3 posn { get; set; } //8 8: ArrayOfBytes: 3: posn //actually ArrayOfFloats3 (Vector3!) + public ArrayOfBytes3 colour { get; set; } //20 20: ArrayOfBytes: 3: colour + public byte flashiness { get; set; } //23 23: UnsignedByte: 0: 3829693202 + public float intensity { get; set; } //24 24: Float: 0: intensity + public uint flags { get; set; } //28 28: UnsignedInt: 0: flags + public short boneTag { get; set; } //32 32: SignedShort: 0: boneTag + public byte lightType { get; set; } //34 34: UnsignedByte: 0: 482065968 + public byte groupId { get; set; } //35 35: UnsignedByte: 0: 2501631252 + public uint timeFlags { get; set; } //36 36: UnsignedInt: 0: timeFlags//2248791340 + public float falloff { get; set; } //40 40: Float: 0: falloff + public float falloffExponent { get; set; } //44 44: Float: 0: falloffExponent + public Vector4 cullingPlane { get; set; } //48 48: ArrayOfBytes: 4: 1689591312 //48: 1689591312//cullingPlane - actually ArrayOfFloats4! + public byte shadowBlur { get; set; } //64 64: UnsignedByte: 0: shadowBlur + public byte padding1 { get; set; } //65 65: UnsignedByte: 0: padding1//3180641850 + public short padding2 { get; set; } //66 66: SignedShort: 0: padding2//2346113727 + public uint padding3 { get; set; } //68 68: UnsignedInt: 0: padding3//3521603295 + public float volIntensity { get; set; } //72 72: Float: 0: volIntensity//689780512 + public float volSizeScale { get; set; } //76 76: Float: 0: volSizeScale//2029533327 + public ArrayOfBytes3 volOuterColour { get; set; } //80 80: ArrayOfBytes: 3: volOuterColour//2283994062 + public byte lightHash { get; set; } //83 83: UnsignedByte: 0: lightHash//643049222 + public float volOuterIntensity { get; set; } //84 84: Float: 0: volOuterIntensity//3008198647 + public float coronaSize { get; set; } //88 88: Float: 0: coronaSize//1705000075 + public float volOuterExponent { get; set; } //92 92: Float: 0: volOuterExponent//2758849250 + public byte lightFadeDistance { get; set; } //96 96: UnsignedByte: 0: lightFadeDistance//1307926275 + public byte shadowFadeDistance { get; set; } //97 97: UnsignedByte: 0: shadowFadeDistance//1944267876 + public byte specularFadeDistance { get; set; } //98 98: UnsignedByte: 0: specularFadeDistance//4150887048 + public byte volumetricFadeDistance { get; set; } //99 99: UnsignedByte: 0: volumetricFadeDistance//2066998816 + public float shadowNearClip { get; set; } //100 100: Float: 0: shadowNearClip//954647178 + public float coronaIntensity { get; set; } //104 104: Float: 0: coronaIntensity//2292363771 + public float coronaZBias { get; set; } //108 108: Float: 0: coronaZBias//2520359283 + public Vector3 direction { get; set; } //112 112: ArrayOfBytes: 3: direction //actually ArrayOfFloats3 (Vector3!) + public Vector3 tangent { get; set; } //124 124: ArrayOfBytes: 3: tangent //actually ArrayOfFloats3 (Vector3!) + public float coneInnerAngle { get; set; } //136 136: Float: 0: coneInnerAngle//1163671864 + public float coneOuterAngle { get; set; } //140 140: Float: 0: coneOuterAngle//4175029060 + public Vector3 extents { get; set; } //144 144: ArrayOfBytes: 3: extents//759134656 //actually ArrayOfFloats3 (Vector3!) + public uint projectedTextureKey { get; set; } //156 156: UnsignedInt: 0: projectedTextureKey//1076718994 + } + + [TC(typeof(EXP))] public struct CCarGen //80 bytes, Key:2345238261 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public uint Unused2 { get; set; }//8 + public uint Unused3 { get; set; }//12 + public Vector3 position { get; set; } //16 16: Float_XYZ: 0: position + public float Unused4 { get; set; }//28 + public float orientX { get; set; } //32 32: Float: 0: orientX=735213009 + public float orientY { get; set; } //36 36: Float: 0: orientY=979440342 + public float perpendicularLength { get; set; } //40 40: Float: 0: perpendicularLength=124715667 + public MetaHash carModel { get; set; } //44 44: Hash: 0: carModel + public uint flags { get; set; } //48 48: UnsignedInt: 0: flags /// _CP_: looks like flag 1879051873 in cargens forces to spawn a vehicle + public int bodyColorRemap1 { get; set; } //52 52: SignedInt: 0: bodyColorRemap1=1429703670 + public int bodyColorRemap2 { get; set; } //56 56: SignedInt: 0: bodyColorRemap2=1254848286 + public int bodyColorRemap3 { get; set; } //60 60: SignedInt: 0: bodyColorRemap3=1880965569 + public int bodyColorRemap4 { get; set; } //64 64: SignedInt: 0: bodyColorRemap4=1719152247 + public MetaHash popGroup { get; set; } //68 68: Hash: 0: popGroup=911358791 + public sbyte livery { get; set; } //72 72: SignedByte: 0: livery + public byte Unused5 { get; set; }//73 + public ushort Unused6 { get; set; }//74 + public uint Unused7 { get; set; }//76 + + public override string ToString() + { + return carModel.ToString() + ", " + position.ToString() + ", " + popGroup.ToString() + ", " + livery.ToString(); + } + } + + [TC(typeof(EXP))] public struct Unk_1701774085 //96 bytes, Key:2859775340 //dexy: cloth CollisionData (child of rage__phVerletClothCustomBounds) ... eg josh house // Tom: explosions? + { + public CharPointer OwnerName { get; set; } //0 0: CharPointer: 0: OwnerName + public Vector4 Rotation { get; set; } //16 16: Float_XYZW: 0: Rotation + public Vector3 Position { get; set; } //32 32: Float_XYZ: 0: Position + public float Unused0 { get; set; }//44 + public Vector3 Normal { get; set; } //48 48: Float_XYZ: 0: Normal + public float Unused1 { get; set; }//60 + public float CapsuleRadius { get; set; } //64 64: Float: 0: CapsuleRadius + public float CapsuleLen { get; set; } //68 68: Float: 0: CapsuleLen + public float CapsuleHalfHeight { get; set; } //72 72: Float: 0: CapsuleHalfHeight + public float CapsuleHalfWidth { get; set; } //76 76: Float: 0: CapsuleHalfWidth + public Unk_3044470860 Flags { get; set; } //80 80: IntFlags2: 3044470860: Flags + public uint Unused2 { get; set; }//84 + public uint Unused3 { get; set; }//88 + public uint Unused4 { get; set; }//92 + } + [TC(typeof(EXP))] public class MUnk_1701774085 : MetaWrapper + { + public Unk_1701774085 _Data; + public Unk_1701774085 Data { get { return _Data; } } + + public string OwnerName { get; set; } + + public MUnk_1701774085() { } + public MUnk_1701774085(Meta meta, Unk_1701774085 s) + { + _Data = s; + OwnerName = MetaTypes.GetString(meta, _Data.OwnerName); + } + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + OwnerName = MetaTypes.GetString(meta, _Data.OwnerName); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + if (OwnerName != null) + { + _Data.OwnerName = mb.AddStringPtr(OwnerName); + } + + mb.AddEnumInfo((MetaName)3044470860); + mb.AddStructureInfo((MetaName)1701774085/*.SectionUNKNOWN1*/); + return mb.AddItemPtr((MetaName)1701774085/*.SectionUNKNOWN1*/, _Data); + } + + public override string ToString() + { + return "Unk_1701774085 - " + OwnerName; + } + } + + [TC(typeof(EXP))] public struct CCompositeEntityType //304 bytes, Key:659539004 dex: composite entity type - ytyp // Tom: des_ destruction + { + public ArrayOfChars64 Name { get; set; } //0 0: ArrayOfChars: 64: Name + public float lodDist { get; set; } //64 64: Float: 0: lodDist + public uint flags { get; set; } //68 68: UnsignedInt: 0: flags + public uint specialAttribute { get; set; } //72 72: UnsignedInt: 0: specialAttribute + public uint Unused0 { get; set; }//76 + public Vector3 bbMin { get; set; } //80 80: Float_XYZ: 0: bbMin + public float Unused1 { get; set; }//92 + public Vector3 bbMax { get; set; } //96 96: Float_XYZ: 0: bbMax + public float Unused2 { get; set; }//108 + public Vector3 bsCentre { get; set; } //112 112: Float_XYZ: 0: bsCentre + public float Unused3 { get; set; }//124 + public float bsRadius { get; set; } //128 128: Float: 0: bsRadius + public uint Unused4 { get; set; }//132 + public ArrayOfChars64 StartModel { get; set; } //136 136: ArrayOfChars: 64: StartModel + public ArrayOfChars64 EndModel { get; set; } //200 200: ArrayOfChars: 64: EndModel + public MetaHash StartImapFile { get; set; } //264 264: Hash: 0: StartImapFile//2462971690 + public MetaHash EndImapFile { get; set; } //268 268: Hash: 0: EndImapFile//2059586669 + public MetaHash PtFxAssetName { get; set; } //272 272: Hash: 0: PtFxAssetName//2497993358 + public uint Unused5 { get; set; }//276 + public Array_Structure Animations { get; set; } //280 280: Array: 0: Animations {0: Structure: 1980345114: 256} + public uint Unused6 { get; set; }//296 + public uint Unused7 { get; set; }//300 + + public override string ToString() + { + return Name.ToString() + ", " + StartModel.ToString() + ", " + EndModel.ToString() + ", " + + StartImapFile.ToString() + ", " + EndImapFile.ToString() + ", " + PtFxAssetName.ToString(); + } + } + + [TC(typeof(EXP))] public struct Unk_1980345114 //216 bytes, Key:4110496011 //destruction animations? + { + public ArrayOfChars64 AnimDict { get; set; } //0 0: ArrayOfChars: 64: AnimDict + public ArrayOfChars64 AnimName { get; set; } //64 64: ArrayOfChars: 64: AnimName + public ArrayOfChars64 AnimatedModel { get; set; } //128 128: ArrayOfChars: 64: AnimatedModel + public float punchInPhase { get; set; } //192 192: Float: 0: punchInPhase//3142377407 + public float punchOutPhase { get; set; } //196 196: Float: 0: punchOutPhase//2164219370 + public Array_Structure effectsData { get; set; } //200 200: Array: 0: effectsData {0: Structure: 3430328684: 256} + } + + [TC(typeof(EXP))] public struct Unk_2741784237 //64 bytes, Key:1172796107 //occludeModels + { + public Vector3 bmin { get; set; } //0 0: Float_XYZ: 0: bmin + public float Unused0 { get; set; }//12 + public Vector3 bmax { get; set; } //16 16: Float_XYZ: 0: bmax + public float Unused1 { get; set; }//28 + public uint dataSize { get; set; } //32 32: UnsignedInt: 0: dataSize//2442753371 + public uint Unused2 { get; set; }//36 + public DataBlockPointer verts { get; set; } //40 40: DataBlockPointer: 2: verts + public ushort Unk_853977995 { get; set; } //48 48: UnsignedShort: 0: 853977995 + public ushort Unk_2337695078 { get; set; } //50 50: UnsignedShort: 0: 2337695078 + public uint flags { get; set; } //52 52: UnsignedInt: 0: flags + public uint Unused3 { get; set; }//56 + public uint Unused4 { get; set; }//60 + } + + [TC(typeof(EXP))] public struct Unk_975711773 //16 bytes, Key:1831736438 //boxOccluders + { + public short iCenterX { get; set; } //0 0: SignedShort: 0: 48026296 + public short iCenterY { get; set; } //2 2: SignedShort: 0: 896907229 + public short iCenterZ { get; set; } //4 4: SignedShort: 0: 1597508449 + public short iCosZ { get; set; } //6 6: SignedShort: 0: iCosZ + public short iLength { get; set; } //8 8: SignedShort: 0: 2854610661 + public short iWidth { get; set; } //10 10: SignedShort: 0: 168013536 + public short iHeight { get; set; } //12 12: SignedShort: 0: 3485277993 + public short iSinZ { get; set; } //14 14: SignedShort: 0: iSinZ + } + + [TC(typeof(EXP))] public struct Unk_3430328684 //160 bytes, Key:1724963966 //destruction animation effects + { + public uint fxType { get; set; } //0 0: UnsignedInt: 0: fxType + public uint Unused0 { get; set; }//4 + public uint Unused1 { get; set; }//8 + public uint Unused2 { get; set; }//12 + public Vector3 fxOffsetPos { get; set; } //16 16: Float_XYZ: 0: fxOffsetPos + public float Unused3 { get; set; }//28 + public Vector4 fxOffsetRot { get; set; } //32 32: Float_XYZW: 0: fxOffsetRot + public uint boneTag { get; set; } //48 48: UnsignedInt: 0: boneTag + public float startPhase { get; set; } //52 52: Float: 0: startPhase + public float endPhase { get; set; } //56 56: Float: 0: endPhase + public byte ptFxIsTriggered { get; set; } //60 60: Boolean: 0: ptFxIsTriggered + public ArrayOfChars64 ptFxTag { get; set; } //61 61: ArrayOfChars: 64: ptFxTag + public byte Unused4 { get; set; }//125 + public ushort Unused5 { get; set; }//126 + public float ptFxScale { get; set; } //128 128: Float: 0: ptFxScale + public float ptFxProbability { get; set; } //132 132: Float: 0: ptFxProbability + public byte ptFxHasTint { get; set; } //136 136: Boolean: 0: ptFxHasTint + public byte ptFxTintR { get; set; } //137 137: UnsignedByte: 0: ptFxTintR + public byte ptFxTintG { get; set; } //138 138: UnsignedByte: 0: ptFxTintG + public byte ptFxTintB { get; set; } //139 139: UnsignedByte: 0: ptFxTintB + public uint Unused6 { get; set; }//140 + public Vector3 ptFxSize { get; set; } //144 144: Float_XYZ: 0: ptFxSize + public uint Unused7 { get; set; }//156 + } + + [TC(typeof(EXP))] public struct CExtensionDefParticleEffect //96 bytes, Key:466596385 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public uint Unused3 { get; set; }//28 + public Vector4 offsetRotation { get; set; } //32 32: Float_XYZW: 0: offsetRotation + public CharPointer fxName { get; set; } //48 48: CharPointer: 0: fxName + public int fxType { get; set; } //64 64: SignedInt: 0: fxType + public int boneTag { get; set; } //68 68: SignedInt: 0: boneTag + public float scale { get; set; } //72 72: Float: 0: scale + public int probability { get; set; } //76 76: SignedInt: 0: probability + public int flags { get; set; } //80 80: SignedInt: 0: flags + public uint color { get; set; } //84 84: UnsignedInt: 0: color + public uint Unused4 { get; set; }//88 + public uint Unused5 { get; set; }//92 + + public override string ToString() + { + return "CExtensionDefParticleEffect - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefParticleEffect : MetaWrapper + { + public CExtensionDefParticleEffect _Data; + public CExtensionDefParticleEffect Data { get { return _Data; } } + + public string fxName { get; set; } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + fxName = MetaTypes.GetString(meta, _Data.fxName); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + if (fxName != null) + { + _Data.fxName = mb.AddStringPtr(fxName); + } + + mb.AddStructureInfo(MetaName.CExtensionDefParticleEffect); + return mb.AddItemPtr(MetaName.CExtensionDefParticleEffect, _Data); + } + + public override string Name + { + get + { + return fxName; + } + } + + public override string ToString() + { + return _Data.ToString() + " - " + fxName; + } + } + + [TC(typeof(EXP))] public struct CExtensionDefLightEffect //48 bytes, Key:2436199897 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public Array_Structure instances { get; set; } //32 32: Array: 0: 274177522 {0: Structure: CLightAttrDef: 256} + + public override string ToString() + { + return "CExtensionDefLightEffect - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefLightEffect : MetaWrapper + { + public CExtensionDefLightEffect _Data; + public CExtensionDefLightEffect Data { get { return _Data; } } + + public CLightAttrDef[] instances { get; set; } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + instances = MetaTypes.ConvertDataArray(meta, MetaName.CLightAttrDef, _Data.instances); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + if (instances != null) + { + _Data.instances = mb.AddItemArrayPtr(MetaName.CLightAttrDef, instances); + } + + mb.AddStructureInfo(MetaName.CLightAttrDef); + mb.AddStructureInfo(MetaName.CExtensionDefLightEffect); + return mb.AddItemPtr(MetaName.CExtensionDefLightEffect, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString() + " (" + (instances?.Length ?? 0).ToString() + " Attributes)"; + } + } + + [TC(typeof(EXP))] public struct CExtensionDefAudioCollisionSettings //48 bytes, Key:2701897500 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public MetaHash settings { get; set; } //32 32: Hash: 0: settings + public uint Unused4 { get; set; }//36 + public uint Unused5 { get; set; }//40 + public uint Unused6 { get; set; }//44 + + public override string ToString() + { + return "CExtensionDefAudioCollisionSettings - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefAudioCollisionSettings : MetaWrapper + { + public CExtensionDefAudioCollisionSettings _Data; + public CExtensionDefAudioCollisionSettings Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CExtensionDefAudioCollisionSettings); + return mb.AddItemPtr(MetaName.CExtensionDefAudioCollisionSettings, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefAudioEmitter //64 bytes, Key:15929839 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public Vector4 offsetRotation { get; set; } //32 32: Float_XYZW: 0: offsetRotation + public MetaHash effectHash { get; set; } //48 48: UnsignedInt: 0: effectHash//2982223448 + public uint Unused4 { get; set; }//52 + public uint Unused5 { get; set; }//56 + public uint Unused6 { get; set; }//60 + + public override string ToString() + { + return "CExtensionDefAudioEmitter - " + name.ToString() + ": " + effectHash.ToString() + ": " + offsetPosition.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefAudioEmitter : MetaWrapper + { + public CExtensionDefAudioEmitter _Data; + public CExtensionDefAudioEmitter Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CExtensionDefAudioEmitter); + return mb.AddItemPtr(MetaName.CExtensionDefAudioEmitter, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefExplosionEffect //80 bytes, Key:2840366784 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public Vector4 offsetRotation { get; set; } //32 32: Float_XYZW: 0: offsetRotation + public CharPointer explosionName { get; set; } //48 48: CharPointer: 0: explosionName//3301388915 + public int boneTag { get; set; } //64 64: SignedInt: 0: boneTag + public int explosionTag { get; set; } //68 68: SignedInt: 0: explosionTag//2653034051 + public int explosionType { get; set; } //72 72: SignedInt: 0: explosionType//3379115010 + public uint flags { get; set; } //76 76: UnsignedInt: 0: flags + + public override string ToString() + { + return "CExtensionDefExplosionEffect - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefExplosionEffect : MetaWrapper + { + public CExtensionDefExplosionEffect _Data; + public CExtensionDefExplosionEffect Data { get { return _Data; } } + + public string explosionName { get; set; } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + explosionName = MetaTypes.GetString(meta, _Data.explosionName); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + if (explosionName != null) + { + _Data.explosionName = mb.AddStringPtr(explosionName); + } + mb.AddStructureInfo(MetaName.CExtensionDefExplosionEffect); + return mb.AddItemPtr(MetaName.CExtensionDefExplosionEffect, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString() + " - " + explosionName; + } + } + + [TC(typeof(EXP))] public struct CExtensionDefLadder //96 bytes, Key:1978210597 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public Vector3 bottom { get; set; } //32 32: Float_XYZ: 0: bottom + public float Unused4 { get; set; }//44 + public Vector3 top { get; set; } //48 48: Float_XYZ: 0: top + public float Unused5 { get; set; }//60 + public Vector3 normal { get; set; } //64 64: Float_XYZ: 0: normal + public float Unused6 { get; set; }//76 + public Unk_1294270217 materialType { get; set; } //80 80: IntEnum: 1294270217: materialType//932754174 + public MetaHash template { get; set; } //84 84: Hash: 0: template + public byte canGetOffAtTop { get; set; } //88 88: Boolean: 0: canGetOffAtTop//564839673 + public byte canGetOffAtBottom { get; set; } //89 89: Boolean: 0: canGetOffAtBottom//923729576 + public ushort Unused7 { get; set; }//90 + public uint Unused8 { get; set; }//92 + + public override string ToString() + { + return "CExtensionDefLadder - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefLadder : MetaWrapper + { + public CExtensionDefLadder _Data; + public CExtensionDefLadder Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddEnumInfo((MetaName)1294270217); + mb.AddStructureInfo(MetaName.CExtensionDefLadder); + return mb.AddItemPtr(MetaName.CExtensionDefLadder, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefBuoyancy //32 bytes, Key:2383039928 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + + public override string ToString() + { + return "CExtensionDefBuoyancy - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefBuoyancy : MetaWrapper + { + public CExtensionDefBuoyancy _Data; + public CExtensionDefBuoyancy Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CExtensionDefBuoyancy); + return mb.AddItemPtr(MetaName.CExtensionDefBuoyancy, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefExpression //48 bytes, Key:24441706 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public MetaHash Unk_1095612811 { get; set; } //32 32: Hash: 0: 1095612811 + public MetaHash expressionName { get; set; } //36 36: Hash: 0: expressionName + public MetaHash Unk_2766477159 { get; set; } //40 40: Hash: 0: 2766477159 + public byte Unk_1562817888 { get; set; } //44 44: Boolean: 0: 1562817888 + public byte Unused4 { get; set; }//45 + public ushort Unused5 { get; set; }//46 + + public override string ToString() + { + return "CExtensionDefExpression - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefExpression : MetaWrapper + { + public CExtensionDefExpression _Data; + public CExtensionDefExpression Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CExtensionDefExpression); + return mb.AddItemPtr(MetaName.CExtensionDefExpression, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefLightShaft //176 bytes, Key:2526429398 + { + public uint Unused00 { get; set; }//0 + public uint Unused01 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused02 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused03 { get; set; }//28 + public Vector3 cornerA { get; set; } //32 32: Float_XYZ: 0: 3302595027 + public float Unused04 { get; set; }//44 + public Vector3 cornerB { get; set; } //48 48: Float_XYZ: 0: 2393877884 + public float Unused05 { get; set; }//60 + public Vector3 cornerC { get; set; } //64 64: Float_XYZ: 0: 2692731164 + public float Unused06 { get; set; }//76 + public Vector3 cornerD { get; set; } //80 80: Float_XYZ: 0: 4250372814 + public float Unused07 { get; set; }//92 + public Vector3 direction { get; set; } //96 96: Float_XYZ: 0: direction + public float Unused08 { get; set; }//108 + public float directionAmount { get; set; } //112 112: Float: 0: 1441249296 + public float length { get; set; } //116 116: Float: 0: length + public float Unk_1616789093 { get; set; } //120 120: Float: 0: 1616789093 + public float Unk_120454521 { get; set; } //124 124: Float: 0: 120454521 + public float Unk_1297365553 { get; set; } //128 128: Float: 0: 1297365553 + public float Unk_75548206 { get; set; } //132 132: Float: 0: 75548206 + public float Unk_40301253 { get; set; } //136 136: Float: 0: 40301253 + public float Unk_475013030 { get; set; } //140 140: Float: 0: 475013030 + public uint color { get; set; } //144 144: UnsignedInt: 0: color + public float intensity { get; set; } //148 148: Float: 0: intensity + public byte flashiness { get; set; } //152 152: UnsignedByte: 0: 3829693202 + public byte Unused09 { get; set; }//153 + public ushort Unused10 { get; set; }//154 + public uint flags { get; set; } //156 156: UnsignedInt: 0: flags + public Unk_1931949281 densityType { get; set; } //160 160: IntEnum: 1931949281: densityType//235100599 + public Unk_2266515059 volumeType { get; set; } //164 164: IntEnum: 2266515059: volumeType//4021175589 + public float softness { get; set; } //168 168: Float: 0: softness//187712958 + public byte Unk_59101696 { get; set; } //172 172: Boolean: 0: 59101696 + public byte Unused11 { get; set; }//173 + public ushort Unused12 { get; set; }//174 + + public override string ToString() + { + return "CExtensionDefLightShaft - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefLightShaft : MetaWrapper + { + public CExtensionDefLightShaft _Data; + public CExtensionDefLightShaft Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddEnumInfo((MetaName)1931949281); + mb.AddEnumInfo((MetaName)2266515059); + mb.AddStructureInfo(MetaName.CExtensionDefLightShaft); + return mb.AddItemPtr(MetaName.CExtensionDefLightShaft, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefDoor //48 bytes, Key:2671601385 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public byte enableLimitAngle { get; set; } //32 32: Boolean: 0: enableLimitAngle=1979299226 + public byte startsLocked { get; set; } //33 33: Boolean: 0: startsLocked=3204572347 + public byte canBreak { get; set; } //34 34: Boolean: 0: canBreak=2756786344 + public byte Unused4 { get; set; }//35 + public float limitAngle { get; set; } //36 36: Float: 0: limitAngle + public float doorTargetRatio { get; set; } //40 40: Float: 0: doorTargetRatio=770433283 + public MetaHash audioHash { get; set; } //44 44: Hash: 0: audioHash=224069936 + + public override string ToString() + { + return "CExtensionDefDoor - " + name.ToString() + ", " + audioHash.ToString() + ", " + offsetPosition.ToString() + ", " + limitAngle.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefDoor : MetaWrapper + { + public CExtensionDefDoor _Data; + public CExtensionDefDoor Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CExtensionDefDoor); + return mb.AddItemPtr(MetaName.CExtensionDefDoor, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefSpawnPoint //96 bytes, Key:3077340721 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public Vector4 offsetRotation { get; set; } //32 32: Float_XYZW: 0: offsetRotation + public MetaHash spawnType { get; set; } //48 48: Hash: 0: spawnType + public MetaHash pedType { get; set; } //52 52: Hash: 0: pedType + public MetaHash group { get; set; } //56 56: Hash: 0: group + public MetaHash interior { get; set; } //60 60: Hash: 0: interior + public MetaHash requiredImap { get; set; } //64 64: Hash: 0: requiredImap + public Unk_3573596290 availableInMpSp { get; set; } //68 68: IntEnum: 3573596290: availableInMpSp + public float probability { get; set; } //72 72: Float: 0: probability + public float timeTillPedLeaves { get; set; } //76 76: Float: 0: timeTillPedLeaves + public float radius { get; set; } //80 80: Float: 0: radius + public byte start { get; set; } //84 84: UnsignedByte: 0: start + public byte end { get; set; } //85 85: UnsignedByte: 0: end + public ushort Unused4 { get; set; }//86 + public Unk_700327466 flags { get; set; } //88 88: IntFlags2: 700327466: flags + public byte highPri { get; set; } //92 92: Boolean: 0: highPri + public byte extendedRange { get; set; } //93 93: Boolean: 0: extendedRange + public byte shortRange { get; set; } //94 94: Boolean: 0: shortRange + public byte Unused5 { get; set; }//95 + + public override string ToString() + { + return spawnType.ToString() + ": " + name.ToString() + ", " + pedType.ToString();// + ", " + flags.ToString() + ", " + offsetPosition.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefSpawnPoint : MetaWrapper + { + [TC(typeof(EXP))] public object Parent { get; set; } + public MCScenarioPointRegion ScenarioRegion { get; private set; } + + public CExtensionDefSpawnPoint _Data; + public CExtensionDefSpawnPoint Data { get { return _Data; } } + + public Vector3 ParentPosition { get; set; } = Vector3.Zero; + public Vector3 OffsetPosition { get { return _Data.offsetPosition; } set { _Data.offsetPosition = value; } } + public Vector4 OffsetRotation { get { return _Data.offsetRotation; } set { _Data.offsetRotation = value; } } + public MetaHash NameHash { get { return _Data.name; } set { _Data.name = value; } } + public MetaHash SpawnType { get { return _Data.spawnType; } set { _Data.spawnType = value; } } + public MetaHash PedType { get { return _Data.pedType; } set { _Data.pedType = value; } } + public MetaHash Group { get { return _Data.group; } set { _Data.group = value; } } + public MetaHash Interior { get { return _Data.interior; } set { _Data.interior = value; } } + public MetaHash RequiredImap { get { return _Data.requiredImap; } set { _Data.requiredImap = value; } } + public Unk_3573596290 AvailableInMpSp { get { return _Data.availableInMpSp; } set { _Data.availableInMpSp = value; } } + public float Probability { get { return _Data.probability; } set { _Data.probability = value; } } + public float TimeTillPedLeaves { get { return _Data.timeTillPedLeaves; } set { _Data.timeTillPedLeaves = value; } } + public float Radius { get { return _Data.radius; } set { _Data.radius = value; } } + public byte StartTime { get { return _Data.start; } set { _Data.start = value; } } + public byte EndTime { get { return _Data.end; } set { _Data.end = value; } } + public Unk_700327466 Flags { get { return _Data.flags; } set { _Data.flags = value; } } + public bool HighPri { get { return _Data.highPri == 1; } set { _Data.highPri = (byte)(value ? 1 : 0); } } + public bool ExtendedRange { get { return _Data.extendedRange == 1; } set { _Data.extendedRange = (byte)(value ? 1 : 0); } } + public bool ShortRange { get { return _Data.shortRange == 1; } set { _Data.shortRange = (byte)(value ? 1 : 0); } } + + public Vector3 Position { get { return _Data.offsetPosition + ParentPosition; } set { _Data.offsetPosition = value - ParentPosition; } } + public Quaternion Orientation { get { return new Quaternion(_Data.offsetRotation); } set { _Data.offsetRotation = value.ToVector4(); } } + + public MCExtensionDefSpawnPoint() { } + public MCExtensionDefSpawnPoint(MCScenarioPointRegion region, Meta meta, CExtensionDefSpawnPoint data, object parent) + { + ScenarioRegion = region; + Parent = parent; + _Data = data; + } + public MCExtensionDefSpawnPoint(MCScenarioPointRegion region, MCExtensionDefSpawnPoint copy) + { + ScenarioRegion = region; + if (copy != null) + { + _Data = copy.Data; + Parent = copy.Parent; + ParentPosition = copy.ParentPosition; + } + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddEnumInfo((MetaName)3573596290); + mb.AddEnumInfo((MetaName)700327466); + mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint); + return mb.AddItemPtr(MetaName.CExtensionDefSpawnPoint, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefSpawnPointOverride //64 bytes, Key:2551875873 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public MetaHash ScenarioType { get; set; } //32 32: Hash: 0: ScenarioType + public byte iTimeStartOverride { get; set; } //36 36: UnsignedByte: 0: iTimeStartOverride//591476992 + public byte iTimeEndOverride { get; set; } //37 37: UnsignedByte: 0: iTimeEndOverride//2688038523 + public ushort Unused4 { get; set; }//38 + public MetaHash Group { get; set; } //40 40: Hash: 0: Group + public MetaHash ModelSet { get; set; } //44 44: Hash: 0: ModelSet + public Unk_3573596290 AvailabilityInMpSp { get; set; } //48 48: IntEnum: 3573596290: AvailabilityInMpSp//2932681318 + public Unk_700327466 Flags { get; set; } //52 52: IntFlags2: 700327466: Flags + public float Radius { get; set; } //56 56: Float: 0: Radius + public float TimeTillPedLeaves { get; set; } //60 60: Float: 0: TimeTillPedLeaves//4073598194 + + public override string ToString() + { + return "CExtensionDefSpawnPointOverride - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefSpawnPointOverride : MetaWrapper + { + public CExtensionDefSpawnPointOverride _Data; + public CExtensionDefSpawnPointOverride Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddEnumInfo((MetaName)3573596290); + mb.AddEnumInfo((MetaName)700327466); + mb.AddStructureInfo(MetaName.CExtensionDefSpawnPointOverride); + return mb.AddItemPtr(MetaName.CExtensionDefSpawnPointOverride, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefWindDisturbance //96 bytes, Key:3971538917 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public Vector4 offsetRotation { get; set; } //32 32: Float_XYZW: 0: offsetRotation + public int disturbanceType { get; set; } //48 48: SignedInt: 0: disturbanceType//3802708370 + public int boneTag { get; set; } //52 52: SignedInt: 0: boneTag + public uint Unused4 { get; set; }//56 + public uint Unused5 { get; set; }//60 + public Vector4 size { get; set; } //64 64: Float_XYZW: 0: size + public float strength { get; set; } //80 80: Float: 0: strength + public int flags { get; set; } //84 84: SignedInt: 0: flags + public uint Unused6 { get; set; }//88 + public uint Unused7 { get; set; }//92 + + public override string ToString() + { + return "CExtensionDefWindDisturbance - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefWindDisturbance : MetaWrapper + { + public CExtensionDefWindDisturbance _Data; + public CExtensionDefWindDisturbance Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CExtensionDefWindDisturbance); + return mb.AddItemPtr(MetaName.CExtensionDefWindDisturbance, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CExtensionDefProcObject //80 bytes, Key:3965391891 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public MetaHash name { get; set; } //8 8: Hash: 0: name + public uint Unused2 { get; set; }//12 + public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition + public float Unused3 { get; set; }//28 + public float radiusInner { get; set; } //32 32: Float: 0: radiusInner//406390660 + public float radiusOuter { get; set; } //36 36: Float: 0: radiusOuter//1814053978 + public float spacing { get; set; } //40 40: Float: 0: spacing + public float minScale { get; set; } //44 44: Float: 0: minScale//3662913353 + public float maxScale { get; set; } //48 48: Float: 0: maxScale//803384552 + public float Unk_3913056845 { get; set; } //52 52: Float: 0: 3913056845 + public float Unk_147400493 { get; set; } //56 56: Float: 0: 147400493 + public float Unk_2591582364 { get; set; } //60 60: Float: 0: 2591582364 + public float Unk_3889902555 { get; set; } //64 64: Float: 0: 3889902555 + public uint objectHash { get; set; } //68 68: UnsignedInt: 0: objectHash//1951307499 + public uint flags { get; set; } //72 72: UnsignedInt: 0: flags + public uint Unused4 { get; set; }//76 + + public override string ToString() + { + return "CExtensionDefProcObject - " + name.ToString(); + } + } + [TC(typeof(EXP))] public class MCExtensionDefProcObject : MetaWrapper + { + public CExtensionDefProcObject _Data; + public CExtensionDefProcObject Data { get { return _Data; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CExtensionDefProcObject); + return mb.AddItemPtr(MetaName.CExtensionDefProcObject, _Data); + } + + public override string Name + { + get + { + return _Data.name.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + + + + + + + [TC(typeof(EXP))] public struct CScenarioPointRegion //SCENARIO YMT ROOT - in /scenario/ folder //376 bytes, Key:3501351821 + { + public int VersionNumber { get; set; } //0 0: SignedInt: 0: VersionNumber + public uint Unused0 { get; set; }//4 + public CScenarioPointContainer Points { get; set; } //8 8: Structure: CScenarioPointContainer//2380938603: Points//702683191 + public uint Unused1 { get; set; }//56 + public uint Unused2 { get; set; }//60 + public uint Unused3 { get; set; }//64 + public uint Unused4 { get; set; }//68 + public Array_Structure EntityOverrides { get; set; } //72 72: Array: 0: EntityOverrides//697469539 {0: Structure: CScenarioEntityOverride//4213733800: 256} + public uint Unused5 { get; set; }//88 + public uint Unused6 { get; set; }//92 + public Unk_4023740759 Unk_3696045377 { get; set; } //[PATHS] 96 96: Structure: 4023740759: 3696045377 + public rage__spdGrid2D AccelGrid { get; set; } //184 184: Structure: rage__spdGrid2D: AccelGrid//3053155275 + public Array_ushort Unk_3844724227 { get; set; } //248 248: Array: 0: 3844724227 {0: UnsignedShort: 0: 256} + public Array_Structure Clusters { get; set; } //264 264: Array: 0: Clusters//3587988394 {0: Structure: CScenarioPointCluster//750308016: 256} + public CScenarioPointLookUps LookUps { get; set; } //280 280: Structure: CScenarioPointLookUps//3019621867: LookUps//1097626284 + } + [TC(typeof(EXP))] public class MCScenarioPointRegion : MetaWrapper + { + public YmtFile Ymt { get; set; } + + public CScenarioPointRegion _Data; + public CScenarioPointRegion Data { get { return _Data; } } + + public MCScenarioPointContainer Points { get; set; } + public MCScenarioEntityOverride[] EntityOverrides { get; set; } + public MUnk_4023740759 Paths { get; set; } + public ushort[] Unk_3844724227 { get; set; } //GRID DATA - 2d dimensions - AccelGrid ((MaxX-MinX)+1)*((MaxY-MinY)+1) + public MCScenarioPointCluster[] Clusters { get; set; } + public MCScenarioPointLookUps LookUps { get; set; } + + public int VersionNumber { get { return _Data.VersionNumber; } set { _Data.VersionNumber = value; } } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + var data = MetaTypes.GetData(meta, ptr); + Load(meta, data); + } + public void Load(Meta meta, CScenarioPointRegion data) + { + _Data = data; + + + Points = new MCScenarioPointContainer(this, meta, _Data.Points); + + + var entOverrides = MetaTypes.ConvertDataArray(meta, MetaName.CScenarioEntityOverride, _Data.EntityOverrides); + if (entOverrides != null) + { + EntityOverrides = new MCScenarioEntityOverride[entOverrides.Length]; + for (int i = 0; i < entOverrides.Length; i++) + { + EntityOverrides[i] = new MCScenarioEntityOverride(this, meta, entOverrides[i]); + } + } + + + Paths = new MUnk_4023740759(this, meta, _Data.Unk_3696045377); + + + var clusters = MetaTypes.ConvertDataArray(meta, MetaName.CScenarioPointCluster, _Data.Clusters); + if (clusters != null) + { + Clusters = new MCScenarioPointCluster[clusters.Length]; + for (int i = 0; i < clusters.Length; i++) + { + Clusters[i] = new MCScenarioPointCluster(this, meta, clusters[i]); + } + } + + Unk_3844724227 = MetaTypes.GetUshortArray(meta, _Data.Unk_3844724227); + + LookUps = new MCScenarioPointLookUps(this, meta, _Data.LookUps); + + + #region data analysis + ////data analysis + //if (Points.LoadSavePoints != null) + //{ } //no hits here! + //if (Unk_3844724227 != null) + //{ + // var grid = _Data.AccelGrid; + // var minx = grid.Unk_MinX_860552138; + // var maxx = grid.Unk_MaxX_3824598937; + // var miny = grid.Unk_MinY_496029782; + // var maxy = grid.Unk_MaxY_3374647798; + // var len = Unk_3844724227.Length; + // var calclen = ((maxx - minx) + 1) * ((maxy - miny) + 1); + // if (len != calclen) + // { } //no hits here! + // int pointcount = 0; + // if (Points.MyPoints != null) pointcount += Points.MyPoints.Length; + // //if (Points.LoadSavePoints != null) pointcount += Points.LoadSavePoints.Length;//not necessary! + // int lastuval = 0; + // for (int i = 0; i < Unk_3844724227.Length; i++) + // { + // var uval = Unk_3844724227[i]; + // var uval2 = uval & 0x7FFF; + // var uval3 = uval >> 15; //what does this bit mean? + // if (uval3 > 0) + // { } + // lastuval = uval2; + // if (uval2 > pointcount) + // { } //no hits here! + // } + // if (lastuval != pointcount) + // { } //no hits here! + //} + #endregion + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + + var sprb = mb.EnsureBlock(MetaName.CScenarioPointRegion); + //var hashb = mb.EnsureBlock(MetaName.HASH); + //var ushb = mb.EnsureBlock(MetaName.USHORT); + //var pntb = mb.EnsureBlock(MetaName.CScenarioPoint); + + mb.AddStructureInfo(MetaName.CScenarioPointContainer); + mb.AddStructureInfo((MetaName)4023740759); + mb.AddStructureInfo(MetaName.rage__spdGrid2D); + mb.AddStructureInfo(MetaName.CScenarioPointLookUps); + mb.AddStructureInfo(MetaName.CScenarioPointRegion); + + + if (Points != null) + { + var scp = new CScenarioPointContainer(); + + var loadSavePoints = Points.GetCLoadSavePoints(); + if (loadSavePoints != null)//this never seems to be used... + { + mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint); + mb.AddEnumInfo((MetaName)3573596290); + mb.AddEnumInfo((MetaName)700327466); + scp.LoadSavePoints = mb.AddItemArrayPtr(MetaName.CExtensionDefSpawnPoint, loadSavePoints); + } + var myPoints = Points.GetCMyPoints(); + if (myPoints != null) + { + mb.AddStructureInfo(MetaName.CScenarioPoint); + mb.AddEnumInfo((MetaName)700327466); + scp.MyPoints = mb.AddItemArrayPtr(MetaName.CScenarioPoint, myPoints); + } + + _Data.Points = scp; + } + else + { + _Data.Points = new CScenarioPointContainer(); + } + + + if ((EntityOverrides != null) && (EntityOverrides.Length > 0)) + { + //mb.AddStructureInfo(MetaName.CScenarioEntityOverride); //will get added by MCScenarioEntityOverride + //mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint); + _Data.EntityOverrides = mb.AddWrapperArray(EntityOverrides); + } + else + { + _Data.EntityOverrides = new Array_Structure(); + } + + + if (Paths != null) + { + var pd = new Unk_4023740759(); + + var nodes = Paths.GetCNodes(); + if (nodes != null) + { + mb.AddStructureInfo(MetaName.CScenarioChainingNode); + pd.Nodes = mb.AddItemArrayPtr(MetaName.CScenarioChainingNode, nodes); + } + var edges = Paths.GetCEdges(); + if (edges != null) + { + mb.AddStructureInfo(MetaName.CScenarioChainingEdge); + mb.AddEnumInfo((MetaName)3609807418); + mb.AddEnumInfo((MetaName)3971773454); + mb.AddEnumInfo((MetaName)941086046); + pd.Edges = mb.AddItemArrayPtr(MetaName.CScenarioChainingEdge, edges); + } + if (Paths.Chains != null) + { + foreach (var chain in Paths.Chains) + { + if (chain.EdgeIds != null) + { + chain._Data.EdgeIds = mb.AddUshortArrayPtr(chain.EdgeIds); + } + else + { + chain._Data.EdgeIds = new Array_ushort(); + } + } + } + var chains = Paths.GetCChains(); + if (chains != null) + { + mb.AddStructureInfo(MetaName.CScenarioChain); + pd.Chains = mb.AddItemArrayPtr(MetaName.CScenarioChain, chains); + } + + _Data.Unk_3696045377 = pd; + } + else + { + _Data.Unk_3696045377 = new Unk_4023740759(); + } + + + if ((Clusters != null) && (Clusters.Length > 0)) + { + //mb.AddStructureInfo(MetaName.rage__spdSphere); + //mb.AddStructureInfo(MetaName.CScenarioPointCluster); + _Data.Clusters = mb.AddWrapperArray(Clusters); + } + else + { + _Data.Clusters = new Array_Structure(); + } + + + if ((Unk_3844724227 != null) && (Unk_3844724227.Length > 0)) + { + _Data.Unk_3844724227 = mb.AddUshortArrayPtr(Unk_3844724227); + } + else + { + _Data.Unk_3844724227 = new Array_ushort(); + } + + + if (LookUps != null) + { + var spl = new CScenarioPointLookUps(); + if ((LookUps.TypeNames != null) && (LookUps.TypeNames.Length > 0)) + { + spl.TypeNames = mb.AddHashArrayPtr(LookUps.TypeNames); + } + if ((LookUps.PedModelSetNames != null) && (LookUps.PedModelSetNames.Length > 0)) + { + spl.PedModelSetNames = mb.AddHashArrayPtr(LookUps.PedModelSetNames); + } + if ((LookUps.VehicleModelSetNames != null) && (LookUps.VehicleModelSetNames.Length > 0)) + { + spl.VehicleModelSetNames = mb.AddHashArrayPtr(LookUps.VehicleModelSetNames); + } + if ((LookUps.GroupNames != null) && (LookUps.GroupNames.Length > 0)) + { + spl.GroupNames = mb.AddHashArrayPtr(LookUps.GroupNames); + } + if ((LookUps.InteriorNames != null) && (LookUps.InteriorNames.Length > 0)) + { + spl.InteriorNames = mb.AddHashArrayPtr(LookUps.InteriorNames); + } + if ((LookUps.RequiredIMapNames != null) && (LookUps.RequiredIMapNames.Length > 0)) + { + spl.RequiredIMapNames = mb.AddHashArrayPtr(LookUps.RequiredIMapNames); + } + _Data.LookUps = spl; + } + else + { + _Data.LookUps = new CScenarioPointLookUps(); //this shouldn't happen... + } + + + return mb.AddItemPtr(MetaName.CScenarioPointRegion, _Data); + } + + + + public void AddCluster(MCScenarioPointCluster cluster) + { + List newclusters = new List(); + if (Clusters != null) + { + newclusters.AddRange(Clusters); + } + cluster.Region = this; + //cluster.ClusterIndex = newclusters.Count; + newclusters.Add(cluster); + Clusters = newclusters.ToArray(); + } + public void AddEntity(MCScenarioEntityOverride ent) + { + List newents = new List(); + if (EntityOverrides != null) + { + newents.AddRange(EntityOverrides); + } + ent.Region = this; + //ent.EntityIndex = newents.Count; + newents.Add(ent); + EntityOverrides = newents.ToArray(); + } + + public bool RemoveCluster(MCScenarioPointCluster cluster) + { + bool r = false; + if (Clusters != null) + { + List newclusters = new List(); + foreach (var nc in Clusters) + { + if (nc == cluster) + { + r = true; + } + else + { + //nc.ClusterIndex = newclusters.Count; + newclusters.Add(nc); + } + } + if (r) + { + Clusters = newclusters.ToArray(); + } + } + return r; + } + public bool RemoveEntity(MCScenarioEntityOverride ent) + { + bool r = false; + if (EntityOverrides != null) + { + List newents = new List(); + foreach (var nc in EntityOverrides) + { + if (nc == ent) + { + r = true; + } + else + { + //nc.EntityIndex = newents.Count; + newents.Add(nc); + } + } + if (r) + { + EntityOverrides = newents.ToArray(); + } + } + return r; + } + + + + public override string Name + { + get + { + return Ymt?.ToString() ?? "CScenarioPointRegion"; + } + } + + public override string ToString() + { + return Name; + } + + } + + [TC(typeof(EXP))] public struct CScenarioPointContainer //SCENARIO Region Points arrays // 48 bytes, Key:2489654897 + { + public Array_Structure LoadSavePoints { get; set; } //0 0: Array: 0: LoadSavePoints//3016741991 {0: Structure: CExtensionDefSpawnPoint: 256} + public Array_Structure MyPoints { get; set; } //16 16: Array: 0: MyPoints//1170781136 {0: Structure: CScenarioPoint//4103049490: 256} + public uint Unused0 { get; set; }//32 + public uint Unused1 { get; set; }//36 + public uint Unused2 { get; set; }//40 + public uint Unused3 { get; set; }//44 + + public override string ToString() + { + return LoadSavePoints.Count1.ToString() + " LoadSavePoints, " + MyPoints.Count1.ToString() + " MyPoints"; + } + } + [TC(typeof(EXP))] public class MCScenarioPointContainer : MetaWrapper + { + [TC(typeof(EXP))] public object Parent { get; set; } + public MCScenarioPointRegion Region { get; private set; } + + public CScenarioPointContainer _Data; + public CScenarioPointContainer Data { get { return _Data; } set { _Data = value; } } + + public MCExtensionDefSpawnPoint[] LoadSavePoints { get; set; } + public MCScenarioPoint[] MyPoints { get; set; } + + + + public MCScenarioPointContainer() { } + public MCScenarioPointContainer(MCScenarioPointRegion region) + { + Region = region; + } + public MCScenarioPointContainer(MCScenarioPointRegion region, Meta meta, CScenarioPointContainer d) + { + Region = region; + _Data = d; + Init(meta); + } + + public void Init(Meta meta) + { + var vLoadSavePoints = MetaTypes.ConvertDataArray(meta, MetaName.CExtensionDefSpawnPoint, _Data.LoadSavePoints); + if (vLoadSavePoints != null) + { + LoadSavePoints = new MCExtensionDefSpawnPoint[vLoadSavePoints.Length]; + for (int i = 0; i < vLoadSavePoints.Length; i++) + { + LoadSavePoints[i] = new MCExtensionDefSpawnPoint(Region, meta, vLoadSavePoints[i], this); + } + } + + var vMyPoints = MetaTypes.ConvertDataArray(meta, MetaName.CScenarioPoint, _Data.MyPoints); + if (vMyPoints != null) + { + MyPoints = new MCScenarioPoint[vMyPoints.Length]; + for (int i = 0; i < vMyPoints.Length; i++) + { + MyPoints[i] = new MCScenarioPoint(Region, meta, vMyPoints[i], this); + MyPoints[i].PointIndex = i; + } + } + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + Init(meta); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CScenarioPointContainer); + return mb.AddItemPtr(MetaName.CScenarioPointContainer, _Data); + } + + + public CExtensionDefSpawnPoint[] GetCLoadSavePoints() + { + if ((LoadSavePoints == null) || (LoadSavePoints.Length == 0)) return null; + CExtensionDefSpawnPoint[] r = new CExtensionDefSpawnPoint[LoadSavePoints.Length]; + for (int i = 0; i < LoadSavePoints.Length; i++) + { + r[i] = LoadSavePoints[i].Data; + } + return r; + } + public CScenarioPoint[] GetCMyPoints() + { + if ((MyPoints == null) || (MyPoints.Length == 0)) return null; + CScenarioPoint[] r = new CScenarioPoint[MyPoints.Length]; + for (int i = 0; i < MyPoints.Length; i++) + { + r[i] = MyPoints[i].Data; + } + return r; + } + + public void AddMyPoint(MCScenarioPoint p) + { + List newpoints = new List(); + if (MyPoints != null) + { + newpoints.AddRange(MyPoints); + } + p.PointIndex = newpoints.Count; + newpoints.Add(p); + p.Container = this; + MyPoints = newpoints.ToArray(); + } + public void AddLoadSavePoint(MCExtensionDefSpawnPoint p) + { + List newpoints = new List(); + if (LoadSavePoints != null) + { + newpoints.AddRange(LoadSavePoints); + } + newpoints.Add(p); + p.Parent = this; + LoadSavePoints = newpoints.ToArray(); + } + + public bool RemoveMyPoint(MCScenarioPoint p) + { + bool r = false; + if (MyPoints != null) + { + List newpoints = new List(); + foreach (var mp in MyPoints) + { + if (mp == p) + { + r = true; + } + else + { + newpoints.Add(mp); + } + } + if (r) + { + MyPoints = newpoints.ToArray(); + + for (int i = 0; i < MyPoints.Length; i++) + { + MyPoints[i].PointIndex = i; + } + } + } + return r; + } + public bool RemoveLoadSavePoint(MCExtensionDefSpawnPoint p) + { + bool r = false; + if (LoadSavePoints != null) + { + List newpoints = new List(); + foreach (var mp in LoadSavePoints) + { + if (mp == p) + { + r = true; + } + else + { + newpoints.Add(mp); + } + } + if (r) + { + LoadSavePoints = newpoints.ToArray(); + } + } + return r; + } + + + + public override string Name + { + get + { + return "CScenarioPointContainer"; + } + } + + public override string ToString() + { + return _Data.ToString(); + } + + } + + [TC(typeof(EXP))] public struct CScenarioPoint //SCENARIO Point, similar to CExtensionDefSpawnPointOverride //64 bytes, Key:402442150 + { + public uint Unused0 { get; set; }//0 + public uint Unused1 { get; set; }//4 + public uint Unused2 { get; set; }//8 + public uint Unused3 { get; set; }//12 + public uint Unused4 { get; set; }//16 + public byte Unused5 { get; set; }//20 + public byte iType { get; set; } //21 21: UnsignedByte: 0: iType + public byte ModelSetId { get; set; } //22 22: UnsignedByte: 0: ModelSetId//3361647288 + public byte iInterior { get; set; } //23 23: UnsignedByte: 0: 1975994103 + public byte iRequiredIMapId { get; set; } //24 24: UnsignedByte: 0: iRequiredIMapId//1229525587 + public byte iProbability { get; set; } //25 25: UnsignedByte: 0: iProbability//2974610960 + public byte Unk_717991212_SpOnly { get; set; } //26 26: UnsignedByte: 0: 717991212 // animal point, or a ped with a pet? + public byte iTimeStartOverride { get; set; } //27 27: UnsignedByte: 0: 591476992 + public byte iTimeEndOverride { get; set; } //28 28: UnsignedByte: 0: 2688038523 + public byte iRadius { get; set; } //29 29: UnsignedByte: 0: iRadius + public byte iTimeTillPedLeaves { get; set; } //30 30: UnsignedByte: 0: 2296188475 //in game minutes? + public byte Unused6 { get; set; }//31 + public ushort iScenarioGroup { get; set; } //32 32: UnsignedShort: 0: iScenarioGroup//2180252673 + public ushort Unused7 { get; set; }//34 + public Unk_700327466 Flags { get; set; } //36 36: IntFlags2: 700327466: Flags + public uint Unused8 { get; set; }//40 + public uint Unused9 { get; set; }//44 + public Vector4 vPositionAndDirection { get; set; } //48 48: Float_XYZW: 0: vPositionAndDirection//4685037 + + public override string ToString() + { + return FloatUtil.GetVector4String(vPositionAndDirection); //iTimeStartOverride.ToString() + "-" + iTimeEndOverride.ToString();// + ", " + Flags.ToString(); + } + } + [TC(typeof(EXP))] public class MCScenarioPoint : MetaWrapper + { + [TC(typeof(EXP))] public MCScenarioPointContainer Container { get; set; } + public MCScenarioPointRegion Region { get; set; } + + public CScenarioPoint _Data; + public CScenarioPoint Data { get { return _Data; } set { _Data = value; } } + + public Vector3 Position { get { return _Data.vPositionAndDirection.XYZ(); } set { _Data.vPositionAndDirection = new Vector4(value, Direction); } } + public float Direction { get { return _Data.vPositionAndDirection.W; } set { _Data.vPositionAndDirection = new Vector4(Position, value); } } + public Quaternion Orientation + { + get { return Quaternion.RotationAxis(Vector3.UnitZ, Direction); } + set + { + Vector3 dir = value.Multiply(Vector3.UnitX); + float dira = (float)Math.Atan2(dir.Y, dir.X); + Direction = dira; + } + } + + + public byte TypeId { get { return _Data.iType; } set { _Data.iType = value; } } + public ScenarioType Type { get; set; } + + public byte ModelSetId { get { return _Data.ModelSetId; } set { _Data.ModelSetId = value; } } + public AmbientModelSet ModelSet { get; set; } + + public byte InteriorId { get { return _Data.iInterior; } set { _Data.iInterior = value; } } + public MetaHash InteriorName { get; set; } + + public ushort GroupId { get { return _Data.iScenarioGroup; } set { _Data.iScenarioGroup = value; } } + public MetaHash GroupName { get; set; } + + public byte IMapId { get { return _Data.iRequiredIMapId; } set { _Data.iRequiredIMapId = value; } } + public MetaHash IMapName { get; set; } + + public string TimeRange { get { return _Data.iTimeStartOverride.ToString().PadLeft(2, '0') + ":00 - " + _Data.iTimeEndOverride.ToString().PadLeft(2, '0') + ":00"; } } + public byte TimeStart { get { return _Data.iTimeStartOverride; } set { _Data.iTimeStartOverride = value; } } + public byte TimeEnd { get { return _Data.iTimeEndOverride; } set { _Data.iTimeEndOverride = value; } } + public byte Probability { get { return _Data.iProbability; } set { _Data.iProbability = value; } } + public byte SpOnlyFlag { get { return _Data.Unk_717991212_SpOnly; } set { _Data.Unk_717991212_SpOnly = value; } } + public byte Radius { get { return _Data.iRadius; } set { _Data.iRadius = value; } } + public byte WaitTime { get { return _Data.iTimeTillPedLeaves; } set { _Data.iTimeTillPedLeaves = value; } } + public Unk_700327466 Flags { get { return _Data.Flags; } set { _Data.Flags = value; } } + + public int PointIndex { get; set; } + + + public MCScenarioPoint(MCScenarioPointRegion region) { Region = region; } + public MCScenarioPoint(MCScenarioPointRegion region, Meta meta, CScenarioPoint d, MCScenarioPointContainer container) + { + Region = region; + Container = container; + _Data = d; + } + public MCScenarioPoint(MCScenarioPointRegion region, MCScenarioPoint copy) + { + Region = region; + if (copy != null) + { + _Data = copy.Data; + Type = copy.Type; + ModelSet = copy.ModelSet; + InteriorName = copy.InteriorName; + GroupName = copy.GroupName; + IMapName = copy.IMapName; + } + } + + public void CopyFrom(MCScenarioPoint copy) + { + _Data = copy.Data; + Type = copy.Type; + ModelSet = copy.ModelSet; + InteriorName = copy.InteriorName; + GroupName = copy.GroupName; + IMapName = copy.IMapName; + } + + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CScenarioPoint); + return mb.AddItemPtr(MetaName.CScenarioPoint, _Data); + } + + public override string Name + { + get + { + return (Type?.ToString() ?? "") + ": " + (ModelSet?.ToString() ?? ""); + } + } + + public override string ToString() + { + return Name + ": " + TimeRange; + } + + } + + [TC(typeof(EXP))] public struct CScenarioEntityOverride //SCENARIO Entity Override //80 bytes, Key:1271200492 + { + public Vector3 EntityPosition { get; set; } //0 0: Float_XYZ: 0: EntityPosition//642078041 + public float Unused00 { get; set; }//12 + public MetaHash EntityType { get; set; } //16 16: Hash: 0: EntityType//1374199246 + public uint Unused01 { get; set; }//20 + public Array_Structure ScenarioPoints { get; set; } //24 24: Array: 0: ScenarioPoints {0: Structure: CExtensionDefSpawnPoint: 256} + public uint Unused02 { get; set; }//40 + public uint Unused03 { get; set; }//44 + public uint Unused04 { get; set; }//48 + public uint Unused05 { get; set; }//52 + public uint Unused06 { get; set; }//56 + public uint Unused07 { get; set; }//60 + public byte Unk_538733109 { get; set; } //64 64: Boolean: 0: 538733109 + public byte Unk_1035513142 { get; set; } //65 65: Boolean: 0: 1035513142 + public ushort Unused08 { get; set; }//66 + public uint Unused09 { get; set; }//68 + public uint Unused10 { get; set; }//72 + public uint Unused11 { get; set; }//76 + + public override string ToString() + { + return EntityType.ToString() + ", " + ScenarioPoints.Count1.ToString() + " ScenarioPoints"; + } + } + [TC(typeof(EXP))] public class MCScenarioEntityOverride : MetaWrapper + { + [TC(typeof(EXP))] public object Parent { get; set; } + public MCScenarioPointRegion Region { get; set; } + + public CScenarioEntityOverride _Data; + public CScenarioEntityOverride Data { get { return _Data; } set { _Data = value; } } + + public Vector3 Position { get { return _Data.EntityPosition; } set { _Data.EntityPosition = value; } } + + public MetaHash TypeName { get { return _Data.EntityType; } set { _Data.EntityType = value; } } + public byte Unk1 { get { return _Data.Unk_538733109; } set { _Data.Unk_538733109 = value; } } + public byte Unk2 { get { return _Data.Unk_1035513142; } set { _Data.Unk_1035513142 = value; } } + + + public MCExtensionDefSpawnPoint[] ScenarioPoints { get; set; } + + public MCScenarioEntityOverride() { } + public MCScenarioEntityOverride(MCScenarioPointRegion region, MCScenarioEntityOverride copy) + { + Region = region; + if (copy != null) + { + _Data = copy.Data; + } + } + public MCScenarioEntityOverride(MCScenarioPointRegion region, Meta meta, CScenarioEntityOverride d) + { + Region = region; + _Data = d; + Init(meta); + } + + public void Init(Meta meta) + { + + var scenarioPoints = MetaTypes.ConvertDataArray(meta, MetaName.CExtensionDefSpawnPoint, _Data.ScenarioPoints); + if (scenarioPoints != null) + { + ScenarioPoints = new MCExtensionDefSpawnPoint[scenarioPoints.Length]; + for (int i = 0; i < scenarioPoints.Length; i++) + { + ScenarioPoints[i] = new MCExtensionDefSpawnPoint(Region, meta, scenarioPoints[i], this); + ScenarioPoints[i].ParentPosition = Position; + } + } + + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + Init(meta); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CScenarioEntityOverride); + + if (ScenarioPoints != null) + { + mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint); + mb.AddEnumInfo((MetaName)3573596290); + mb.AddEnumInfo((MetaName)700327466); + _Data.ScenarioPoints = mb.AddWrapperArray(ScenarioPoints); + } + + return mb.AddItemPtr(MetaName.CScenarioEntityOverride, _Data); + } + + + public void AddScenarioPoint(MCExtensionDefSpawnPoint p) + { + List newpoints = new List(); + if (ScenarioPoints != null) + { + newpoints.AddRange(ScenarioPoints); + } + newpoints.Add(p); + p.Parent = this; + ScenarioPoints = newpoints.ToArray(); + } + public bool RemoveScenarioPoint(MCExtensionDefSpawnPoint p) + { + bool r = false; + if (ScenarioPoints != null) + { + List newpoints = new List(); + foreach (var mp in ScenarioPoints) + { + if (mp == p) + { + r = true; + } + else + { + newpoints.Add(mp); + } + } + if (r) + { + ScenarioPoints = newpoints.ToArray(); + } + } + return r; + } + + + + public override string Name + { + get + { + return "CScenarioEntityOverride " + _Data.EntityType.ToString(); + } + } + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct Unk_4023740759 //SCENARIO PATH ARRAYS //88 bytes, Key:88255871 + { + public Array_Structure Nodes { get; set; } //0 0: Array: 0: Nodes {0: Structure: CScenarioChainingNode//3340683255: 256} + public Array_Structure Edges { get; set; } //16 16: Array: 0: Edges {0: Structure: CScenarioChainingEdge//4255409560: 256} + public Array_Structure Chains { get; set; } //32 32: Array: 0: Chains {0: Structure: CScenarioChain: 256} + public uint Unused0 { get; set; }//48 + public uint Unused1 { get; set; }//52 + public uint Unused2 { get; set; }//56 + public uint Unused3 { get; set; }//60 + public uint Unused4 { get; set; }//64 + public uint Unused5 { get; set; }//68 + public uint Unused6 { get; set; }//72 + public uint Unused7 { get; set; }//76 + public uint Unused8 { get; set; }//80 + public uint Unused9 { get; set; }//84 + + public override string ToString() + { + return Nodes.Count1.ToString() + " Nodes, " + Edges.Count1.ToString() + " Edges, " + Chains.Count1.ToString() + " Chains"; + } + } + [TC(typeof(EXP))] public class MUnk_4023740759 : MetaWrapper + { + public MCScenarioPointRegion Region { get; private set; } + + public Unk_4023740759 _Data; + public Unk_4023740759 Data { get { return _Data; } set { _Data = value; } } + + public MCScenarioChainingNode[] Nodes { get; set; } + public MCScenarioChainingEdge[] Edges { get; set; } + public MCScenarioChain[] Chains { get; set; } + + public MUnk_4023740759() { } + public MUnk_4023740759(MCScenarioPointRegion region) { Region = region; } + public MUnk_4023740759(MCScenarioPointRegion region, Meta meta, Unk_4023740759 d) + { + Region = region; + _Data = d; + Init(meta); + } + + public void Init(Meta meta) + { + var pathnodes = MetaTypes.ConvertDataArray(meta, MetaName.CScenarioChainingNode, _Data.Nodes); + if (pathnodes != null) + { + Nodes = new MCScenarioChainingNode[pathnodes.Length]; + for (int i = 0; i < pathnodes.Length; i++) + { + Nodes[i] = new MCScenarioChainingNode(Region, meta, pathnodes[i], this, i); + } + } + + var pathedges = MetaTypes.ConvertDataArray(meta, MetaName.CScenarioChainingEdge, _Data.Edges); + if (pathedges != null) + { + Edges = new MCScenarioChainingEdge[pathedges.Length]; + for (int i = 0; i < pathedges.Length; i++) + { + Edges[i] = new MCScenarioChainingEdge(Region, meta, pathedges[i], i); + } + } + + var pathchains = MetaTypes.ConvertDataArray(meta, MetaName.CScenarioChain, _Data.Chains); + if (pathchains != null) + { + Chains = new MCScenarioChain[pathchains.Length]; + for (int i = 0; i < pathchains.Length; i++) + { + Chains[i] = new MCScenarioChain(Region, meta, pathchains[i]); + } + } + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + Init(meta); + } + + + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo((MetaName)4023740759); + return mb.AddItemPtr((MetaName)4023740759, _Data); + } + + + + + + + + public CScenarioChainingNode[] GetCNodes() + { + if ((Nodes == null) || (Nodes.Length == 0)) return null; + CScenarioChainingNode[] r = new CScenarioChainingNode[Nodes.Length]; + for (int i = 0; i < Nodes.Length; i++) + { + r[i] = Nodes[i].Data; + } + return r; + } + public CScenarioChainingEdge[] GetCEdges() + { + if ((Edges == null) || (Edges.Length == 0)) return null; + CScenarioChainingEdge[] r = new CScenarioChainingEdge[Edges.Length]; + for (int i = 0; i < Edges.Length; i++) + { + r[i] = Edges[i].Data; + } + return r; + } + public CScenarioChain[] GetCChains() + { + if ((Chains == null) || (Chains.Length == 0)) return null; + CScenarioChain[] r = new CScenarioChain[Chains.Length]; + for (int i = 0; i < Chains.Length; i++) + { + r[i] = Chains[i].Data; + } + return r; + } + + + + public void AddNode(MCScenarioChainingNode node) + { + List newnodes = new List(); + if (Nodes != null) + { + newnodes.AddRange(Nodes); + } + node.Parent = this; + node.Region = Region; + node.NodeIndex = newnodes.Count; + newnodes.Add(node); + Nodes = newnodes.ToArray(); + } + public void AddEdge(MCScenarioChainingEdge edge) + { + List newedges = new List(); + if (Edges != null) + { + newedges.AddRange(Edges); + } + edge.Region = Region; + edge.EdgeIndex = newedges.Count; + newedges.Add(edge); + Edges = newedges.ToArray(); + } + public void AddChain(MCScenarioChain chain) + { + List newchains = new List(); + if (Chains != null) + { + newchains.AddRange(Chains); + } + chain.Region = Region; + chain.ChainIndex = newchains.Count; + newchains.Add(chain); + Chains = newchains.ToArray(); + } + + public bool RemoveNode(MCScenarioChainingNode n) + { + bool r = false; + if (Edges != null) + { + //first remove any edges referencing this node... + List remedges = new List(); + if (Chains != null) + { + foreach (var chain in Chains) + { + if (chain.Edges == null) continue; + remedges.Clear(); + foreach (var edge in chain.Edges) + { + if ((edge.NodeFrom == n) || (edge.NodeTo == n)) + { + remedges.Add(edge); + } + } + foreach (var edge in remedges) + { + chain.RemoveEdge(edge); + } + } + } + remedges.Clear(); + foreach (var edge in Edges) + { + if ((edge.NodeFrom == n) || (edge.NodeTo == n)) + { + remedges.Add(edge); + } + } + foreach (var edge in remedges) + { + RemoveEdge(edge); + } + } + + if (Nodes != null) + { + List newnodes = new List(); + foreach (var nn in Nodes) + { + if (nn == n) + { + r = true; + } + else + { + nn.NodeIndex = newnodes.Count; + newnodes.Add(nn); + } + } + if (r) + { + Nodes = newnodes.ToArray(); + + foreach (var e in Edges) + { + e.NodeIndexFrom = (ushort)e.NodeFrom.NodeIndex; + e.NodeIndexTo = (ushort)e.NodeTo.NodeIndex; + } + + } + } + return r; + } + public bool RemoveEdge(MCScenarioChainingEdge e) + { + bool r = false; + if (Edges != null) + { + List newedges = new List(); + foreach (var ne in Edges) + { + if (ne == e) + { + r = true; + } + else + { + ne.EdgeIndex = newedges.Count; + newedges.Add(ne); + } + } + if (r) + { + Edges = newedges.ToArray(); + + foreach (var c in Chains) + { + for (int i = 0; i < c.Edges.Length; i++) + { + c.EdgeIds[i] = (ushort)c.Edges[i].EdgeIndex; + } + } + } + } + return r; + } + public bool RemoveChain(MCScenarioChain c) + { + bool r = false; + if (Chains != null) + { + List newchains = new List(); + foreach (var nc in Chains) + { + if (nc == c) + { + r = true; + } + else + { + nc.ChainIndex = newchains.Count; + newchains.Add(nc); + } + } + if (r) + { + Chains = newchains.ToArray(); + } + } + return r; + } + + + + public override string Name + { + get + { + return "Unk_4023740759 (Scenario paths) " + _Data.ToString(); + } + } + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CScenarioChainingNode //SCENARIO PATH NODE //32 bytes, Key:1811784424 + { + public Vector3 Position { get; set; } //0 0: Float_XYZ: 0: Position + public float Unused0 { get; set; }//12 + public MetaHash Unk_2602393771 { get; set; } //16 16: Hash: 0: 2602393771 + public MetaHash ScenarioType { get; set; } //20 20: Hash: 0: ScenarioType + public byte Unk_407126079_NotFirst { get; set; } //24 24: Boolean: 0: 407126079 //can move backwards? (not first node) + public byte Unk_1308720135_NotLast { get; set; } //25 25: Boolean: 0: 1308720135 //can move forwards? (not last node) + public ushort Unused1 { get; set; }//26 + public uint Unused2 { get; set; }//28 + + public override string ToString() + { + return //Unk_407126079.ToString() + ", " + Unk_1308720135.ToString() + ", " + + ScenarioType.ToString() + ", " + Unk_2602393771.ToString(); + } + } + [TC(typeof(EXP))] public class MCScenarioChainingNode : MetaWrapper + { + [TC(typeof(EXP))] public MUnk_4023740759 Parent { get; set; } + public MCScenarioPointRegion Region { get; set; } + + public CScenarioChainingNode _Data; + public CScenarioChainingNode Data { get { return _Data; } set { _Data = value; } } + + public Vector3 Position { get { return _Data.Position; } set { _Data.Position = value; } } + public MetaHash Unk1 { get { return _Data.Unk_2602393771; } set { _Data.Unk_2602393771 = value; } } + public MetaHash TypeHash { get { return _Data.ScenarioType; } set { _Data.ScenarioType = value; } } + public ScenarioType Type { get; set; } + public bool NotFirst { get { return _Data.Unk_407126079_NotFirst == 1; } set { _Data.Unk_407126079_NotFirst = (byte)(value ? 1 : 0); } } + public bool NotLast { get { return _Data.Unk_1308720135_NotLast == 1; } set { _Data.Unk_1308720135_NotLast = (byte)(value ? 1 : 0); } } + + public int NodeIndex { get; set; } + public MCScenarioChain Chain { get; set; } + + + public MCScenarioChainingNode() { } + public MCScenarioChainingNode(MCScenarioPointRegion region, Meta meta, CScenarioChainingNode d, MUnk_4023740759 parent, int index) + { + Region = region; + Parent = parent; + _Data = d; + NodeIndex = index; + } + public MCScenarioChainingNode(MCScenarioPointRegion region, MCScenarioChainingNode copy) + { + Region = region; + _Data = copy._Data; + Type = copy.Type; + } + + public void CopyFrom(MCScenarioChainingNode copy) + { + _Data = copy._Data; + Type = copy.Type; + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CScenarioChainingNode); + return mb.AddItemPtr(MetaName.CScenarioChainingNode, _Data); + } + + public override string Name + { + get + { + return "CScenarioChainingNode";// + _Data.Unk_2602393771.ToString(); + } + } + + + public override string ToString() + { + return _Data.ToString(); + } + + } + + [TC(typeof(EXP))] public struct CScenarioChainingEdge //SCENARIO PATH EDGE //8 bytes, Key:2004985940 + { + public ushort NodeIndexFrom { get; set; } //0 0: UnsignedShort: 0: NodeIndexFrom//3236798246 + public ushort NodeIndexTo { get; set; } //2 2: UnsignedShort: 0: NodeIndexTo//2851806039 + public Unk_3609807418 Action { get; set; } //4 4: ByteEnum: 3609807418: Action + public Unk_3971773454 NavMode { get; set; } //5 5: ByteEnum: 3971773454: NavMode//859022269 + public Unk_941086046 NavSpeed { get; set; } //6 6: ByteEnum: 941086046: NavSpeed//1419316113 + public byte Unused0 { get; set; }//7 + + public override string ToString() + { + return NodeIndexFrom.ToString() + ", " + NodeIndexTo.ToString() + ", " + Action.ToString() + ", " + NavMode.ToString() + ", " + NavSpeed.ToString(); + } + } + [TC(typeof(EXP))] public class MCScenarioChainingEdge : MetaWrapper + { + public MCScenarioPointRegion Region { get; set; } + + public CScenarioChainingEdge _Data; + public CScenarioChainingEdge Data { get { return _Data; } set { _Data = value; } } + + public MCScenarioChainingNode NodeFrom { get; set; } + public MCScenarioChainingNode NodeTo { get; set; } + public ushort NodeIndexFrom { get { return _Data.NodeIndexFrom; } set { _Data.NodeIndexFrom = value; } } + public ushort NodeIndexTo { get { return _Data.NodeIndexTo; } set { _Data.NodeIndexTo = value; } } + public Unk_3609807418 Action { get { return _Data.Action; } set { _Data.Action = value; } } + public Unk_3971773454 NavMode { get { return _Data.NavMode; } set { _Data.NavMode = value; } } + public Unk_941086046 NavSpeed { get { return _Data.NavSpeed; } set { _Data.NavSpeed = value; } } + + + public int EdgeIndex { get; set; } + + public MCScenarioChainingEdge() { } + public MCScenarioChainingEdge(MCScenarioPointRegion region, Meta meta, CScenarioChainingEdge d, int index) + { + Region = region; + _Data = d; + EdgeIndex = index; + } + public MCScenarioChainingEdge(MCScenarioPointRegion region, MCScenarioChainingEdge copy) + { + Region = region; + _Data = copy._Data; + NodeFrom = copy.NodeFrom; + NodeTo = copy.NodeTo;//these should be updated later... + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CScenarioChainingEdge); + return mb.AddItemPtr(MetaName.CScenarioChainingEdge, _Data); + } + + public override string Name + { + get + { + return "CScenarioChainingEdge"; + } + } + + public override string ToString() + { + return Action.ToString() + ", " + NavMode.ToString() + ", " + NavSpeed.ToString(); + } + + } + + [TC(typeof(EXP))] public struct CScenarioChain //SCENARIO PATH CHAIN //40 bytes, Key:2751910366 + { + public byte Unk_1156691834 { get; set; } //0 0: UnsignedByte: 0: 1156691834 + public byte Unused0 { get; set; }//1 + public ushort Unused1 { get; set; }//2 + public uint Unused2 { get; set; }//4 + public Array_ushort EdgeIds { get; set; } //8 8: Array: 0: EdgeIds {0: UnsignedShort: 0: 256} + public uint Unused3 { get; set; }//24 + public uint Unused4 { get; set; }//28 + public uint Unused5 { get; set; }//32 + public uint Unused6 { get; set; }//36 + + public override string ToString() + { + return Unk_1156691834.ToString() + ": " + EdgeIds.Count1.ToString() + " EdgeIds"; + } + } + [TC(typeof(EXP))] public class MCScenarioChain : MetaWrapper + { + public MCScenarioPointRegion Region { get; set; } + + public CScenarioChain _Data; + public CScenarioChain Data { get { return _Data; } set { _Data = value; } } + + public byte Unk1 { get { return _Data.Unk_1156691834; } set { _Data.Unk_1156691834 = value; } } + + public ushort[] EdgeIds { get; set; } + public MCScenarioChainingEdge[] Edges { get; set; } + + public int ChainIndex { get; set; } + + public MCScenarioChain() { } + public MCScenarioChain(MCScenarioPointRegion region, Meta meta, CScenarioChain d) + { + Region = region; + _Data = d; + EdgeIds = MetaTypes.GetUshortArray(meta, _Data.EdgeIds); + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + EdgeIds = MetaTypes.GetUshortArray(meta, _Data.EdgeIds); + } + + + public void AddEdge(MCScenarioChainingEdge edge) + { + List newedges = new List(); + List newedgeids = new List(); + if (Edges != null) + { + newedges.AddRange(Edges); + } + if (EdgeIds != null) + { + newedgeids.AddRange(EdgeIds); + } + edge.Region = Region; + newedges.Add(edge); + newedgeids.Add((ushort)edge.EdgeIndex); + Edges = newedges.ToArray(); + EdgeIds = newedgeids.ToArray(); + } + public bool RemoveEdge(MCScenarioChainingEdge e) + { + bool r = false; + if (Edges != null) + { + List newedges = new List(); + List newedgeids = new List(); + foreach (var ne in Edges) + { + if (ne == e) + { + r = true; + } + else + { + newedges.Add(ne); + newedgeids.Add((ushort)ne.EdgeIndex); + } + } + if (r) + { + Edges = newedges.ToArray(); + EdgeIds = newedgeids.ToArray(); + } + } + return r; + } + + + public override MetaPOINTER Save(MetaBuilder mb) + { + //TODO! + //if (EdgeIds != null) + //{ + // mb.AddStructureInfo(MetaName.ushort); + // _Data.EdgeIds = mb.AddItemArrayPtr(MetaName.ushort, EdgeIds); + //} + + mb.AddStructureInfo(MetaName.CScenarioChain); + return mb.AddItemPtr(MetaName.CScenarioChain, _Data); + } + + public override string Name + { + get + { + return "CScenarioChain"; + } + } + + public override string ToString() + { + return _Data.ToString(); + } + + } + + [TC(typeof(EXP))] public struct CScenarioPointCluster //SCENARIO spawn cluster - all things spawn together //80 bytes, Key:3622480419 + { + public CScenarioPointContainer Points { get; set; } //0 0: Structure: CScenarioPointContainer//2380938603: Points//702683191 + public rage__spdSphere ClusterSphere { get; set; } //48 48: Structure: 1062159465: ClusterSphere//352461053 + public float Unk_1095875445 { get; set; } //64 64: Float: 0: 1095875445 //spawn chance? eg 5, 30 + public byte Unk_3129415068 { get; set; } //68 68: Boolean: 0: 3129415068 + public uint Unused0 { get; set; }//72 + public uint Unused1 { get; set; }//76 + + public override string ToString() + { + return Points.ToString();// + ", Sphere: " + ClusterSphere.ToString(); + } + } + [TC(typeof(EXP))] public class MCScenarioPointCluster : MetaWrapper + { + public MCScenarioPointRegion Region { get; set; } + + public CScenarioPointCluster _Data; + public CScenarioPointCluster Data { get { return _Data; } set { _Data = value; } } + + public MCScenarioPointContainer Points { get; set; } + + public Vector3 Position //is separate from Points... + { + get { return _Data.ClusterSphere.centerAndRadius.XYZ(); } + set + { + var v4 = new Vector4(value, _Data.ClusterSphere.centerAndRadius.W); + _Data.ClusterSphere = new rage__spdSphere() { centerAndRadius = v4 }; + } + } + public float Radius + { + get { return _Data.ClusterSphere.centerAndRadius.W; } + set + { + var v4 = new Vector4(_Data.ClusterSphere.centerAndRadius.XYZ(), value); + _Data.ClusterSphere = new rage__spdSphere() { centerAndRadius = v4 }; + } + } + public float Unk1 { get { return _Data.Unk_1095875445; } set { _Data.Unk_1095875445 = value; } } + public bool Unk2 { get { return _Data.Unk_3129415068==1; } set { _Data.Unk_3129415068 = (byte)(value?1:0); } } + + public MCScenarioPointCluster() { } + public MCScenarioPointCluster(MCScenarioPointRegion region) { Region = region; } + public MCScenarioPointCluster(MCScenarioPointRegion region, MCScenarioPointCluster copy) + { + Region = region; + if (copy != null) + { + _Data = copy.Data; + } + Points = new MCScenarioPointContainer(region); + Points.Parent = this; + } + public MCScenarioPointCluster(MCScenarioPointRegion region, Meta meta, CScenarioPointCluster d) + { + Region = region; + _Data = d; + Points = new MCScenarioPointContainer(region, meta, d.Points); + Points.Parent = this; + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + Points = new MCScenarioPointContainer(Region, meta, _Data.Points); + Points.Parent = this; + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.rage__spdSphere); + mb.AddStructureInfo(MetaName.CScenarioPointCluster); + + + if (Points != null) + { + var scp = new CScenarioPointContainer(); + + ////meta version + //if ((Points.LoadSavePoints != null) && (Points.LoadSavePoints.Length > 0)) + //{ + // scp.LoadSavePoints = mb.AddWrapperArray(Points.LoadSavePoints); + //} + //if ((Points.MyPoints != null) && (Points.MyPoints.Length > 0)) + //{ + // scp.MyPoints = mb.AddWrapperArray(Points.MyPoints); + //} + + //optimised version... + var loadSavePoints = Points.GetCLoadSavePoints(); + if (loadSavePoints != null)//this never seems to be used... + { + mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint); + mb.AddEnumInfo((MetaName)3573596290); + mb.AddEnumInfo((MetaName)700327466); + scp.LoadSavePoints = mb.AddItemArrayPtr(MetaName.CExtensionDefSpawnPoint, loadSavePoints); + } + var myPoints = Points.GetCMyPoints(); + if (myPoints != null) + { + mb.AddStructureInfo(MetaName.CScenarioPoint); + mb.AddEnumInfo((MetaName)700327466); + scp.MyPoints = mb.AddItemArrayPtr(MetaName.CScenarioPoint, myPoints); + } + + _Data.Points = scp; + } + else + { + _Data.Points = new CScenarioPointContainer(); + } + + return mb.AddItemPtr(MetaName.CScenarioPointCluster, _Data); + } + + public override string Name + { + get { return "CScenarioPointCluster"; } + } + + + public override string ToString() + { + return _Data.ToString(); + } + } + + [TC(typeof(EXP))] public struct CScenarioPointLookUps //SCENARIO hash arrays //96 bytes, Key:2669361587 + { + public Array_uint TypeNames { get; set; } //0 0: Array: 0: TypeNames//3057471271 {0: Hash: 0: 256} + public Array_uint PedModelSetNames { get; set; } //16 16: Array: 0: PedModelSetNames//3020866217 {0: Hash: 0: 256} + public Array_uint VehicleModelSetNames { get; set; } //32 32: Array: 0: VehicleModelSetNames//3827910541 {0: Hash: 0: 256} + public Array_uint GroupNames { get; set; } //48 48: Array: 0: GroupNames//2506712617 {0: Hash: 0: 256} + public Array_uint InteriorNames { get; set; } //64 64: Array: 0: InteriorNames {0: Hash: 0: 256} + public Array_uint RequiredIMapNames { get; set; } //[ymap names] //80 80: Array: 0: RequiredIMapNames//1767860162 {0: Hash: 0: 256} + + public override string ToString() + { + return "CScenarioPointLookUps"; + } + } + [TC(typeof(EXP))] public class MCScenarioPointLookUps : MetaWrapper + { + public MCScenarioPointRegion Region { get; set; } + + public CScenarioPointLookUps _Data; + public CScenarioPointLookUps Data { get { return _Data; } set { _Data = value; } } + + public MetaHash[] TypeNames { get; set; } //scenario type hashes used by points + public MetaHash[] PedModelSetNames { get; set; } //ped names + public MetaHash[] VehicleModelSetNames { get; set; } //vehicle names + public MetaHash[] GroupNames { get; set; } //scenario group names? + public MetaHash[] InteriorNames { get; set; } + public MetaHash[] RequiredIMapNames { get; set; } //ymap names + + + public MCScenarioPointLookUps() { } + public MCScenarioPointLookUps(MCScenarioPointRegion region) + { + Region = region; + } + public MCScenarioPointLookUps(MCScenarioPointRegion region, Meta meta, CScenarioPointLookUps d) + { + Region = region; + _Data = d; + Init(meta); + } + + public void Init(Meta meta) + { + TypeNames = MetaTypes.GetHashArray(meta, _Data.TypeNames); + PedModelSetNames = MetaTypes.GetHashArray(meta, _Data.PedModelSetNames); + VehicleModelSetNames = MetaTypes.GetHashArray(meta, _Data.VehicleModelSetNames); + GroupNames = MetaTypes.GetHashArray(meta, _Data.GroupNames); + InteriorNames = MetaTypes.GetHashArray(meta, _Data.InteriorNames); + RequiredIMapNames = MetaTypes.GetHashArray(meta, _Data.RequiredIMapNames); + } + + public override void Load(Meta meta, MetaPOINTER ptr) + { + _Data = MetaTypes.GetData(meta, ptr); + Init(meta); + } + + public override MetaPOINTER Save(MetaBuilder mb) + { + mb.AddStructureInfo(MetaName.CScenarioPointLookUps); + return mb.AddItemPtr(MetaName.CScenarioPointLookUps, _Data); + } + + public override string Name + { + get + { + return "CScenarioPointLookUps"; + } + } + + public override string ToString() + { + return _Data.ToString(); + } + + } + + + + + + + + + + + + + + + + + + + + public struct CStreamingRequestRecord //40 bytes, Key:3825587854 //SRL YMT ROOT - in /streaming/ folder + { + public Array_Structure Frames { get; set; } //0 0: Array: 0: Frames//419044527 {0: Structure: CStreamingRequestFrame//999226379: 256} + public Array_Structure CommonSets { get; set; } //16 16: Array: 0: CommonSets//4248405899 {0: Structure: 1358189812: 256} + public byte NewStyle { get; set; } //32 32: Boolean: 0: 2333392588 + public byte Unused0 { get; set; }//33 + public ushort Unused1 { get; set; }//34 + public uint Unused2 { get; set; }//36 + } + + public struct CStreamingRequestFrame //112 bytes, Key:1112444512 //SRL frame... + { + public Array_uint AddList { get; set; } //0 0: Array: 0: AddList//327274266 {0: Hash: 0: 256} + public Array_uint RemoveList { get; set; } //16 16: Array: 0: RemoveList//3372321331 {0: Hash: 0: 256} + public Array_uint Unk_896120921 { get; set; } //32 32: Array: 0: 896120921 {0: Hash: 0: 256} + public Vector3 CamPos { get; set; } //48 48: Float_XYZ: 0: CamPos//357008256 + public float Unused0 { get; set; }//60 + public Vector3 CamDir { get; set; } //64 64: Float_XYZ: 0: CamDir//210316193 + public float Unused1 { get; set; }//76 + public Array_byte Unk_1762439591 { get; set; } //80 80: Array: 0: 1762439591 {0: UnsignedByte: 0: 256} + public uint Flags { get; set; } //96 96: UnsignedInt: 0: Flags + public uint Unused2 { get; set; }//100 + public uint Unused3 { get; set; }//104 + public uint Unused4 { get; set; }//108 + } + + public struct CStreamingRequestFrame_v2 //96 bytes, Key:3672937465 //SRL frame... + { + public Array_uint AddList { get; set; } //0 0: Array: 0: AddList//327274266 {0: Hash: 0: 256} + public Array_uint RemoveList { get; set; } //16 16: Array: 0: RemoveList//3372321331 {0: Hash: 0: 256} + public Vector3 CamPos { get; set; } //32 32: Float_XYZ: 0: CamPos//357008256 + public float Unused0 { get; set; }//44 + public Vector3 CamDir { get; set; } //48 48: Float_XYZ: 0: CamDir//210316193 + public float Unused1 { get; set; }//60 + public Array_byte Unk_1762439591 { get; set; } //64 64: Array: 0: 1762439591 {0: UnsignedByte: 0: 256} + public uint Flags { get; set; } //80 80: UnsignedInt: 0: Flags + public uint Unused2 { get; set; }//84 + public uint Unused3 { get; set; }//88 + public uint Unused4 { get; set; }//92 + } + + public struct Unk_1358189812 //16 bytes, Key:3710200606 //SRL hashes list? + { + public Array_uint Requests { get; set; } //0 0: Array: 0: Requests//2743119154 {0: Hash: 0: 256} + } + + + + + + + + + + + + + + + public struct Unk_376833625 //112 bytes, Key:4030871161 //COMPONENT PEDS YMT ROOT - in componentpeds .rpf's + { + public byte Unk_1235281004 { get; set; } //0 0: Boolean: 0: 1235281004 + public byte Unk_4086467184 { get; set; } //1 1: Boolean: 0: 4086467184 + public byte Unk_911147899 { get; set; } //2 2: Boolean: 0: 911147899 + public byte Unk_315291935 { get; set; } //3 3: Boolean: 0: 315291935 + public ArrayOfBytes12 Unk_2996560424 { get; set; } //4 4: ArrayOfBytes: 12: 2996560424 + public Array_Structure Unk_3796409423 { get; set; } //16 16: Array: 0: 3796409423 {0: Structure: 3538495220: 256} + public Array_Structure Unk_2131007641 { get; set; } //32 32: Array: 0: 2131007641 {0: Structure: 253191135: 256} + public Array_Structure compInfos { get; set; } //48 48: Array: 0: compInfos//592652859 {0: Structure: CComponentInfo//1866571721: 256} + public Unk_2858946626 propInfo { get; set; } //64 64: Structure: 2858946626: propInfo//2240851416 + public MetaHash dlcName { get; set; } //104 104: Hash: 0: dlcName + public uint Unused0 { get; set; }//108 + } + + public struct Unk_3538495220 //24 bytes, Key:2024084511 //COMPONENT PEDS unknown + { + public byte Unk_3371516811 { get; set; } //0 0: UnsignedByte: 0: 3371516811 + public byte Unused0 { get; set; }//1 + public ushort Unused1 { get; set; }//2 + public uint Unused2 { get; set; }//4 + public Array_Structure Unk_1756136273 { get; set; } //8 8: Array: 0: 1756136273 {0: Structure: 1535046754: 256} + } + + public struct Unk_1535046754 //48 bytes, Key:124073662 //COMPONENT PEDS unknown /cloth? + { + public byte propMask { get; set; } //0 0: UnsignedByte: 0: propMask//2932859459 + public byte Unk_2806194106 { get; set; } //1 1: UnsignedByte: 0: 2806194106 + public ushort Unused0 { get; set; }//2 + public uint Unused1 { get; set; }//4 + public Array_Structure aTexData { get; set; } //8 8: Array: 0: aTexData//1251090986 {0: Structure: 1036962405: 256} + public Unk_2236980467 clothData { get; set; } //24 24: Structure: 2236980467: clothData//2464583091 + } + + public struct Unk_1036962405 //3 bytes, Key:4272717794 //COMPONENT PEDS (cloth?) TexData + { + public byte texId { get; set; } //0 0: UnsignedByte: 0: texId + public byte distribution { get; set; } //1 1: UnsignedByte: 0: distribution//914976023 + public byte Unused0 { get; set; }//2 + } + + public struct Unk_2236980467 //24 bytes, Key:508935687 //COMPONENT PEDS clothData + { + public byte Unk_2828247905 { get; set; } //0 0: Boolean: 0: 2828247905 + public byte Unused0 { get; set; }//1 + public ushort Unused1 { get; set; }//2 + public uint Unused2 { get; set; }//4 + public uint Unused3 { get; set; }//8 + public uint Unused4 { get; set; }//12 + public uint Unused5 { get; set; }//16 + public uint Unused6 { get; set; }//20 + } + + public struct Unk_253191135 //48 bytes, Key:3120284999 //COMPONENT PEDS unknown + { + public MetaHash name { get; set; } //0 0: Hash: 0: name + public ArrayOfBytes12 Unk_173599222 { get; set; } //4 4: ArrayOfBytes: 12: 173599222 + public ArrayOfBytes12 Unk_2991454271 { get; set; } //16 16: ArrayOfBytes: 12: 2991454271 + public ArrayOfBytes6 Unk_3598106198 { get; set; } //28 28: ArrayOfBytes: 6: 3598106198 + public ArrayOfBytes6 Unk_2095974912 { get; set; } //34 34: ArrayOfBytes: 6: 2095974912 + public ArrayOfBytes6 Unk_672172037 { get; set; } //40 40: ArrayOfBytes: 6: 672172037 + public ushort Unused0 { get; set; }//46 + } + + public struct CComponentInfo //48 bytes, Key:3693847250 //COMPONENT PEDS CComponentInfo + { + public MetaHash Unk_802196719 { get; set; } //0 0: Hash: 0: 802196719 + public MetaHash Unk_4233133352 { get; set; } //4 4: Hash: 0: 4233133352 + public ArrayOfBytes5 Unk_128864925 { get; set; } //8 8: ArrayOfBytes: 5: 128864925 + public byte Unused0 { get; set; }//13 + public ushort Unused1 { get; set; }//14 + public uint Unused2 { get; set; }//16 + public uint Unused3 { get; set; }//20 + public uint Unused4 { get; set; }//24 + public uint flags { get; set; } //28 28: UnsignedInt: 0: flags + public int inclusions { get; set; } //32 32: IntFlags2: 0: inclusions//2172318933 + public int exclusions { get; set; } //36 36: IntFlags2: 0: exclusions + public Unk_884254308 Unk_1613922652 { get; set; } //40 40: ShortFlags: 884254308: 1613922652 + public ushort Unk_2114993291 { get; set; } //42 42: UnsignedShort: 0: 2114993291 + public byte Unk_3509540765 { get; set; } //44 44: UnsignedByte: 0: 3509540765 + public byte Unk_4196345791 { get; set; } //45 45: UnsignedByte: 0: 4196345791 + public ushort Unused5 { get; set; }//46 + } + + public struct Unk_2858946626 //40 bytes, Key:1792487819 //COMPONENT PEDS unknown + { + public byte Unk_2598445407 { get; set; } //0 0: UnsignedByte: 0: 2598445407 + public byte Unused0 { get; set; }//1 + public ushort Unused1 { get; set; }//2 + public uint Unused2 { get; set; }//4 + public Array_Structure Unk_3902803273 { get; set; } //8 8: Array: 0: 3902803273 {0: Structure: 94549140: 256} + public Array_Structure aAnchors { get; set; } //24 24: Array: 0: aAnchors//162345210 {0: Structure: CAnchorProps//2170383875: 256} + } + + public struct Unk_94549140 //56 bytes, Key:2029738350 //COMPONENT PEDS unknown + { + public MetaHash audioId { get; set; } //0 0: Hash: 0: audioId + public ArrayOfBytes5 expressionMods { get; set; } //4 4: ArrayOfBytes: 5: expressionMods//942761829 + public byte Unused0 { get; set; }//9 + public ushort Unused1 { get; set; }//10 + public uint Unused2 { get; set; }//12 + public uint Unused3 { get; set; }//16 + public uint Unused4 { get; set; }//20 + public Array_Structure texData { get; set; } //24 24: Array: 0: texData//4088935562 {0: Structure: 254518642: 256} + public Unk_4212977111 renderFlags { get; set; } //40 40: IntFlags1: 4212977111: renderFlags//4239582912 + public uint propFlags { get; set; } //44 44: UnsignedInt: 0: propFlags//1066841901 + public ushort flags { get; set; } //48 48: UnsignedShort: 0: flags + public byte anchorId { get; set; } //50 50: UnsignedByte: 0: anchorId//2731224028 + public byte propId { get; set; } //51 51: UnsignedByte: 0: propId//3817142252 + public byte Unk_2894625425 { get; set; } //52 52: UnsignedByte: 0: 2894625425 + public byte Unused5 { get; set; }//53 + public ushort Unused6 { get; set; }//54 + } + + public struct Unk_254518642 //12 bytes, Key:2767296137 //COMPONENT PEDS (expression?) texData + { + public int inclusions { get; set; } //0 0: IntFlags2: 0: inclusions//2172318933 + public int exclusions { get; set; } //4 4: IntFlags2: 0: exclusions + public byte texId { get; set; } //8 8: UnsignedByte: 0: texId + public byte inclusionId { get; set; } //9 9: UnsignedByte: 0: inclusionId//1938349561 + public byte exclusionId { get; set; } //10 10: UnsignedByte: 0: exclusionId//3819522186 + public byte distribution { get; set; } //11 11: UnsignedByte: 0: distribution//914976023 + } + + public struct CAnchorProps //24 bytes, Key:403574180 //COMPONENT PEDS CAnchorProps + { + public Array_byte props { get; set; } //0 0: Array: 0: props {0: UnsignedByte: 0: 256} + public Unk_2834549053 anchor { get; set; } //16 16: IntEnum: 2834549053: anchor + public uint Unused0 { get; set; }//20 + } + + + + + + + + + + + +} diff --git a/GameFiles/MetaTypes/MetaXml.cs b/GameFiles/MetaTypes/MetaXml.cs new file mode 100644 index 0000000..82e7c7d --- /dev/null +++ b/GameFiles/MetaTypes/MetaXml.cs @@ -0,0 +1,1535 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class MetaXml : MetaXmlBase + { + + + public static string GetXml(Meta meta) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(XmlHeader); + + if (meta != null) + { + var cont = new MetaCont(meta); + + WriteNode(sb, 0, cont, meta.RootBlockIndex, 0, XmlTagMode.Structure); + } + + return sb.ToString(); + } + + private static void WriteNode(StringBuilder sb, int indent, MetaCont cont, int blockId, int offset, XmlTagMode tagMode = XmlTagMode.None, MetaName structName = 0) + { + + var block = cont.Meta.GetBlock(blockId); + if (block == null) + { + ErrorXml(sb, indent, "Couldn't find block " + blockId + "!"); + return; + } + + if (structName == 0) + { + structName = block.StructureNameHash; + } + + var name = HashString(structName); + var data = block.Data; + + var structInfo = cont.GetStructureInfo(structName); + if (structInfo == null) + { + ErrorXml(sb, indent, "Couldn't find structure info " + name + "!"); + return; + } + if (structInfo.Entries == null) + { + ErrorXml(sb, indent, "Couldn't find structure info entries for " + name + "!"); + return; + } + + + switch (tagMode) + { + case XmlTagMode.Structure: + OpenTag(sb, indent, name); + break; + case XmlTagMode.Item: + OpenTag(sb, indent, "Item"); + break; + case XmlTagMode.ItemAndType: + OpenTag(sb, indent, "Item type=\"" + name + "\""); + break; + } + + var cind = indent + 1; + MetaStructureEntryInfo_s arrEntry = new MetaStructureEntryInfo_s(); + for (int i = 0; i < structInfo.Entries.Length; i++) + { + var entry = structInfo.Entries[i]; + if (entry.EntryNameHash == MetaName.ARRAYINFO) + { + arrEntry = entry; + continue; + } + var ename = HashString(entry.EntryNameHash); + var eoffset = offset + entry.DataOffset; + switch (entry.DataType) + { + default: + ErrorXml(sb, cind, ename + ": Unexpected entry DataType: " + entry.DataType.ToString()); + break; + case MetaStructureEntryDataType.Array: + + WriteArrayNode(sb, cind, cont, data, arrEntry, ename, eoffset); + + break; + case MetaStructureEntryDataType.ArrayOfBytes: + OpenTag(sb, cind, ename, false); + var byteArrLen = (int)entry.ReferenceKey; + for (int n = 0; n < byteArrLen; n++) + { + var bidx = eoffset + n; + byte b = ((bidx >= 0) && (bidx < data.Length)) ? data[bidx] : (byte)0; + sb.Append(b.ToString("X").PadLeft(2, '0')); + } + CloseTag(sb, 0, ename); + break; + case MetaStructureEntryDataType.ArrayOfChars: + OpenTag(sb, cind, ename, false); + uint charArrLen = (uint)entry.ReferenceKey; + for (int n = 0; n < charArrLen; n++) + { + var bidx = eoffset + n; + if ((bidx >= 0) && (bidx < data.Length)) + { + byte b = data[bidx]; + if (b == 0) break; + sb.Append((char)b); + } + } + CloseTag(sb, 0, ename); + break; + case MetaStructureEntryDataType.Boolean: + var boolVal = BitConverter.ToBoolean(data, eoffset); + ValueTag(sb, cind, ename, boolVal?"true":"false"); + break; + case MetaStructureEntryDataType.ByteEnum: + var byteEnumVal = data[eoffset]; + ValueTag(sb, cind, ename, byteEnumVal.ToString()); + break; + case MetaStructureEntryDataType.CharPointer: + var charPtr = MetaTypes.ConvertData(data, eoffset); + string charStr = MetaTypes.GetString(cont.Meta, charPtr); + OneLineTag(sb, cind, ename, charStr); + break; + case MetaStructureEntryDataType.DataBlockPointer: + OpenTag(sb, cind, ename); + var dataPtr = MetaTypes.ConvertData(data, eoffset); + ErrorXml(sb, cind + 1, "DataBlockPointer not currently supported here!"); //TODO! ymap occludeModels vertices data is this type! + CloseTag(sb, cind, ename); + break; + case MetaStructureEntryDataType.Float: + var floatVal = BitConverter.ToSingle(data, eoffset); + ValueTag(sb, cind, ename, FloatUtil.ToString(floatVal)); + break; + case MetaStructureEntryDataType.Float_XYZ: + var v3 = MetaTypes.ConvertData(data, eoffset); + SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3.X) + "\" y=\"" + FloatUtil.ToString(v3.Y) + "\" z=\"" + FloatUtil.ToString(v3.Z) + "\""); + break; + case MetaStructureEntryDataType.Float_XYZW: + var v4 = MetaTypes.ConvertData(data, eoffset); + SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v4.X) + "\" y=\"" + FloatUtil.ToString(v4.Y) + "\" z=\"" + FloatUtil.ToString(v4.Z) + "\" w=\"" + FloatUtil.ToString(v4.W) + "\""); + break; + case MetaStructureEntryDataType.Hash: + var hashVal = MetaTypes.ConvertData(data, eoffset); + var hashStr = HashString(hashVal); + StringTag(sb, cind, ename, hashStr); + break; + case MetaStructureEntryDataType.IntEnum: + var intEnumVal = BitConverter.ToInt32(data, eoffset); + var intEnumStr = GetEnumString(cont, entry, intEnumVal); + StringTag(sb, cind, ename, intEnumStr); + break; + case MetaStructureEntryDataType.IntFlags1: + var intFlags1Val = BitConverter.ToInt32(data, eoffset); + var intFlags1Str = GetEnumString(cont, entry, intFlags1Val); + StringTag(sb, cind, ename, intFlags1Str); + break; + case MetaStructureEntryDataType.IntFlags2: + var intFlags2Val = BitConverter.ToInt32(data, eoffset); + var intFlags2Str = GetEnumString(cont, entry, intFlags2Val); + StringTag(sb, cind, ename, intFlags2Str); + break; + case MetaStructureEntryDataType.ShortFlags: + var shortFlagsVal = BitConverter.ToInt16(data, eoffset); + var shortFlagsStr = GetEnumString(cont, entry, shortFlagsVal); + StringTag(sb, cind, ename, shortFlagsStr); + break; + case MetaStructureEntryDataType.SignedByte: + sbyte sbyteVal = (sbyte)data[eoffset]; + ValueTag(sb, cind, ename, sbyteVal.ToString()); + break; + case MetaStructureEntryDataType.SignedInt: + var intVal = BitConverter.ToInt32(data, eoffset); + ValueTag(sb, cind, ename, intVal.ToString()); + break; + case MetaStructureEntryDataType.SignedShort: + var shortVal = BitConverter.ToInt16(data, eoffset); + ValueTag(sb, cind, ename, shortVal.ToString()); + break; + case MetaStructureEntryDataType.Structure: + OpenTag(sb, cind, ename); + WriteNode(sb, cind, cont, blockId, eoffset, XmlTagMode.None, entry.ReferenceKey); + CloseTag(sb, cind, ename); + break; + case MetaStructureEntryDataType.StructurePointer: + OpenTag(sb, cind, ename); + ErrorXml(sb, cind + 1, "StructurePointer not supported here! Tell dexy!"); + CloseTag(sb, cind, ename); + break; + case MetaStructureEntryDataType.UnsignedByte: + var byteVal = data[eoffset]; + ValueTag(sb, cind, ename, byteVal.ToString()); + //ValueTag(sb, cind, ename, "0x" + byteVal.ToString("X").PadLeft(2, '0')); + break; + case MetaStructureEntryDataType.UnsignedInt: + var uintVal = BitConverter.ToUInt32(data, eoffset); + switch (entry.EntryNameHash) + { + default: + ValueTag(sb, cind, ename, uintVal.ToString()); + break; + case MetaName.color: + ValueTag(sb, cind, ename, "0x" + uintVal.ToString("X").PadLeft(8, '0')); + break; + } + + break; + case MetaStructureEntryDataType.UnsignedShort: + var ushortVal = BitConverter.ToUInt16(data, eoffset); + ValueTag(sb, cind, ename, ushortVal.ToString());// "0x" + ushortVal.ToString("X").PadLeft(4, '0')); + break; + } + } + + switch (tagMode) + { + case XmlTagMode.Structure: + CloseTag(sb, indent, name); + break; + case XmlTagMode.Item: + case XmlTagMode.ItemAndType: + CloseTag(sb, indent, "Item"); + break; + } + + } + + private static void WriteArrayNode(StringBuilder sb, int indent, MetaCont cont, byte[] data, MetaStructureEntryInfo_s arrEntry, string ename, int eoffset) + { + int aCount = 0; + var aind = indent + 1; + string arrTag = ename; + switch (arrEntry.DataType) + { + default: + ErrorXml(sb, indent, ename + ": Unexpected array entry DataType: " + arrEntry.DataType.ToString()); + break; + case MetaStructureEntryDataType.Structure: + var arrStruc = MetaTypes.ConvertData(data, eoffset); + var aBlockId = (int)arrStruc.PointerDataId; + var aOffset = (int)arrStruc.PointerDataOffset; + aCount = arrStruc.Count1; + arrTag += " itemType=\"" + HashString(arrEntry.ReferenceKey) + "\""; + if (aCount > 0) + { + OpenTag(sb, indent, arrTag); + var atyp = cont.GetStructureInfo(arrEntry.ReferenceKey); + var aBlock = cont.Meta.GetBlock(aBlockId); + for (int n = 0; n < aCount; n++) + { + WriteNode(sb, aind, cont, aBlockId, aOffset, XmlTagMode.Item, arrEntry.ReferenceKey); + aOffset += atyp.StructureSize; + + if ((n < (aCount - 1)) && (aBlock != null) && (aOffset >= aBlock.DataLength)) + { + aOffset = 0; + aBlockId++; + aBlock = cont.Meta.GetBlock(aBlockId); + } + } + CloseTag(sb, indent, ename); + } + else + { + SelfClosingTag(sb, indent, arrTag); + } + break; + case MetaStructureEntryDataType.StructurePointer: + var arrStrucP = MetaTypes.ConvertData(data, eoffset); + var ptrArr = MetaTypes.GetPointerArray(cont.Meta, arrStrucP); + aCount = ptrArr?.Length ?? 0; + if (aCount > 0) + { + OpenTag(sb, indent, arrTag); + for (int n = 0; n < aCount; n++) + { + var ptr = ptrArr[n]; + var eboffset = ptr.ItemOffset * 16; + WriteNode(sb, aind, cont, ptr.BlockID, eboffset, XmlTagMode.ItemAndType); + } + CloseTag(sb, indent, ename); + } + else + { + SelfClosingTag(sb, indent, arrTag); + } + break; + case MetaStructureEntryDataType.UnsignedInt: + var arrUint = MetaTypes.ConvertData(data, eoffset); + var uintArr = MetaTypes.GetUintArray(cont.Meta, arrUint); + WriteRawArray(sb, uintArr, indent, ename, "uint"); + break; + case MetaStructureEntryDataType.UnsignedShort: + var arrUshort = MetaTypes.ConvertData(data, eoffset); + var ushortArr = MetaTypes.GetUshortArray(cont.Meta, arrUshort); + WriteRawArray(sb, ushortArr, indent, ename, "ushort"); + break; + case MetaStructureEntryDataType.UnsignedByte: + var arrUbyte = MetaTypes.ConvertData(data, eoffset); + var byteArr = MetaTypes.GetByteArray(cont.Meta, arrUbyte); + WriteRawArray(sb, byteArr, indent, ename, "byte"); + break; + case MetaStructureEntryDataType.Float: + var arrFloat = MetaTypes.ConvertData(data, eoffset); + var floatArr = MetaTypes.GetFloatArray(cont.Meta, arrFloat); + WriteRawArray(sb, floatArr, indent, ename, "float"); + break; + case MetaStructureEntryDataType.Float_XYZ: + var arrV3 = MetaTypes.ConvertData(data, eoffset); + var v4Arr = MetaTypes.ConvertDataArray(cont.Meta, MetaName.VECTOR4, arrV3.Pointer, arrV3.Count1); + WriteItemArray(sb, v4Arr, indent, ename, "Vector3/4", FormatVector4); + break; + case MetaStructureEntryDataType.CharPointer: + ErrorXml(sb, indent, "CharPointer ARRAY not supported here! Tell dexy!"); + break; + case MetaStructureEntryDataType.DataBlockPointer: + ErrorXml(sb, indent, "DataBlockPointer ARRAY not supported here! Tell dexy!"); + break; + case MetaStructureEntryDataType.Hash: + var arrHash = MetaTypes.ConvertData(data, eoffset); + var hashArr = MetaTypes.GetHashArray(cont.Meta, arrHash); + WriteItemArray(sb, hashArr, indent, ename, "Hash", FormatHash); + break; + } + } + + + + + private static string GetEnumString(MetaCont cont, MetaStructureEntryInfo_s entry, int value) + { + var eName = entry.ReferenceKey; + var eInfo = cont.GetEnumInfo(eName); + if ((eInfo == null) || (eInfo.Entries == null)) + { + return value.ToString(); + } + + bool isFlags = (entry.DataType == MetaStructureEntryDataType.IntFlags1) || + (entry.DataType == MetaStructureEntryDataType.IntFlags2);// || + //(entry.DataType == MetaStructureEntryDataType.ShortFlags); + + if (isFlags) + { + StringBuilder sb = new StringBuilder(); + foreach (var ev in eInfo.Entries) + { + var v = ev.EntryValue; + var m = 1 << v; + if ((value & m) > 0) + { + if (sb.Length > 0) sb.Append(", "); + sb.Append(HashString(ev.EntryNameHash)); + } + } + return sb.ToString(); + } + else + { + foreach (var ev in eInfo.Entries) + { + if (ev.EntryValue == value) + { + return HashString(ev.EntryNameHash); + } + } + return value.ToString(); //if we got here, there was no match... + } + } + + + + + private class MetaCont + { + public Meta Meta { get; set; } + + Dictionary structInfos = new Dictionary(); + Dictionary enumInfos = new Dictionary(); + + public MetaCont(Meta meta) + { + Meta = meta; + + if (meta.StructureInfos != null) + { + foreach (var si in meta.StructureInfos) + { + structInfos[si.StructureNameHash] = si; + } + } + if (meta.EnumInfos != null) + { + foreach (var ei in meta.EnumInfos) + { + enumInfos[ei.EnumNameHash] = ei; + } + } + } + + public MetaStructureInfo GetStructureInfo(MetaName name) + { + MetaStructureInfo i = null; + structInfos.TryGetValue(name, out i); + return i; + } + public MetaEnumInfo GetEnumInfo(MetaName name) + { + MetaEnumInfo i = null; + enumInfos.TryGetValue(name, out i); + return i; + } + + } + + } + + public class PsoXml : MetaXmlBase + { + + public static string GetXml(PsoFile pso) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(XmlHeader); + + if ((pso != null) && (pso.DataSection != null) && (pso.DataMapSection != null)) + { + var cont = new PsoCont(pso); + + WriteNode(sb, 0, cont, pso.DataMapSection.RootId, 0, XmlTagMode.Structure); + } + + return sb.ToString(); + } + + + private static void WriteNode(StringBuilder sb, int indent, PsoCont cont, int blockId, int offset, XmlTagMode tagMode = XmlTagMode.None, MetaName structName = 0) + { + + var block = cont.Pso.GetBlock(blockId); + if (block == null) + { + ErrorXml(sb, indent, "Couldn't find block " + blockId + "!"); + return; + } + + + var boffset = offset + block.Offset; + + if (structName == 0) + { + structName = block.NameHash; + } + + var name = HashString(structName); + var data = cont.Pso.DataSection.Data; + + var structInfo = cont.GetStructureInfo(structName); + if (structInfo == null) + { + ErrorXml(sb, indent, "Couldn't find structure info " + name + "!"); + return; + } + if (structInfo.Entries == null) + { + ErrorXml(sb, indent, "Couldn't find structure info entries for " + name + "!"); + return; + } + + switch (tagMode) + { + case XmlTagMode.Structure: + OpenTag(sb, indent, name); + break; + case XmlTagMode.Item: + OpenTag(sb, indent, "Item"); + break; + case XmlTagMode.ItemAndType: + OpenTag(sb, indent, "Item type=\"" + name + "\""); + break; + } + + + var cind = indent + 1; + for (int i = 0; i < structInfo.Entries.Length; i++) + { + var entry = structInfo.Entries[i]; + if (entry.EntryNameHash == MetaName.ARRAYINFO) + { + continue; + } + var ename = HashString(entry.EntryNameHash); + var eoffset = boffset + entry.DataOffset; + switch (entry.Type) + { + default: + ErrorXml(sb, cind, ename + ": Unexpected entry DataType: " + entry.Type.ToString()); + break; + case PsoDataType.Array: + + WriteArrayNode(sb, cind, cont, blockId, offset, entry, structInfo, ename); + + break; + case PsoDataType.Boolean: + var boolVal = BitConverter.ToBoolean(data, eoffset); + ValueTag(sb, cind, ename, boolVal?"true":"false"); + break; + case PsoDataType.Byte1: //was LONG_01h //signed byte? + //var long1Val = MetaTypes.SwapBytes(BitConverter.ToUInt64(data, eoffset)); + //ValueTag(sb, cind, ename, long1Val.ToString()); + var byte1Val = (sbyte)data[eoffset]; + ValueTag(sb, cind, ename, byte1Val.ToString()); + break; + case PsoDataType.Byte2: + var byte2Val = data[eoffset]; + ValueTag(sb, cind, ename, byte2Val.ToString()); + break; + case PsoDataType.Enum: + var enumInfo = cont.GetEnumInfo((MetaName)entry.ReferenceKey); + switch (entry.Unk_5h) + { + default: + ErrorXml(sb, cind, ename + ": Unexpected Enum subtype: " + entry.Unk_5h.ToString()); + break; + case 0: //int enum + var intEVal = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset)); + var intE = enumInfo.FindEntry(intEVal); + StringTag(sb, cind, ename, HashString(intE?.EntryNameHash ?? 0)); + break; + case 2: //byte enum + var byteEVal = data[eoffset]; + var byteE = enumInfo.FindEntry(byteEVal); + StringTag(sb, cind, ename, HashString(byteE?.EntryNameHash ?? 0)); + break; + } + break; + case PsoDataType.Flags: + var flagsInfo = cont.GetEnumInfo(entry.EntryNameHash); + uint? flagsVal = null; + switch (entry.Unk_5h) + { + default: + ErrorXml(sb, cind, ename + ": Unexpected Flags subtype: " + entry.Unk_5h.ToString()); + break; + case 0: //int flags + flagsVal = MetaTypes.SwapBytes(BitConverter.ToUInt32(data, eoffset)); + break; + case 1: //short flags + flagsVal = MetaTypes.SwapBytes(BitConverter.ToUInt16(data, eoffset)); + break; + case 2: //byte flags + flagsVal = data[eoffset]; + break; + } + if (flagsVal.HasValue) + { + uint fv = flagsVal.Value; + if (flagsInfo != null) + { + string fstr = ""; + for (int n = 0; n < flagsInfo.EntriesCount; n++) + { + var fentry = flagsInfo.Entries[n]; + var fmask = (1 << fentry.EntryKey); + if ((fv & fmask) > 0) + { + if (fstr != "") fstr += " "; + fstr += HashString(fentry.EntryNameHash); + } + } + StringTag(sb, cind, ename, fstr); + } + else + { + if (fv != 0) ValueTag(sb, cind, ename, fv.ToString()); + else SelfClosingTag(sb, cind, ename); + } + } + break; + case PsoDataType.Float: + var floatVal = MetaTypes.SwapBytes(BitConverter.ToSingle(data, eoffset)); + ValueTag(sb, cind, ename, FloatUtil.ToString(floatVal)); + break; + case PsoDataType.Float2: + var v2 = MetaTypes.SwapBytes(MetaTypes.ConvertData(data, eoffset)); + SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v2.X) + "\" y=\"" + FloatUtil.ToString(v2.Y) + "\""); + break; + case PsoDataType.Float3: + var v3 = MetaTypes.SwapBytes(MetaTypes.ConvertData(data, eoffset)); + SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3.X) + "\" y=\"" + FloatUtil.ToString(v3.Y) + "\" z=\"" + FloatUtil.ToString(v3.Z) + "\""); + break; + case PsoDataType.Float3a: //TODO: check this! + var v3a = MetaTypes.SwapBytes(MetaTypes.ConvertData(data, eoffset)); + SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3a.X) + "\" y=\"" + FloatUtil.ToString(v3a.Y) + "\" z=\"" + FloatUtil.ToString(v3a.Z) + "\""); + break; + case PsoDataType.Float3b: //TODO: check this! //...why are there 3 different types of float3? + var v3b = MetaTypes.SwapBytes(MetaTypes.ConvertData(data, eoffset)); + SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3b.X) + "\" y=\"" + FloatUtil.ToString(v3b.Y) + "\" z=\"" + FloatUtil.ToString(v3b.Z) + "\""); + break; + case PsoDataType.Float4: + var v4 = MetaTypes.SwapBytes(MetaTypes.ConvertData(data, eoffset)); + SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v4.X) + "\" y=\"" + FloatUtil.ToString(v4.Y) + "\" z=\"" + FloatUtil.ToString(v4.Z) + "\" w=\"" + FloatUtil.ToString(v4.W) + "\""); + break; + case PsoDataType.INT_05h: //TODO: convert hashes? + var int5Val = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset)); + ValueTag(sb, cind, ename, int5Val.ToString()); + break; + case PsoDataType.Integer: + switch (entry.Unk_5h) + { + default: + ErrorXml(sb, cind, ename + ": Unexpected Integer subtype: " + entry.Unk_5h.ToString()); + break; + case 0: //signed int + var int6aVal = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset)); + ValueTag(sb, cind, ename, int6aVal.ToString()); + break; + case 1: //unsigned int + var int6bVal = MetaTypes.SwapBytes(BitConverter.ToUInt32(data, eoffset)); + ValueTag(sb, cind, ename, "0x" + int6bVal.ToString("X").PadLeft(8, '0')); + break; + } + break; + case PsoDataType.LONG_20h: + var long2Val = MetaTypes.SwapBytes(BitConverter.ToUInt64(data, eoffset)); + ValueTag(sb, cind, ename, long2Val.ToString()); + break; + case PsoDataType.Map: + + WriteMapNode(sb, indent, cont, eoffset, entry, structInfo, ename); + + break; + case PsoDataType.SHORT_03h: + var short3Val = (short)MetaTypes.SwapBytes(BitConverter.ToUInt16(data, eoffset)); + ValueTag(sb, cind, ename, short3Val.ToString()); + break; + case PsoDataType.SHORT_04h: + var short4Val = MetaTypes.SwapBytes(BitConverter.ToUInt16(data, eoffset)); + ValueTag(sb, cind, ename, short4Val.ToString()); + break; + case PsoDataType.SHORT_1Eh://half float? + var short1EVal = MetaTypes.SwapBytes(BitConverter.ToUInt16(data, eoffset)); + ValueTag(sb, cind, ename, short1EVal.ToString()); + break; + case PsoDataType.String: + var str0 = GetStringValue(cont.Pso, entry, data, eoffset); + if (str0 == null) + { + ErrorXml(sb, cind, ename + ": Unexpected String subtype: " + entry.Unk_5h.ToString()); + } + else + { + StringTag(sb, cind, ename, str0); + } + break; + case PsoDataType.Structure: + switch (entry.Unk_5h) + { + default: + ErrorXml(sb, cind, ename + ": Unexpected Structure subtype: " + entry.Unk_5h.ToString()); + break; + case 0: //default structure + OpenTag(sb, cind, ename); + WriteNode(sb, cind, cont, blockId, offset + entry.DataOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey); + CloseTag(sb, cind, ename); + break; + case 3: //structure pointer... + case 4: //also pointer? what's the difference? + var ptrVal = MetaTypes.ConvertData(data, eoffset); + ptrVal.SwapEnd(); + var pbid = ptrVal.BlockID; + bool pbok = true; + if (pbid <= 0) + { + pbok = false; //no block specified? + } + if (pbid > cont.Pso.DataMapSection.EntriesCount) + { + pbok = false; //bad pointer? different type..? should output an error message here? + } + if (pbok) + { + WriteNode(sb, cind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey); + } + else + { + SelfClosingTag(sb, cind, ename); + } + break; + } + break; + } + } + + + + + switch (tagMode) + { + case XmlTagMode.Structure: + CloseTag(sb, indent, name); + break; + case XmlTagMode.Item: + case XmlTagMode.ItemAndType: + CloseTag(sb, indent, "Item"); + break; + } + } + + private static void WriteArrayNode(StringBuilder sb, int indent, PsoCont cont, int blockId, int offset, PsoStructureEntryInfo entry, PsoStructureInfo estruct, string ename) + { + + + var block = cont.Pso.GetBlock(blockId); + var boffset = offset + block.Offset; + var eoffset = boffset + entry.DataOffset; + var aOffset = offset + entry.DataOffset; + var aBlockId = blockId; + uint aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF; + var aind = indent + 1; + string arrTag = ename; + PsoStructureEntryInfo arrEntry = estruct.GetEntry((int)(entry.ReferenceKey & 0xFFFF)); + if (arrEntry == null) + { + ErrorXml(sb, indent, "ARRAYINFO not found for " + ename + "!"); + return; + } + + var data = cont.Pso.DataSection.Data; + + switch (entry.Unk_5h) + { + default: + ErrorXml(sb, indent, ename + ": WIP! Unsupported Array subtype: " + entry.Unk_5h.ToString()); + break; + case 0: //Array_Structure + var arrStruc = MetaTypes.ConvertData(data, eoffset); + arrStruc.SwapEnd(); + aBlockId = (int)arrStruc.PointerDataId; + aOffset = (int)arrStruc.PointerDataOffset; + aCount = arrStruc.Count1; + break; + case 1: //Raw in-line array + break; + case 2: //also raw in-line array, but how different from above? + break; + case 4: //pointer array? default array? + if (arrEntry.Unk_5h == 3) //pointers... + { + var arrStruc4 = MetaTypes.ConvertData(data, eoffset); + arrStruc4.SwapEnd(); + aBlockId = (int)arrStruc4.PointerDataId; + aOffset = (int)arrStruc4.PointerDataOffset; + aCount = arrStruc4.Count1; + } + break; + case 129: //also raw inline array? in junctions.pso + break; + } + + switch (arrEntry.Type) + { + default: + ErrorXml(sb, indent, ename + ": WIP! Unsupported array entry DataType: " + arrEntry.Type.ToString()); + break; + case PsoDataType.Array: + var rk0 = (entry.ReferenceKey >> 16) & 0x0000FFFF; + if (rk0 > 0) + { + //var arrStruc5 = MetaTypes.ConvertDataArray(data, eoffset, (int)rk0); + //for (int n = 0; n < rk0; n++) arrStruc5[n].SwapEnd(); + aOffset = offset + entry.DataOffset; + + OpenTag(sb, indent, arrTag); + for (int n = 0; n < rk0; n++) //ARRAY ARRAY! + { + WriteArrayNode(sb, aind, cont, blockId, aOffset, arrEntry, estruct, "Item"); + + aOffset += 16;//ptr size... todo: what if not pointer array? + } + CloseTag(sb, indent, ename); + } + else + { + SelfClosingTag(sb, indent, arrTag); + } + break; + case PsoDataType.Structure: + switch (arrEntry.Unk_5h) + { + case 0: + break; + case 3://structure pointer array + var arrStrucPtr = MetaTypes.ConvertData(data, eoffset); + arrStrucPtr.SwapEnd(); + aBlockId = (int)arrStrucPtr.PointerDataId; + aOffset = (int)arrStrucPtr.PointerDataOffset; + aCount = arrStrucPtr.Count1; + if (aCount > 0) + { + var ptrArr = PsoTypes.GetPointerArray(cont.Pso, arrStrucPtr); + OpenTag(sb, indent, arrTag); + for (int n = 0; n < aCount; n++) + { + var ptrVal = ptrArr[n]; + WriteNode(sb, aind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.ItemAndType); + } + CloseTag(sb, indent, ename); + } + break; + default: + break; + } + arrTag += " itemType=\"" + HashString((MetaName)arrEntry.ReferenceKey) + "\""; + if (aCount > 0) + { + var aBlock = cont.Pso.GetBlock(aBlockId); + var atyp = cont.GetStructureInfo((MetaName)arrEntry.ReferenceKey); + if (aBlock == null) + { + ErrorXml(sb, indent, ename + ": Array block not found: " + aBlockId.ToString()); + } + else if (aBlock.NameHash != MetaName.PsoPOINTER) + { + OpenTag(sb, indent, arrTag); + if (atyp == null) + { + ErrorXml(sb, indent, ename + ": Array type not found: " + HashString(arrEntry.ReferenceKey)); + } + else + { + for (int n = 0; n < aCount; n++) + { + WriteNode(sb, aind, cont, aBlockId, aOffset, XmlTagMode.Item, (MetaName)arrEntry.ReferenceKey); + aOffset += atyp.StructureLength; + if ((n < (aCount - 1)) && (aBlock != null) && (aOffset >= aBlock.Length)) + { + break; + } + } + } + CloseTag(sb, indent, ename); + } + else + { } //pointer array should get here, but it's already handled above. should improve this. + } + else + { + SelfClosingTag(sb, indent, arrTag); + } + break; + case PsoDataType.String: + switch (entry.Unk_5h) + { + default: + ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString()); + break; + case 0: //hash array... + var arrHash = MetaTypes.ConvertData(data, eoffset); + arrHash.SwapEnd(); + var hashArr = PsoTypes.GetHashArray(cont.Pso, arrHash); + WriteItemArray(sb, hashArr, indent, ename, "Hash", FormatHash); + break; + } + break; + case PsoDataType.Float2: + aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF; + arrTag += " itemType=\"Vector2\""; + var v2Arr = MetaTypes.ConvertDataArray(data, eoffset, (int)aCount); + WriteRawArray(sb, v2Arr, indent, ename, "Vector2", FormatVector2Swap, 1); + break; + case PsoDataType.Float3: + aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF; + arrTag += " itemType=\"Vector3\""; //this is actually aligned as vector4, the W values are crazy in places + var v4Arr = MetaTypes.ConvertDataArray(data, eoffset, (int)aCount); + WriteRawArray(sb, v4Arr, indent, ename, "Vector3", FormatVector4SwapXYZOnly, 1); + break; + case PsoDataType.Byte2: + var barr = new byte[aCount]; + if (aCount > 0) + { + var bblock = cont.Pso.GetBlock(aBlockId); + var boffs = bblock.Offset + aOffset; + Buffer.BlockCopy(data, boffs, barr, 0, (int)aCount); + } + WriteRawArray(sb, barr, indent, ename, "byte"); + break; + case PsoDataType.Boolean: + var barr2 = new byte[aCount]; + if (aCount > 0) + { + var bblock = cont.Pso.GetBlock(aBlockId); + var boffs = bblock.Offset + aOffset; + Buffer.BlockCopy(data, boffs, barr2, 0, (int)aCount); + } + WriteRawArray(sb, barr2, indent, ename, "boolean"); //todo: true/false output + break; + case PsoDataType.Float: + var arrFloat = MetaTypes.ConvertData(data, eoffset); + arrFloat.SwapEnd(); + var floatArr = PsoTypes.GetFloatArray(cont.Pso, arrFloat); + WriteRawArray(sb, floatArr, indent, ename, "float"); + break; + case PsoDataType.SHORT_04h: + var arrShort = MetaTypes.ConvertData(data, eoffset); + arrShort.SwapEnd(); + var shortArr = PsoTypes.GetUShortArray(cont.Pso, arrShort); + WriteRawArray(sb, shortArr, indent, ename, "ushort"); + break; + case PsoDataType.Integer: + var intArr = MetaTypes.ConvertDataArray(data, eoffset, (int)aCount); + WriteRawArray(sb, intArr, indent, ename, "int"); + break; + case PsoDataType.INT_05h: + var arrUint2 = MetaTypes.ConvertData(data, eoffset); + arrUint2.SwapEnd(); + var intArr2 = PsoTypes.GetUintArray(cont.Pso, arrUint2); + WriteRawArray(sb, intArr2, indent, ename, "int"); + break; + case PsoDataType.Enum: + var arrEnum = MetaTypes.ConvertData(data, eoffset); + arrEnum.SwapEnd(); + var enumArr = PsoTypes.GetUintArray(cont.Pso, arrEnum); + var enumDef = cont.GetEnumInfo((MetaName)arrEntry.ReferenceKey); + WriteItemArray(sb, enumArr, indent, ename, "enum", (ie)=> { + var eval = enumDef?.FindEntry((int)ie); + return HashString(eval?.EntryNameHash ?? 0); + }); + break; + } + + } + + private static void WriteMapNode(StringBuilder sb, int indent, PsoCont cont, int eoffset, PsoStructureEntryInfo entry, PsoStructureInfo structInfo, string ename) + { + var cind = indent + 1; + var data = cont.Pso.DataSection.Data; + switch (entry.Unk_5h) + { + default: + ErrorXml(sb, cind, ename + ": Unexpected Map subtype: " + entry.Unk_5h.ToString()); + break; + case 1: + var mapidx1 = entry.ReferenceKey & 0x0000FFFF; + var mapidx2 = (entry.ReferenceKey >> 16) & 0x0000FFFF; + var mapreftype1 = structInfo.Entries[mapidx2]; + var mapreftype2 = structInfo.Entries[mapidx1]; + var x1 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));//same as ref key? + var x2 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 4));//0? + var xStrucPtr = MetaTypes.ConvertData(data, eoffset + 8); + xStrucPtr.SwapEnd(); + var xBlockId = (int)xStrucPtr.PointerDataId; + var xBlock = cont.Pso.GetBlock(xBlockId); + if ((xBlock == null) && (xStrucPtr.Count1 > 0)) + { + ErrorXml(sb, cind, ename + ": Couldn't find Map xBlock: " + xStrucPtr.PointerDataId.ToString()); + } + else + { + if (xStrucPtr.Count1 != xStrucPtr.Count2) + { + } + if (xStrucPtr.Count1 > 0) + { + var xStruct = cont.GetStructureInfo(xBlock.NameHash); + var xOffset1 = xStrucPtr.PointerDataOffset; + var xind = indent + 1; + var aind = indent + 2; + var kEntry = xStruct?.FindEntry(MetaName.Key); + var iEntry = xStruct?.FindEntry(MetaName.Item); + + if ((xStruct == null) && (xBlock.NameHash == 0)) + { + SelfClosingTag(sb, cind, ename); + } + else if (xStruct == null) + { + ErrorXml(sb, aind, ename + ": Map struct type not found: " + HashString(xBlock.NameHash)); + } + else if ((xStruct.IndexInfo == null) || (xStruct.IndexInfo.NameHash != MetaName.ARRAYINFO)) + { + ErrorXml(sb, aind, ename + ": Map struct was not ARRAYINFO! " + (xStruct == null ? "" : xStruct.ToString())); + } + else if ((kEntry == null) || (iEntry == null)) + { + ErrorXml(sb, aind, ename + ": Map Key/Item entries not found!"); + } + else if (kEntry.Type != PsoDataType.String) + { + ErrorXml(sb, aind, ename + ": Map Key was not a string!"); + } + else if (iEntry.Type != PsoDataType.Structure) + { + ErrorXml(sb, aind, ename + ": Map Item was not a structure!"); + } + else if (iEntry.Unk_5h != 3) + { + ErrorXml(sb, aind, ename + ": Map Item was not a structure pointer!"); + } + else + { + OpenTag(sb, xind, ename); + int xOffset = (int)xOffset1; + int xCount = xStrucPtr.Count1; + + for (int n = 0; n < xCount; n++) + { + //WriteNode(sb, aind, cont, xBlockId, xOffset, XmlTagMode.Item, xStruct.IndexInfo.NameHash); + + int sOffset = xOffset + xBlock.Offset; + var kOffset = sOffset + kEntry.DataOffset; + var iOffset = sOffset + iEntry.DataOffset; + var kStr = GetStringValue(cont.Pso, kEntry, data, kOffset); + var iPtr = MetaTypes.ConvertData(data, iOffset); + iPtr.SwapEnd(); + var iBlock = cont.Pso.GetBlock(iPtr.BlockID); + if (iBlock == null) + { + OpenTag(sb, aind, "Item type=\"" + HashString((MetaName)entry.ReferenceKey) + "\" key=\"" + kStr + "\""); + WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey); + CloseTag(sb, aind, "Item"); + } + else + { + var iStr = "Item type=\"" + HashString(iBlock.NameHash) + "\" key=\"" + kStr + "\""; + var iStruc = cont.GetStructureInfo(iBlock.NameHash); + if (iStruc?.EntriesCount == 0) + { + SelfClosingTag(sb, aind, iStr); + } + else + { + OpenTag(sb, aind, iStr); + WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None);//, (MetaName)entry.ReferenceKey); + CloseTag(sb, aind, "Item"); + } + } + xOffset += xStruct.StructureLength; + if ((n < (xCount - 1)) && (xBlock != null) && (xOffset >= xBlock.Length)) + { + ErrorXml(sb, aind, "Offset out of range! Count is " + xCount.ToString()); + break; //out of range... + } + } + CloseTag(sb, xind, ename); + } + } + else + { + SelfClosingTag(sb, cind, ename); + } + } + break; + } + } + + + + + private static string GetStringValue(PsoFile pso, PsoStructureEntryInfo entry, byte[] data, int eoffset) + { + switch (entry.Unk_5h) + { + default: + return null; + case 0: + var str0len = (int)((entry.ReferenceKey >> 16) & 0xFFFF); + return Encoding.ASCII.GetString(data, eoffset, str0len).Replace("\0", ""); + case 1: + case 2: + var dataPtr2 = MetaTypes.ConvertData(data, eoffset); + dataPtr2.SwapEnd(); + return PsoTypes.GetString(pso, dataPtr2); + case 3: + var charPtr3 = MetaTypes.ConvertData(data, eoffset); + charPtr3.SwapEnd(); + var strval = PsoTypes.GetString(pso, charPtr3); + return strval ?? ""; + case 7: + case 8: + var hashVal = MetaTypes.SwapBytes(MetaTypes.ConvertData(data, eoffset)); + return HashString(hashVal); + } + + } + + + + + public class PsoCont + { + public PsoFile Pso { get; set; } + + public Dictionary EnumDict = new Dictionary(); + public Dictionary StructDict = new Dictionary(); + + + public PsoCont(PsoFile pso) + { + Pso = pso; + + if ((pso.SchemaSection == null) || (pso.SchemaSection.Entries == null) || (pso.SchemaSection.EntriesIdx == null)) + { + return; + } + + + for (int i = 0; i < pso.SchemaSection.Entries.Length; i++) + { + var entry = pso.SchemaSection.Entries[i]; + var enuminfo = entry as PsoEnumInfo; + var structinfo = entry as PsoStructureInfo; + + if (enuminfo != null) + { + if (!EnumDict.ContainsKey(enuminfo.IndexInfo.NameHash)) + { + EnumDict.Add(enuminfo.IndexInfo.NameHash, enuminfo); + } + else + { + //PsoEnumInfo oldei = EnumDict[enuminfo.IndexInfo.NameHash]; + //if (!ComparePsoEnumInfos(oldei, enuminfo)) + //{ + //} + } + } + else if (structinfo != null) + { + if (!StructDict.ContainsKey(structinfo.IndexInfo.NameHash)) + { + StructDict.Add(structinfo.IndexInfo.NameHash, structinfo); + } + else + { + //PsoStructureInfo oldsi = StructDict[structinfo.IndexInfo.NameHash]; + //if (!ComparePsoStructureInfos(oldsi, structinfo)) + //{ + //} + } + } + + } + } + + + public PsoStructureInfo GetStructureInfo(MetaName name) + { + PsoStructureInfo i = null; + StructDict.TryGetValue(name, out i); + return i; + } + public PsoEnumInfo GetEnumInfo(MetaName name) + { + PsoEnumInfo i = null; + EnumDict.TryGetValue(name, out i); + return i; + } + + } + + } + + public class RbfXml : MetaXmlBase + { + + public static string GetXml(RbfFile rbf) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(XmlHeader); + + WriteNode(sb, 0, rbf.current); + + return sb.ToString(); + } + + private static void WriteNode(StringBuilder sb, int indent, RbfStructure rs) + { + if (rs.Children.Count == 0) + { + SelfClosingTag(sb, indent, rs.Name); + return; + } + + int cind = indent + 1; + + bool oneline = ((rs.Children.Count == 1) && (rs.Children[0].Name == null)); + + OpenTag(sb, indent, rs.Name, !oneline); + + + foreach (var child in rs.Children) + { + if (child is RbfBytes) + { + var bytesChild = (RbfBytes)child; + var contentField = rs.FindChild("content") as RbfString;//TODO: fix this to output nicer XML! + if (contentField != null) + { + OpenTag(sb, cind, "value"); + var aind = cind + 1; + + if (contentField.Value == "char_array") + { + foreach (byte k in bytesChild.Value) + { + Indent(sb, aind); + sb.AppendLine(k.ToString()); + } + } + else if (contentField.Value.Equals("short_array")) + { + var valueReader = new DataReader(new MemoryStream(bytesChild.Value)); + while (valueReader.Position < valueReader.Length) + { + Indent(sb, aind); + var y = valueReader.ReadUInt16(); + sb.AppendLine(y.ToString()); + } + } + else + { + ErrorXml(sb, aind, "Unexpected content type: " + contentField.Value); + } + + CloseTag(sb, cind, "value"); + } + else + { + string stringValue = Encoding.ASCII.GetString(bytesChild.Value); + string str = stringValue.Substring(0, stringValue.Length - 1); //removes null terminator + + sb.Append(str); + } + } + if (child is RbfFloat) + { + var floatChild = (RbfFloat)child; + ValueTag(sb, cind, child.Name, FloatUtil.ToString(floatChild.Value)); + } + if (child is RbfString) + { + var stringChild = (RbfString)child; + StringTag(sb, cind, stringChild.Name, stringChild.Value); + + //if (stringChild.Name.Equals("content")) + //else if (stringChild.Name.Equals("type")) + //else throw new Exception("Unexpected string content"); + } + if (child is RbfStructure) + { + WriteNode(sb, cind, child as RbfStructure); + } + if (child is RbfUint32) + { + var intChild = (RbfUint32)child; + ValueTag(sb, cind, intChild.Name, UintString(intChild.Value)); + } + if (child is RbfBoolean) + { + var booleanChild = (RbfBoolean)child; + ValueTag(sb, cind, booleanChild.Name, booleanChild.Value.ToString()); + } + if (child is RbfFloat3) + { + var v3 = child as RbfFloat3; + SelfClosingTag(sb, cind, v3.Name + " x=\"" + FloatUtil.ToString(v3.X) + "\" y=\"" + FloatUtil.ToString(v3.Y) + "\" z=\"" + FloatUtil.ToString(v3.Z) + "\""); + } + + + } + + CloseTag(sb, oneline ? 0 : indent, rs.Name); + } + + + + } + + + public class MetaXmlBase + { + + public const string XmlHeader = ""; + + + + public static void Indent(StringBuilder sb, int indent) + { + for (int i = 0; i < indent; i++) + { + sb.Append(" "); + } + } + public static void ErrorXml(StringBuilder sb, int indent, string msg) + { + Indent(sb, indent); + sb.Append(""); + sb.Append(msg); + sb.Append(""); + sb.AppendLine(); + } + public static void OpenTag(StringBuilder sb, int indent, string name, bool appendLine = true) + { + Indent(sb, indent); + sb.Append("<"); + sb.Append(name); + sb.Append(">"); + if (appendLine) sb.AppendLine(); + } + public static void CloseTag(StringBuilder sb, int indent, string name, bool appendLine = true) + { + Indent(sb, indent); + sb.Append(""); + if (appendLine) sb.AppendLine(); + } + public static void ValueTag(StringBuilder sb, int indent, string name, string val) + { + Indent(sb, indent); + sb.Append("<"); + sb.Append(name); + sb.Append(" value=\""); + sb.Append(val); + sb.Append("\" />"); + sb.AppendLine(); + } + public static void OneLineTag(StringBuilder sb, int indent, string name, string text) + { + Indent(sb, indent); + sb.Append("<"); + sb.Append(name); + sb.Append(">"); + sb.Append(text); + sb.Append(""); + sb.AppendLine(); + } + public static void SelfClosingTag(StringBuilder sb, int indent, string val) + { + Indent(sb, indent); + sb.Append("<"); + sb.Append(val); + sb.Append(" />"); + sb.AppendLine(); + } + public static void StringTag(StringBuilder sb, int indent, string name, string text) + { + if (!string.IsNullOrEmpty(text)) OneLineTag(sb, indent, name, text); + else SelfClosingTag(sb, indent, name); + } + + public static void WriteRawArray(StringBuilder sb, T[] arr, int ind, string name, string typeName, Func formatter = null, int arrRowSize = 10) where T : struct + { + var aCount = arr?.Length ?? 0; + //var arrRowSize = 10; + var aind = ind + 1; + var arrTag = name;// + " itemType=\"" + typeName + "\""; + if (aCount > 0) + { + if (aCount <= arrRowSize) + { + OpenTag(sb, ind, arrTag, false); + for (int n = 0; n < aCount; n++) + { + if (n > 0) sb.Append(" "); + string str = (formatter != null) ? formatter(arr[n]) : arr[n].ToString(); + sb.Append(str); + } + CloseTag(sb, 0, name); + } + else + { + OpenTag(sb, ind, arrTag); + for (int n = 0; n < aCount; n++) + { + var col = n % arrRowSize; + if (col == 0) Indent(sb, aind); + if (col > 0) sb.Append(" "); + string str = (formatter != null) ? formatter(arr[n]) : arr[n].ToString(); + sb.Append(str); + bool lastcol = (col == (arrRowSize - 1)); + bool lastn = (n == (aCount - 1)); + if (lastcol || lastn) sb.AppendLine(); + } + CloseTag(sb, ind, name); + } + } + else + { + SelfClosingTag(sb, ind, arrTag); + } + } + + public static void WriteItemArray(StringBuilder sb, T[] arr, int ind, string name, string typeName, Func formatter) where T : struct + { + var aCount = arr?.Length ?? 0; + var arrTag = name;// + " itemType=\"Hash\""; + var aind = ind + 1; + if (aCount > 0) + { + OpenTag(sb, ind, arrTag); + for (int n = 0; n < aCount; n++) + { + Indent(sb, aind); + sb.Append(""); + sb.Append(formatter(arr[n])); + sb.AppendLine(""); + } + CloseTag(sb, ind, name); + } + else + { + SelfClosingTag(sb, ind, arrTag); + } + } + + public static string FormatHash(MetaHash h) //for use with WriteItemArray + { + return h.ToString(); + } + public static string FormatVector2(Vector2 v) //for use with WriteItemArray + { + return FloatUtil.GetVector2String(v); + } + public static string FormatVector3(Vector3 v) //for use with WriteItemArray + { + return FloatUtil.GetVector3String(v); + } + public static string FormatVector4(Vector4 v) //for use with WriteItemArray + { + return FloatUtil.GetVector4String(v); + } + + public static string FormatHashSwap(MetaHash h) //for use with WriteItemArray, swaps endianness + { + return MetaTypes.SwapBytes(h).ToString(); + } + public static string FormatVector2Swap(Vector2 v) //for use with WriteItemArray, swaps endianness + { + return FloatUtil.GetVector2String(MetaTypes.SwapBytes(v)); + } + public static string FormatVector3Swap(Vector3 v) //for use with WriteItemArray, swaps endianness + { + return FloatUtil.GetVector3String(MetaTypes.SwapBytes(v)); + } + public static string FormatVector4Swap(Vector4 v) //for use with WriteItemArray, swaps endianness + { + return FloatUtil.GetVector4String(MetaTypes.SwapBytes(v)); + } + public static string FormatVector4SwapXYZOnly(Vector4 v) //for use with WriteItemArray, swaps endianness, and outputs only XYZ components + { + return FloatUtil.GetVector3String(MetaTypes.SwapBytes(v.XYZ())); + } + + + + public static string HashString(MetaName h) + { + if (Enum.IsDefined(typeof(MetaName), h)) + { + return h.ToString(); + } + + uint uh = (uint)h; + if (uh == 0) return ""; + + var str = JenkIndex.TryGetString(uh); + if (!string.IsNullOrEmpty(str)) return str; + + //TODO: do extra hash lookup here + //if(Lookup.TryGetValue(uh, out str)) ... + + return "hash_" + uh.ToString("X").PadLeft(8, '0'); + + } + public static string HashString(MetaHash h) + { + var str = JenkIndex.TryGetString(h); + + //todo: make sure JenkIndex is built! + //todo: do extra hash lookup here + + if (h == 0) return ""; + + + if (!string.IsNullOrEmpty(str)) return str; + return "hash_" + h.Hex; + } + + + public static string UintString(uint h) + { + if (Enum.IsDefined(typeof(MetaName), h)) + { + return ((MetaName)h).ToString(); + } + + var str = JenkIndex.TryGetString(h); + if (!string.IsNullOrEmpty(str)) return str; + + //TODO: do extra hash lookup here + //if(Lookup.TryGetValue(uh, out str)) ... + + + //if (h == 0) return ""; + return "0x" + h.ToString("X"); + + } + + + + public enum XmlTagMode + { + None = 0, + Structure = 1, + Item = 2, + ItemAndType = 3, + } + } + + +} diff --git a/GameFiles/MetaTypes/Pso.cs b/GameFiles/MetaTypes/Pso.cs new file mode 100644 index 0000000..9f3a98c --- /dev/null +++ b/GameFiles/MetaTypes/Pso.cs @@ -0,0 +1,910 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen and mangled + + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + public enum PsoSection : uint + { + PSIN = 0x5053494E, + PMAP = 0x504D4150, + PSCH = 0x50534348, + PSIG = 0x50534947, + STRF = 0x53545246, + STRS = 0x53545253, + STRE = 0x53545245, + CHKS = 0x43484B53, + } + + public enum PsoDataType : byte + { + //BYTE_00h = 0x00, + //LONG_01h = 0x01, + //BYTE_02h = 0x02, + //SHORT_03h = 0x03, + //SHORT_04h = 0x04, + //INT_05h = 0x05, + //INT_06h = 0x06, + //Float = 0x07, + //LONG_08h = 0x08, + //TYPE_09h = 0x09, + //TYPE_0Ah = 0x0a, + //INT_0Bh = 0x0b, //Hash? Name + //Structure = 0x0c, + //Array = 0x0d, + //BYTE_ENUM_VALUE = 0x0e, + //SHORT_0Fh = 0x0f, //short flags + //TYPE_10h = 0x10, + //TYPE_14h = 0x14, + //Vector4 = 0x15, + //SHORT_1Eh = 0x1e, + //LONG_20h = 0x20 + + Boolean = 0x00, + Byte1 = 0x01, //signed byte.. + Byte2 = 0x02, + SHORT_03h = 0x03, //signed short? + SHORT_04h = 0x04, + INT_05h = 0x05, //signed int? + Integer = 0x06, //...unsigned? + Float = 0x07, + Float2 = 0x08, + Float3 = 0x09, + Float4 = 0x0a, + String = 0x0b, + Structure = 0x0c, + Array = 0x0d, + Enum = 0x0e, + Flags = 0x0f, + Map = 0x10, + Float3a = 0x14, + Float3b = 0x15, + SHORT_1Eh = 0x1e, + LONG_20h = 0x20 + + } + public static class PsoDataTypes + { + public static string GetCSharpTypeName(PsoDataType t) + { + //MetaStructureEntryDataType mdt = (MetaStructureEntryDataType)t; + switch (t) + { + case PsoDataType.Boolean: return "bool"; + case PsoDataType.Byte1: return "sbyte"; //was LONG_01h.. why? + case PsoDataType.Byte2: return "byte"; + case PsoDataType.SHORT_03h: return "short"; + case PsoDataType.SHORT_04h: return "short"; + case PsoDataType.INT_05h: return "int"; + case PsoDataType.Integer: return "int"; + case PsoDataType.Float: return "float"; + case PsoDataType.Float2: return "long"; + case PsoDataType.String: return "uint"; //hash? NEEDS WORK? + case PsoDataType.Enum: return "byte"; + case PsoDataType.Flags: return "short"; + case PsoDataType.SHORT_1Eh: return "short"; + case PsoDataType.LONG_20h: return "long"; + case PsoDataType.Float3: + case PsoDataType.Float4: + case PsoDataType.Map: + case PsoDataType.Float3a: + case PsoDataType.Float3b: + case PsoDataType.Structure: + case PsoDataType.Array: + default: + return t.ToString(); + + //case MetaStructureEntryDataType.Boolean: return "bool"; + //case MetaStructureEntryDataType.SignedByte: return "sbyte"; + //case MetaStructureEntryDataType.UnsignedByte: return "byte"; + //case MetaStructureEntryDataType.SignedShort: return "short"; + //case MetaStructureEntryDataType.UnsignedShort: return "ushort"; + //case MetaStructureEntryDataType.SignedInt: return "int"; + //case MetaStructureEntryDataType.UnsignedInt: return "uint"; + //case MetaStructureEntryDataType.Float: return "float"; + //case MetaStructureEntryDataType.Float_XYZ: return "Vector3"; + //case MetaStructureEntryDataType.Float_XYZW: return "Vector4"; + + //case MetaStructureEntryDataType.Hash: return "uint"; //uint hashes... + //case MetaStructureEntryDataType.ByteEnum: return "byte"; //convert to enum later.. + //case MetaStructureEntryDataType.IntEnum: return "int"; + //case MetaStructureEntryDataType.ShortFlags: return "short"; + //case MetaStructureEntryDataType.IntFlags1: return "int"; + //case MetaStructureEntryDataType.IntFlags2: return "int"; + + //case MetaStructureEntryDataType.Array: + //case MetaStructureEntryDataType.ArrayOfChars: + //case MetaStructureEntryDataType.ArrayOfBytes: + //case MetaStructureEntryDataType.DataBlockPointer: + //case MetaStructureEntryDataType.CharPointer: + //case MetaStructureEntryDataType.StructurePointer: + //case MetaStructureEntryDataType.Structure: + //default: + // return t.ToString(); + } + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoFile + { + public PsoDataSection DataSection { get; set; } + public PsoDataMapSection DataMapSection { get; set; } + public PsoSchemaSection SchemaSection { get; set; } + public PsoSTRFSection STRFSection { get; set; } + public PsoSTRSSection STRSSection { get; set; } + public PsoPSIGSection PSIGSection { get; set; } + public PsoSTRESection STRESection { get; set; } + public PsoCHKSSection CHKSSection { get; set; } + + public void Load(string fileName) + { + using (var stream = new FileStream(fileName, FileMode.Open)) + Load(stream); + } + + public virtual void Load(Stream stream) + { + stream.Position = 0; + + var reader = new DataReader(stream, Endianess.BigEndian); + while (reader.Position < reader.Length) + { + var identInt = reader.ReadUInt32(); + var ident = (PsoSection)identInt; + var length = reader.ReadInt32(); + + reader.Position -= 8; + + var sectionData = reader.ReadBytes(length); + var sectionStream = new MemoryStream(sectionData); + var sectionReader = new DataReader(sectionStream, Endianess.BigEndian); + + switch (ident) + { + case PsoSection.PSIN: //0x5053494E "PSIN" - ID / data section + DataSection = new PsoDataSection(); + DataSection.Read(sectionReader); + break; + case PsoSection.PMAP: //0x504D4150 "PMAP" //data mapping + DataMapSection = new PsoDataMapSection(); + DataMapSection.Read(sectionReader); + break; + case PsoSection.PSCH: //0x50534348 "PSCH" //schema + SchemaSection = new PsoSchemaSection(); + SchemaSection.Read(sectionReader); + break; + case PsoSection.STRF: //0x53545246 "STRF" //paths/STRINGS (folder strings?) + STRFSection = new PsoSTRFSection(); + STRFSection.Read(sectionReader); + break; + case PsoSection.STRS: //0x53545253 "STRS" //names/strings (DES_) + STRSSection = new PsoSTRSSection(); + STRSSection.Read(sectionReader); + break; + case PsoSection.STRE: //0x53545245 "STRE" //probably encrypted strings..... + STRESection = new PsoSTRESection(); + STRESection.Read(sectionReader); + break; + case PsoSection.PSIG: //0x50534947 "PSIG" //signature? + PSIGSection = new PsoPSIGSection(); + PSIGSection.Read(sectionReader); + break; + case PsoSection.CHKS: //0x43484B53 "CHKS" //checksum? + CHKSSection = new PsoCHKSSection(); + CHKSSection.Read(sectionReader); + break; + default: + break; + } + } + } + + public void Save(string fileName) + { + using (var stream = new FileStream(fileName, FileMode.Create)) + Save(stream); + } + + public virtual void Save(Stream stream) + { + var writer = new DataWriter(stream, Endianess.BigEndian); + if (DataSection != null) DataSection.Write(writer); + if (DataMapSection != null) DataMapSection.Write(writer); + if (SchemaSection != null) SchemaSection.Write(writer); + } + + + + + + public PsoDataMappingEntry GetBlock(int id) + { + if (DataMapSection == null) return null; + if (DataMapSection.Entries == null) return null; + PsoDataMappingEntry block = null; + var ind = id - 1; + var blocks = DataMapSection.Entries; + if ((ind >= 0) && (ind < blocks.Length)) + { + block = blocks[ind]; + } + return block; + } + + + + + + public static bool IsPSO(Stream stream) + { + //return !IsRBF(stream); + + //1347635534 + var reader = new DataReader(stream, Endianess.BigEndian); + var identInt = reader.ReadUInt32(); + stream.Position = 0; + return ((identInt ) == 1347635534); //"PSIN" + + } + + public static bool IsRBF(Stream stream) + { + var reader = new DataReader(stream, Endianess.BigEndian); + var identInt = reader.ReadUInt32(); + stream.Position = 0; + return ((identInt & 0xFFFFFF00) == 0x52424600); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoDataSection + { + public uint Ident { get; set; } = 0x5053494E; + public int Length { get; private set; } + public byte[] Data { get; set; } + + public void Read(DataReader reader) + { + Ident = reader.ReadUInt32(); + Length = reader.ReadInt32(); + reader.Position -= 8; + Data = reader.ReadBytes(Length); + } + + public void Write(DataWriter writer) + { + writer.Write(Data); + writer.Position -= Data.Length; + writer.Write((uint)0x5053494E); + writer.Write((uint)(Data.Length)); + writer.Position += Data.Length - 8; + } + + public override string ToString() + { + return Ident.ToString() + ": " + Length.ToString(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoDataMapSection + { + public int Ident { get; set; } = 0x504D4150; + public int Length { get; private set; } + public int RootId { get; set; } + public short EntriesCount { get; private set; } + public short Unknown_Eh { get; set; } = 0x7070; + public PsoDataMappingEntry[] Entries { get; set; } + + public void Read(DataReader reader) + { + Ident = reader.ReadInt32(); + Length = reader.ReadInt32(); + RootId = reader.ReadInt32(); + EntriesCount = reader.ReadInt16(); + Unknown_Eh = reader.ReadInt16(); + Entries = new PsoDataMappingEntry[EntriesCount]; + for (int i = 0; i < EntriesCount; i++) + { + var entry = new PsoDataMappingEntry(); + entry.Read(reader); + Entries[i] = entry; + } + } + + public void Write(DataWriter writer) + { + // update... + EntriesCount = (short)Entries.Length; + Length = 16 + EntriesCount * 16; + + writer.Write(Ident); + writer.Write(Length); + writer.Write(RootId); + writer.Write(EntriesCount); + writer.Write(Unknown_Eh); + foreach (var entry in Entries) + { + entry.Write(writer); + } + } + + public override string ToString() + { + return Ident.ToString() + ": " + EntriesCount.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoDataMappingEntry + { + public MetaName NameHash { get; set; } + public int Offset { get; set; } + public int Unknown_8h { get; set; } = 0x00000000; + public int Length { get; set; } + + public void Read(DataReader reader) + { + this.NameHash = (MetaName)reader.ReadUInt32(); + this.Offset = reader.ReadInt32(); + this.Unknown_8h = reader.ReadInt32(); + this.Length = reader.ReadInt32(); + } + + public void Write(DataWriter writer) + { + writer.Write((uint)NameHash); + writer.Write(Offset); + writer.Write(Unknown_8h); + writer.Write(Length); + } + + public override string ToString() + { + return NameHash.ToString() + ": " + Offset.ToString() + ": " + Length.ToString(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoSchemaSection + { + public int Ident { get; private set; } = 0x50534348; + public int Length { get; set; } + public uint Count { get; set; } + + public PsoElementIndexInfo[] EntriesIdx { get; set; } + public PsoElementInfo[] Entries { get; set; } + + public void Read(DataReader reader) + { + Ident = reader.ReadInt32(); + Length = reader.ReadInt32(); + Count = reader.ReadUInt32(); + + this.EntriesIdx = new PsoElementIndexInfo[Count]; + for (int i = 0; i < Count; i++) + { + var entry = new PsoElementIndexInfo(); + entry.Read(reader); + EntriesIdx[i] = entry; + } + + this.Entries = new PsoElementInfo[Count]; + for (int i = 0; i < Count; i++) + { + reader.Position = EntriesIdx[i].Offset; + var type = reader.ReadByte(); + + reader.Position = EntriesIdx[i].Offset; + if (type == 0) + { + var entry = new PsoStructureInfo(); + entry.Read(reader); + entry.IndexInfo = EntriesIdx[i]; + Entries[i] = entry; + } + else if (type == 1) + { + var entry = new PsoEnumInfo(); + entry.Read(reader); + entry.IndexInfo = EntriesIdx[i]; + Entries[i] = entry; + } + else + throw new Exception("unknown type!"); + } + } + + public void Write(DataWriter writer) + { + + var entriesStream = new MemoryStream(); + var entriesWriter = new DataWriter(entriesStream, Endianess.BigEndian); + for (int i = 0; i < Entries.Length; i++) + { + EntriesIdx[i].Offset = 12 + 8 * Entries.Length + (int)entriesWriter.Position; + Entries[i].Write(entriesWriter); + } + + + + var indexStream = new MemoryStream(); + var indexWriter = new DataWriter(indexStream, Endianess.BigEndian); + foreach (var entry in EntriesIdx) + entry.Write(indexWriter); + + + + + writer.Write(Ident); + writer.Write((int)(12 + entriesStream.Length + indexStream.Length)); + writer.Write((int)(Entries.Length)); + + // write entries index data + var buf1 = new byte[indexStream.Length]; + indexStream.Position = 0; + indexStream.Read(buf1, 0, buf1.Length); + writer.Write(buf1); + + // write entries data + var buf2 = new byte[entriesStream.Length]; + entriesStream.Position = 0; + entriesStream.Read(buf2, 0, buf2.Length); + writer.Write(buf2); + + + } + + public override string ToString() + { + return Ident.ToString() + ": " + Count.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoElementIndexInfo + { + public MetaName NameHash { get; set; } + public int Offset { get; set; } + + public void Read(DataReader reader) + { + this.NameHash = (MetaName)reader.ReadUInt32(); + this.Offset = reader.ReadInt32(); + } + + public void Write(DataWriter writer) + { + writer.Write((uint)NameHash); + writer.Write(Offset); + } + + public override string ToString() + { + return NameHash.ToString() + ": " + Offset.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public abstract class PsoElementInfo + { + public PsoElementIndexInfo IndexInfo { get; set; } + + public abstract void Read(DataReader reader); + + public abstract void Write(DataWriter writer); + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoStructureInfo : PsoElementInfo + { + public byte Type { get; set; } = 0; + public short EntriesCount { get; private set; } + public byte Unk { get; set; } + public int StructureLength { get; set; } + public uint Unk_Ch { get; set; } = 0x00000000; + public PsoStructureEntryInfo[] Entries { get; set; } + + public override void Read(DataReader reader) + { + uint x = reader.ReadUInt32(); + this.Type = (byte)((x & 0xFF000000) >> 24); + this.EntriesCount = (short)(x & 0xFFFF); + this.Unk = (byte)((x & 0x00FF0000) >> 16); + this.StructureLength = reader.ReadInt32(); + this.Unk_Ch = reader.ReadUInt32(); + + Entries = new PsoStructureEntryInfo[EntriesCount]; + for (int i = 0; i < EntriesCount; i++) + { + var entry = new PsoStructureEntryInfo(); + entry.Read(reader); + Entries[i] = entry; + } + } + + public override void Write(DataWriter writer) + { + Type = 0; + EntriesCount = (short)Entries.Length; + + uint typeAndEntriesCount = (uint)(Type << 24) | (uint)(Unk << 16) | (ushort)EntriesCount; + writer.Write(typeAndEntriesCount); + writer.Write(StructureLength); + writer.Write(Unk_Ch); + + foreach (var entry in Entries) + { + entry.Write(writer); + } + } + + public override string ToString() + { + return IndexInfo.ToString() + " - " + Type.ToString() + ": " + EntriesCount.ToString(); + } + + public PsoStructureEntryInfo FindEntry(MetaName name) + { + if (Entries != null) + { + foreach (var entry in Entries) + { + if (entry.EntryNameHash == name) return entry; + } + } + return null; + } + public PsoStructureEntryInfo GetEntry(int id) + { + if ((Entries != null) && (id >= 0) && (id < Entries.Length)) + { + return Entries[id]; + } + return null; + } + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoStructureEntryInfo + { + public MetaName EntryNameHash { get; set; } + public PsoDataType Type { get; set; } + public byte Unk_5h { get; set; } + public ushort DataOffset { get; set; } + public uint ReferenceKey { get; set; } // when array -> entry index with type + + public void Read(DataReader reader) + { + this.EntryNameHash = (MetaName)reader.ReadUInt32(); + this.Type = (PsoDataType)reader.ReadByte(); + this.Unk_5h = reader.ReadByte(); + this.DataOffset = reader.ReadUInt16(); + this.ReferenceKey = reader.ReadUInt32(); + } + + public void Write(DataWriter writer) + { + writer.Write((uint)EntryNameHash); + writer.Write((byte)Type); + writer.Write(Unk_5h); + writer.Write(DataOffset); + writer.Write(ReferenceKey); + } + + public override string ToString() + { + if(ReferenceKey!=0) + { + return EntryNameHash.ToString() + ": " + Type.ToString() + ": " + DataOffset.ToString() + ": " + ((MetaName)ReferenceKey).ToString(); + } + return EntryNameHash.ToString() + ": " + Type.ToString() + ": " + DataOffset.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoEnumInfo : PsoElementInfo + { + public byte Type { get; private set; } = 1; + public int EntriesCount { get; private set; } + public PsoEnumEntryInfo[] Entries { get; set; } + + public override void Read(DataReader reader) + { + uint x = reader.ReadUInt32(); + this.Type = (byte)((x & 0xFF000000) >> 24); + this.EntriesCount = (int)(x & 0x00FFFFFF); + + Entries = new PsoEnumEntryInfo[EntriesCount]; + for (int i = 0; i < EntriesCount; i++) + { + var entry = new PsoEnumEntryInfo(); + entry.Read(reader); + Entries[i] = entry; + } + } + + public override void Write(DataWriter writer) + { + // update... + Type = 1; + EntriesCount = Entries.Length; + + uint typeAndEntriesCount = (uint)(Type << 24) | (uint)EntriesCount; + writer.Write(typeAndEntriesCount); + + foreach (var entry in Entries) + { + entry.Write(writer); + } + } + + public PsoEnumEntryInfo FindEntry(int val) + { + if (Entries == null) return null; + for (int i = 0; i < Entries.Length; i++) + { + var entry = Entries[i]; + if (entry.EntryKey == val) + { + return entry; + } + } + return null; + } + + + public override string ToString() + { + return IndexInfo.ToString() + " - " + Type.ToString() + ": " + EntriesCount.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoEnumEntryInfo + { + public MetaName EntryNameHash { get; set; } + public int EntryKey { get; set; } + + public void Read(DataReader reader) + { + this.EntryNameHash = (MetaName)reader.ReadUInt32(); + this.EntryKey = reader.ReadInt32(); + } + + public void Write(DataWriter writer) + { + writer.Write((uint)EntryNameHash); + writer.Write(EntryKey); + } + + public override string ToString() + { + return EntryNameHash.ToString() + ": " + EntryKey.ToString(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoSTRFSection + { + public int Ident { get; private set; } = 0x53545246; + public int Length { get; set; } + public string[] Strings { get; set; } + + public void Read(DataReader reader) + { + Ident = reader.ReadInt32(); + Length = reader.ReadInt32(); + List strs = new List(); + while (reader.Position < reader.Length) + { + strs.Add(reader.ReadString()); + } + foreach (var str in strs) + { + JenkIndex.Ensure(str); + JenkIndex.Ensure(str.ToLowerInvariant()); + } + Strings = strs.ToArray(); + } + + public void Write(DataWriter writer) + { + + writer.Write(Ident); + writer.Write(Length); + + + } + + public override string ToString() + { + return Ident.ToString() + ": " + Length.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoSTRSSection + { + public int Ident { get; private set; } = 0x53545253; + public int Length { get; set; } + public string[] Strings { get; set; } + + + public void Read(DataReader reader) + { + Ident = reader.ReadInt32(); + Length = reader.ReadInt32(); + + List strs = new List(); + while (reader.Position < reader.Length) + { + strs.Add(reader.ReadString()); + } + foreach (var str in strs) + { + JenkIndex.Ensure(str); + JenkIndex.Ensure(str.ToLowerInvariant()); + } + Strings = strs.ToArray(); + } + + public void Write(DataWriter writer) + { + + writer.Write(Ident); + writer.Write(Length); + + + } + + public override string ToString() + { + return Ident.ToString() + ": " + Length.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoSTRESection + { + public int Ident { get; private set; } = 0x53545245; + public int Length { get; set; } + public byte[] Data { get; set; } + + //public MetaHash[] Hashes { get; set; } + //public byte[] Decr1 { get; set; } + //public byte[] Decr2 { get; set; } + + public void Read(DataReader reader) + { + Ident = reader.ReadInt32(); + Length = reader.ReadInt32(); + + if (Length > 8) + { + Data = reader.ReadBytes(Length - 8); + + //reader.Position = 8; + //List hashes = new List(); + //while (reader.Position < reader.Length) + //{ + // hashes.Add(reader.ReadUInt32()); + //} + //Hashes = hashes.ToArray(); + + //Decr1 = GTACrypto.DecryptAES(Data); + //Decr2 = GTACrypto.DecryptNG(Data, ) + + } + } + + public void Write(DataWriter writer) + { + + writer.Write(Ident); + writer.Write(Length); + + + } + + public override string ToString() + { + return Ident.ToString() + ": " + Length.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoPSIGSection + { + public int Ident { get; private set; } = 0x50534947; + public int Length { get; set; } + public byte[] Data { get; set; } + + public void Read(DataReader reader) + { + Ident = reader.ReadInt32(); + Length = reader.ReadInt32(); + + if (Length > 8) + { + Data = reader.ReadBytes(Length - 8); + } + } + + public void Write(DataWriter writer) + { + + writer.Write(Ident); + writer.Write(Length); + + + } + + public override string ToString() + { + return Ident.ToString() + ": " + Length.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class PsoCHKSSection + { + public int Ident { get; private set; } = 0x43484B53; + public int Length { get; set; } + public uint FileSize { get; set; } + public uint Checksum { get; set; } + public uint Unk0 { get; set; } = 0x79707070; // "yppp" + + public void Read(DataReader reader) + { + Ident = reader.ReadInt32(); + Length = reader.ReadInt32(); + + if (Length != 20) + { return; } + + FileSize = reader.ReadUInt32(); + Checksum = reader.ReadUInt32(); + Unk0 = reader.ReadUInt32(); + } + + public void Write(DataWriter writer) + { + + writer.Write(Ident); + writer.Write(Length); + + + } + + public override string ToString() + { + return Ident.ToString() + ": " + Length.ToString(); + } + } + + + +} diff --git a/GameFiles/MetaTypes/PsoTypes.cs b/GameFiles/MetaTypes/PsoTypes.cs new file mode 100644 index 0000000..0ee79b7 --- /dev/null +++ b/GameFiles/MetaTypes/PsoTypes.cs @@ -0,0 +1,856 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +using TC = System.ComponentModel.TypeConverterAttribute; +using EXP = System.ComponentModel.ExpandableObjectConverter; + + +namespace CodeWalker.GameFiles +{ + public static class PsoTypes + { + //for parsing schema info in PSO files to generate structs for PSO parsing. + //equivalent of MetaTypes but for PSO. + + public static Dictionary EnumDict = new Dictionary(); + public static Dictionary StructDict = new Dictionary(); + + + + public static void Clear() + { + StructDict.Clear(); + } + + public static void EnsurePsoTypes(PsoFile pso) + { + + if ((pso.SchemaSection == null) || (pso.SchemaSection.Entries == null) || (pso.SchemaSection.EntriesIdx == null)) + { + return; + } + + + for (int i = 0; i < pso.SchemaSection.Entries.Length; i++) + { + var entry = pso.SchemaSection.Entries[i]; + var enuminfo = entry as PsoEnumInfo; + var structinfo = entry as PsoStructureInfo; + + if (enuminfo != null) + { + if (!EnumDict.ContainsKey(enuminfo.IndexInfo.NameHash)) + { + EnumDict.Add(enuminfo.IndexInfo.NameHash, enuminfo); + } + else + { + PsoEnumInfo oldei = EnumDict[enuminfo.IndexInfo.NameHash]; + if (!ComparePsoEnumInfos(oldei, enuminfo)) + { + } + } + } + else if (structinfo != null) + { + if (!StructDict.ContainsKey(structinfo.IndexInfo.NameHash)) + { + StructDict.Add(structinfo.IndexInfo.NameHash, structinfo); + } + else + { + PsoStructureInfo oldsi = StructDict[structinfo.IndexInfo.NameHash]; + if (!ComparePsoStructureInfos(oldsi, structinfo)) + { + } + } + } + + } + + } + + public static bool ComparePsoEnumInfos(PsoEnumInfo a, PsoEnumInfo b) + { + //returns true if they are the same. + + if (a.Entries.Length != b.Entries.Length) + { + return false; + } + + for (int i = 0; i < a.Entries.Length; i++) + { + if ((a.Entries[i].EntryNameHash != b.Entries[i].EntryNameHash) || + (a.Entries[i].EntryKey != b.Entries[i].EntryKey)) + { + return false; + } + } + + return true; + } + public static bool ComparePsoStructureInfos(PsoStructureInfo a, PsoStructureInfo b) + { + //returns true if they are the same. + + if (a.Entries.Length != b.Entries.Length) + { + return false; + } + + for (int i = 0; i < a.Entries.Length; i++) + { + if ((a.Entries[i].EntryNameHash != b.Entries[i].EntryNameHash) || + (a.Entries[i].DataOffset != b.Entries[i].DataOffset) || + (a.Entries[i].Type != b.Entries[i].Type)) + { + return false; + } + } + + return true; + } + + + public static string GetTypesString() + { + StringBuilder sbe = new StringBuilder(); + StringBuilder sbs = new StringBuilder(); + + sbe.AppendLine("//Enum infos"); + sbs.AppendLine("//Struct infos"); + + + foreach (var kvp in EnumDict) + { + var ei = kvp.Value; + string name = GetSafeName(ei.IndexInfo.NameHash, ei.Type); + sbe.AppendLine("public enum " + name + " //Type:" + ei.Type.ToString()); + sbe.AppendLine("{"); + foreach (var entry in ei.Entries) + { + string eename = GetSafeName(entry.EntryNameHash, (uint)entry.EntryKey); + sbe.AppendFormat(" {0} = {1},", eename, entry.EntryKey); + sbe.AppendLine(); + } + sbe.AppendLine("}"); + sbe.AppendLine(); + } + + foreach (var kvp in StructDict) + { + var si = kvp.Value; + string name = GetSafeName(si.IndexInfo.NameHash, si.Type); + sbs.AppendLine("public struct " + name + " //" + si.StructureLength.ToString() + " bytes, Type:" + si.Type.ToString()); + sbs.AppendLine("{"); + for (int i = 0; i < si.Entries.Length; i++) + { + var entry = si.Entries[i]; + + if ((entry.DataOffset == 0) && (entry.EntryNameHash == MetaName.ARRAYINFO)) //referred to by array + { + } + else + { + string sename = GetSafeName(entry.EntryNameHash, entry.ReferenceKey); + string fmt = " public {0} {1}; //{2} {3}"; + + if (entry.Type == PsoDataType.Array) + { + if (entry.ReferenceKey >= si.Entries.Length) + { + sbs.AppendFormat(fmt, entry.Type.ToString(), sename, entry.DataOffset, entry.ToString() + " { unexpected key! " + entry.ReferenceKey.ToString() + "}"); + sbs.AppendLine(); + } + else + { + var structentry = si.Entries[(int)entry.ReferenceKey]; + var typename = "Array_" + PsoDataTypes.GetCSharpTypeName(structentry.Type); + sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry.ToString() + " {" + structentry.ToString() + "}"); + sbs.AppendLine(); + } + } + else if (entry.Type == PsoDataType.Structure) + { + var typename = GetSafeName((MetaName)entry.ReferenceKey, entry.ReferenceKey); + sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry.ToString()); + sbs.AppendLine(); + } + else + { + var typename = PsoDataTypes.GetCSharpTypeName(entry.Type); + sbs.AppendFormat(fmt, typename, sename, entry.DataOffset, entry); + sbs.AppendLine(); + } + } + } + sbs.AppendLine("}"); + sbs.AppendLine(); + } + + + sbe.AppendLine(); + sbe.AppendLine(); + sbe.AppendLine(); + sbe.AppendLine(); + sbe.AppendLine(); + sbe.Append(sbs.ToString()); + + string result = sbe.ToString(); + + return result; + } + + + private static string GetSafeName(MetaName namehash, uint key) + { + string name = namehash.ToString(); + if (string.IsNullOrEmpty(name)) + { + name = "Unk_" + key; + } + if (!char.IsLetter(name[0])) + { + name = "Unk_" + name; + } + return name; + } + + + + public static T ConvertDataRaw(byte[] data) where T : struct + { + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var h = handle.AddrOfPinnedObject(); + var r = Marshal.PtrToStructure(h); + handle.Free(); + return r; + } + public static T ConvertDataRaw(byte[] data, int offset) where T : struct + { + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var h = handle.AddrOfPinnedObject(); + var r = Marshal.PtrToStructure(h + offset); + handle.Free(); + return r; + } + public static T ConvertData(byte[] data, int offset) where T : struct, IPsoSwapEnd + { + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var h = handle.AddrOfPinnedObject(); + var r = Marshal.PtrToStructure(h + offset); + handle.Free(); + r.SwapEnd(); + return r; + } + public static T[] ConvertDataArrayRaw(byte[] data, int offset, int count) where T : struct + { + T[] items = new T[count]; + int itemsize = Marshal.SizeOf(typeof(T)); + for (int i = 0; i < count; i++) + { + int off = offset + i * itemsize; + items[i] = ConvertDataRaw(data, off); + } + return items; + } + + + public static T GetItem(PsoFile pso, int offset) where T : struct, IPsoSwapEnd + { + return ConvertData(pso.DataSection.Data, offset); + } + public static T GetRootItem(PsoFile pso) where T : struct, IPsoSwapEnd + { + var i = pso.DataMapSection.RootId - 1; + var e = pso.DataMapSection.Entries[i]; + return GetItem(pso, e.Offset); + } + public static PsoDataMappingEntry GetRootEntry(PsoFile pso) + { + var i = pso.DataMapSection.RootId - 1; + var e = pso.DataMapSection.Entries[i]; + return e; + } + + public static T[] GetItemArrayRaw(PsoFile pso, Array_Structure arr) where T : struct + { + if ((arr.Count1 > 0) && (arr.Pointer > 0)) + { + var entry = pso.DataMapSection.Entries[(int)arr.PointerDataIndex]; + return ConvertDataArrayRaw(pso.DataSection.Data, entry.Offset, arr.Count1); + } + return null; + } + public static T[] GetItemArray(PsoFile pso, Array_Structure arr) where T : struct, IPsoSwapEnd + { + if ((arr.Count1 > 0) && (arr.Pointer > 0)) + { + var entry = pso.DataMapSection.Entries[(int)arr.PointerDataIndex]; + var res = ConvertDataArrayRaw(pso.DataSection.Data, entry.Offset, arr.Count1); + if (res != null) + { + for (int i = 0; i < res.Length; i++) + { + res[i].SwapEnd(); + } + } + return res; + } + return null; + } + + + public static uint[] GetUintArrayRaw(PsoFile pso, Array_uint arr) + { + byte[] data = pso.DataSection.Data; + var entryid = arr.Pointer & 0xFFF; + if ((entryid == 0) || (entryid > pso.DataMapSection.EntriesCount)) + { + return null; + } + var entryoffset = (arr.Pointer & 0xFFFFFF) >> 12; + var arrentry = pso.DataMapSection.Entries[(int)entryid - 1]; + int totoffset = arrentry.Offset + (int)entryoffset; + uint[] readdata = ConvertDataArrayRaw(data, totoffset, arr.Count1); + return readdata; + } + public static uint[] GetUintArray(PsoFile pso, Array_uint arr) + { + uint[] uints = GetUintArrayRaw(pso, arr); + if (uints == null) return null; + for (int i = 0; i < uints.Length; i++) + { + uints[i] = MetaTypes.SwapBytes(uints[i]); + } + return uints; + } + + public static MetaHash[] GetHashArray(PsoFile pso, Array_uint arr) + { + uint[] uints = GetUintArrayRaw(pso, arr); + if (uints == null) return null; + MetaHash[] hashes = new MetaHash[uints.Length]; + for (int n = 0; n < uints.Length; n++) + { + hashes[n].Hash = MetaTypes.SwapBytes(uints[n]); + } + return hashes; + } + + + + + public static float[] GetFloatArrayRaw(PsoFile pso, Array_float arr) + { + byte[] data = pso.DataSection.Data; + var entryid = arr.Pointer & 0xFFF; + if ((entryid == 0) || (entryid > pso.DataMapSection.EntriesCount)) + { + return null; + } + var entryoffset = (arr.Pointer & 0xFFFFFF) >> 12; + var arrentry = pso.DataMapSection.Entries[(int)entryid - 1]; + int totoffset = arrentry.Offset + (int)entryoffset; + float[] readdata = ConvertDataArrayRaw(data, totoffset, arr.Count1); + return readdata; + } + public static float[] GetFloatArray(PsoFile pso, Array_float arr) + { + float[] floats = GetFloatArrayRaw(pso, arr); + if (floats == null) return null; + for (int i = 0; i < floats.Length; i++) + { + floats[i] = MetaTypes.SwapBytes(floats[i]); + } + return floats; + } + + + + + + public static ushort[] GetUShortArrayRaw(PsoFile pso, Array_Structure arr) + { + byte[] data = pso.DataSection.Data; + var entryid = arr.Pointer & 0xFFF; + if ((entryid == 0) || (entryid > pso.DataMapSection.EntriesCount)) + { + return null; + } + var entryoffset = (arr.Pointer & 0xFFFFFF) >> 12; + var arrentry = pso.DataMapSection.Entries[(int)entryid - 1]; + int totoffset = arrentry.Offset + (int)entryoffset; + ushort[] readdata = ConvertDataArrayRaw(data, totoffset, arr.Count1); + return readdata; + } + public static ushort[] GetUShortArray(PsoFile pso, Array_Structure arr) + { + ushort[] ushorts = GetUShortArrayRaw(pso, arr); + if (ushorts == null) return null; + for (int i = 0; i < ushorts.Length; i++) + { + ushorts[i] = MetaTypes.SwapBytes(ushorts[i]); + } + return ushorts; + } + + + + + + + public static T[] GetObjectArray(PsoFile pso, Array_Structure arr) where U : struct, IPsoSwapEnd where T : PsoClass, new() + { + U[] items = GetItemArray(pso, arr); + if (items == null) return null; + if (items.Length == 0) return null; + T[] result = new T[items.Length]; + for (int i = 0; i < items.Length; i++) + { + T newitem = new T(); + newitem.Init(pso, ref items[i]); + result[i] = newitem; + } + return result; + } + + + public static byte[] GetByteArray(PsoFile pso, PsoStructureEntryInfo entry, int offset) + { + var aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF; + var aBlockId = (int)entry.ReferenceKey & 0x0000FFFF; + var block = pso.GetBlock(aBlockId); + if (block == null) return null; + + //block.Offset + + return null; + } + + + + + + + public static PsoPOINTER[] GetPointerArray(PsoFile pso, Array_StructurePointer array) + { + uint count = array.Count1; + if (count == 0) return null; + + int ptrsize = Marshal.SizeOf(typeof(MetaPOINTER)); + int itemsleft = (int)count; //large arrays get split into chunks... + uint ptr = array.Pointer; + int ptrindex = (int)(ptr & 0xFFF) - 1; + int ptroffset = (int)((ptr >> 12) & 0xFFFFF); + var ptrblock = (ptrindex < pso.DataMapSection.EntriesCount) ? pso.DataMapSection.Entries[ptrindex] : null; + if ((ptrblock == null) || (ptrblock.NameHash != MetaName.PsoPOINTER)) + { return null; } + + var offset = ptrblock.Offset; + int boffset = offset + ptroffset; + + var ptrs = ConvertDataArrayRaw(pso.DataSection.Data, boffset, (int)count); + if (ptrs != null) + { + for (int i = 0; i < ptrs.Length; i++) + { + ptrs[i].SwapEnd(); + } + } + + return ptrs; + } + + + public static T[] ConvertDataArray(PsoFile pso, Array_StructurePointer array) where T : struct, IPsoSwapEnd + { + uint count = array.Count1; + if (count == 0) return null; + PsoPOINTER[] ptrs = GetPointerArray(pso, array); + if (ptrs == null) return null; + if (ptrs.Length < count) + { return null; } + + T[] items = new T[count]; + int itemsize = Marshal.SizeOf(typeof(T)); + + for (int i = 0; i < count; i++) + { + var sptr = ptrs[i]; + int blocki = sptr.BlockID - 1; + int offset = (int)sptr.ItemOffset;// * 16;//block data size... + if (blocki >= pso.DataMapSection.EntriesCount) + { continue; } + var block = pso.DataMapSection.Entries[blocki]; + + if ((offset < 0) || (offset >= block.Length)) + { continue; } + + int boffset = block.Offset + offset; + + items[i] = ConvertData(pso.DataSection.Data, boffset); + } + + return items; + } + + + + public static string GetString(PsoFile pso, CharPointer ptr) + { + if (ptr.Count1 == 0) return null; + + var blocki = (int)ptr.PointerDataId;// (ptr.Pointer & 0xFFF) - 1; + var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF; + + var block = pso.GetBlock(blocki); + if (block == null) + { return null; } + + var length = ptr.Count1; + var lastbyte = offset + length; + if (lastbyte >= block.Length) + { return null; } + + var data = pso.DataSection?.Data; + if (data == null) + { return null; } + + var doffset = block.Offset + offset; + + string s = Encoding.ASCII.GetString(data, doffset, length); + + //if (meta.Strings == null) return null; + //if (offset < 0) return null; + //if (offset >= meta.Strings.Length) return null; + //string s = meta.Strings[offset]; + + return s; + } + public static string GetString(PsoFile pso, DataBlockPointer ptr) + { + var blocki = (int)ptr.PointerDataId;// (ptr.Pointer & 0xFFF) - 1; + var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF; + + var block = pso.GetBlock(blocki); + if (block == null) + { return null; } + + //var length = ptr.Count1; + //var lastbyte = offset + length; + //if (lastbyte >= block.Length) + //{ return null; } + + var data = pso.DataSection?.Data; + if (data == null) + { return null; } + + //var doffset = block.Offset + offset; + + //string s = Encoding.ASCII.GetString(data, doffset, length); + + StringBuilder sb = new StringBuilder(); + var o = block.Offset + offset; + char c = (char)data[o]; + while (c != 0) + { + sb.Append(c); + o++; + c = (char)data[o]; + } + var s = sb.ToString(); + + return s; + } + + + } + + + public interface IPsoSwapEnd + { + void SwapEnd(); + } + + public abstract class PsoClass where T : struct, IPsoSwapEnd + { + public abstract void Init(PsoFile pso, ref T v); + } + + + public struct PsoChar64 + { + public byte b00, b01, b02, b03, b04, b05, b06, b07, b08, b09, + b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, + b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, + b30, b31, b32, b33, b34, b35, b36, b37, b38, b39, + b40, b41, b42, b43, b44, b45, b46, b47, b48, b49, + b50, b51, b52, b53, b54, b55, b56, b57, b58, b59, + b60, b61, b62, b63; + + public override string ToString() + { + byte[] bytes = new byte[] + { + b00, b01, b02, b03, b04, b05, b06, b07, b08, b09, + b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, + b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, + b30, b31, b32, b33, b34, b35, b36, b37, b38, b39, + b40, b41, b42, b43, b44, b45, b46, b47, b48, b49, + b50, b51, b52, b53, b54, b55, b56, b57, b58, b59, + b60, b61, b62, b63 + }; + return Encoding.ASCII.GetString(bytes).Replace("\0", string.Empty); + } + } + + + + + [TC(typeof(EXP))] public struct PsoPOINTER : IPsoSwapEnd //8 bytes - pointer to data item + { + public uint Pointer { get; set; } + public uint Unk2 { get; set; } + + public ushort BlockID { get { return (ushort)(Pointer & 0xFFF); } } //1-based ID + public uint ItemOffset { get { return (ushort)((Pointer>>12) & 0xFFFFF); } } //byte offset + + + public override string ToString() + { + return BlockID.ToString() + ", " + ItemOffset.ToString() + ", " + Unk2.ToString(); + } + + public void SwapEnd() + { + Pointer = MetaTypes.SwapBytes(Pointer); + Unk2 = MetaTypes.SwapBytes(Unk2); + } + } + + + + + + + + + + //Struct infos + [TC(typeof(EXP))] public struct CPackFileMetaData : IPsoSwapEnd //96 bytes, Type:0 + { + public Array_Structure MapDataGroups; //0 MapDataGroups: Array: 0 {256: Structure: 0: 3260758307} + public Array_Structure HDTxdBindingArray; //16 HDTxdBindingArray: Array: 16: 2 {256: Structure: 0: CHDTxdAssetBinding} + public Array_Structure imapDependencies; //32 imapDependencies: Array: 32: 4 {256: Structure: 0: 3501026914} + public Array_Structure imapDependencies_2; //48 imapDependencies_2: Array: 48: 6 {256: Structure: 0: 3240050401} + public Array_Structure itypDependencies_2; //64 itypDependencies_2: Array: 64: 8 {256: Structure: 0: 1515605584} + public Array_Structure Interiors; //80 Interiors: Array: 80: 10 {256: Structure: 0: 741495440} + + public void SwapEnd() + { + MapDataGroups.SwapEnd(); + HDTxdBindingArray.SwapEnd(); + imapDependencies.SwapEnd(); + imapDependencies_2.SwapEnd(); + itypDependencies_2.SwapEnd(); + Interiors.SwapEnd(); + } + } + + [TC(typeof(EXP))] public struct CMapDataGroup : IPsoSwapEnd //56 bytes, Type:0 + { + public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0 + public uint Unused0 { get; set; } //4 + public Array_uint Bounds { get; set; } //8 Bounds//3298223272: Array: 8: 1 {256: INT_0Bh: 0} + public ushort Flags { get; set; } //24 Flags: SHORT_0Fh: 24: 2097155 + public ushort Unused1 { get; set; }//26 + public uint Unused2 { get; set; }//28 + public Array_uint WeatherTypes { get; set; } //32 WeatherTypes: Array: 32: 5 {256: INT_0Bh: 0} + public uint HoursOnOff { get; set; } //48 HoursOnOff//4190815249: INT_06h: 48 + public uint Unused3 { get; set; }//52 + + public override string ToString() + { + return Name.ToString() + ": ybn:" + Bounds.Count1.ToString() + ", wt:" + WeatherTypes.Count1.ToString() + ", flags:" + Flags.ToString() + ", hours:" + HoursOnOff.ToString(); + } + + public void SwapEnd() + { + Name = new MetaHash(MetaTypes.SwapBytes(Name.Hash)); + var b = Bounds; b.SwapEnd(); Bounds = b; + var w = WeatherTypes; w.SwapEnd(); WeatherTypes = w; + HoursOnOff = MetaTypes.SwapBytes(HoursOnOff); + Flags = MetaTypes.SwapBytes(Flags); + } + } + + [TC(typeof(EXP))] public struct CHDTxdAssetBinding : IPsoSwapEnd //132 bytes, Type:0 + { + public byte assetType { get; set; } //0 assetType: BYTE_ENUM_VALUE: 0: 3387532954 + public byte Unused01 { get; set; }//1 + public ushort Unused02 { get; set; }//2 + public PsoChar64 targetAsset { get; set; } //4 targetAsset: INT_0Bh: 4: 4194304 + public PsoChar64 HDTxd { get; set; } //68 HDTxd: INT_0Bh: 68: 4194304 + + public override string ToString() + { + return assetType.ToString() + ": " + targetAsset.ToString() + ": " + HDTxd.ToString(); + } + public void SwapEnd() + { + //targetAsset.Hash = MetaTypes.SwapBytes(targetAsset.Hash); + //HDTxd.Hash = MetaTypes.SwapBytes(HDTxd.Hash); + } + } + + [TC(typeof(EXP))] public struct CImapDependency : IPsoSwapEnd //12 bytes, Type:0 // CImapDependency//3501026914 + { + public MetaHash imapName { get; set; } //0 imapName: INT_0Bh: 0 + public MetaHash itypName { get; set; } //4 itypName//2890158180: INT_0Bh: 4 + public MetaHash packFileName { get; set; } //8 packFileName//4216494073: INT_0Bh: 8 + + public override string ToString() + { + return imapName.ToString() + ", " + itypName.ToString() + ", " + packFileName.ToString(); + } + public void SwapEnd() + { + imapName = new MetaHash(MetaTypes.SwapBytes(imapName.Hash)); + itypName = new MetaHash(MetaTypes.SwapBytes(itypName.Hash)); + packFileName = new MetaHash(MetaTypes.SwapBytes(packFileName.Hash)); + } + } + + [TC(typeof(EXP))] public struct CImapDependencies : IPsoSwapEnd //24 bytes, Type:0 // CImapDependencies//3240050401 imapDependencies_2 + { + public MetaHash imapName { get; set; } //0 imapName: INT_0Bh: 0 //name hash + public ushort manifestFlags { get; set; } //4 manifestFlags//1683136603: SHORT_0Fh: 4: 2097153 + public ushort Unused0 { get; set; } //6 + public Array_uint itypDepArray { get; set; } //8 itypDepArray//2410949350: Array: 8: 3 {256: INT_0Bh: 0} //children... + + + public override string ToString() + { + return imapName.ToString() + ": " + manifestFlags.ToString() + ": " + itypDepArray.ToString(); + } + public void SwapEnd() + { + imapName = new MetaHash(MetaTypes.SwapBytes(imapName.Hash)); + manifestFlags = MetaTypes.SwapBytes(manifestFlags); + var d = itypDepArray; d.SwapEnd(); itypDepArray = d; + } + } + + [TC(typeof(EXP))] public struct CItypDependencies : IPsoSwapEnd //24 bytes, Type:0 // CItypDependencies//1515605584 itypDependencies_2 + { + public MetaHash itypName { get; set; } //0 itypName//2890158180: INT_0Bh: 0 + public ushort manifestFlags { get; set; } //4 manifestFlags//1683136603: SHORT_0Fh: 4: 2097153 + public ushort Unused0 { get; set; } //6 + public Array_uint itypDepArray { get; set; } //8 itypDepArray//2410949350: Array: 8: 3 {256: INT_0Bh: 0} + + public override string ToString() + { + return itypName.ToString() + ": " + manifestFlags.ToString() + ": " + itypDepArray.ToString(); + } + public void SwapEnd() + { + itypName = new MetaHash(MetaTypes.SwapBytes(itypName.Hash)); + manifestFlags = MetaTypes.SwapBytes(manifestFlags); + var d = itypDepArray; d.SwapEnd(); itypDepArray = d; + } + } + + [TC(typeof(EXP))] public struct Unk_741495440 : IPsoSwapEnd //24 bytes, Type:0 // Interiors + { + public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0 + public uint Unused0 { get; set; } //4 + public Array_uint Bounds { get; set; } //8 Bounds//3298223272: Array: 8: 1 {256: INT_0Bh: 0} + + public override string ToString() + { + return JenkIndex.GetString(Name); + } + public void SwapEnd() + { + Name = new MetaHash(MetaTypes.SwapBytes(Name.Hash)); + var b = Bounds; b.SwapEnd(); Bounds = b; + } + } + + + + + + + [TC(typeof(EXP))] public struct CScenarioPointManifest : IPsoSwapEnd //56 bytes, Type:0 + { + public int VersionNumber { get; set; } //0 VersionNumber: INT_05h: 0 + public uint Unused0 { get; set; } //4 + public Array_StructurePointer RegionDefs { get; set; } //8 RegionDefs: Array: 8: 1 {ARRAYINFO: Structure: 0} + public Array_StructurePointer Groups { get; set; } //24 Groups: Array: 24: 3 {ARRAYINFO: Structure: 0} + public Array_uint InteriorNames { get; set; } //40 InteriorNames: Array: 40: 5 {ARRAYINFO: INT_0Bh: 0} + + public override string ToString() + { + return VersionNumber.ToString(); + } + public void SwapEnd() + { + VersionNumber = MetaTypes.SwapBytes(VersionNumber); + var r = RegionDefs; r.SwapEnd(); RegionDefs = r; + var g = Groups; g.SwapEnd(); Groups = g; + var i = InteriorNames; i.SwapEnd(); InteriorNames = i; + } + } + + [TC(typeof(EXP))] public struct CScenarioPointRegionDef : IPsoSwapEnd //64 bytes, Type:0 + { + public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0 + public uint Unused0 { get; set; } //4 + public uint Unused1 { get; set; } //8 + public uint Unused2 { get; set; } //12 + public rage__spdAABB AABB { get; set; } //16 AABB: Structure: 16: rage__spdAABB + public uint Unused3 { get; set; } //48 + public uint Unused4 { get; set; } //52 + public uint Unused5 { get; set; } //56 + public uint Unused6 { get; set; } //60 + + public override string ToString() + { + return Name.ToString() + ", " + AABB.ToString(); + } + public void SwapEnd() + { + Name = new MetaHash(MetaTypes.SwapBytes(Name.Hash)); + var aabb = AABB; aabb.SwapEnd(); AABB = aabb; + } + } + + [TC(typeof(EXP))] public struct CScenarioPointGroup : IPsoSwapEnd //8 bytes, Type:0 + { + public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0 + public byte EnabledByDefault { get; set; } //4 EnabledByDefault: BYTE_00h: 4 + public byte Unused0 { get; set; } //5 + public ushort Unused1 { get; set; } //6 + + public override string ToString() + { + return Name.ToString(); + } + public void SwapEnd() + { + Name = new MetaHash(MetaTypes.SwapBytes(Name.Hash)); + } + } + + + + +} diff --git a/GameFiles/MetaTypes/Rbf.cs b/GameFiles/MetaTypes/Rbf.cs new file mode 100644 index 0000000..fab40dc --- /dev/null +++ b/GameFiles/MetaTypes/Rbf.cs @@ -0,0 +1,295 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen and mangled + + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfFile + { + private const int RBF_IDENT = 0x30464252; + + public RbfStructure current { get; set; } + public Stack stack { get; set; } + public List descriptors { get; set; } + + public RbfStructure Load(string fileName) + { + using (var fileStream = new FileStream(fileName, FileMode.Open)) + { + return Load(fileStream); + } + } + + public RbfStructure Load(Stream stream) + { + stack = new Stack(); + descriptors = new List(); + + var reader = new DataReader(stream); + var ident = reader.ReadInt32(); + if (ident != RBF_IDENT) + throw new Exception("The file identifier does not match."); + + while (reader.Position < reader.Length) + { + var descriptorIndex = reader.ReadByte(); + if (descriptorIndex == 0xFF) // close tag + { + var b = reader.ReadByte(); + if (b != 0xFF) + throw new Exception("Expected 0xFF but was " + b.ToString("X2")); + + if (stack.Count > 0) + { + current = stack.Pop(); + } + else + { + if (reader.Position != reader.Length) + throw new Exception("Expected end of stream but was not."); + return current; + } + } + else if (descriptorIndex == 0xFD) // bytes + { + var b = reader.ReadByte(); + if (b != 0xFF) + throw new Exception("Expected 0xFF but was " + b.ToString("X2")); + + var dataLength = reader.ReadInt32(); + var data = reader.ReadBytes(dataLength); + + var bytesValue = new RbfBytes(); + bytesValue.Value = data; + current.Children.Add(bytesValue); + } + else + { + var dataType = reader.ReadByte(); + if (descriptorIndex == descriptors.Count) // new descriptor + data + { + var nameLength = reader.ReadInt16(); + var nameBytes = reader.ReadBytes(nameLength); + var name = Encoding.ASCII.GetString(nameBytes); + + var descriptor = new RbfEntryDescription(); + descriptor.Name = name; + descriptor.Type = dataType; + descriptors.Add(descriptor); + + ParseElement(reader, descriptors.Count - 1, dataType); + } + else // existing descriptor + data + { + if (dataType != descriptors[descriptorIndex].Type) + { + //throw new Exception("Data type does not match. Expected " + // + descriptors[descriptorIndex].Type.ToString() + " but found " + // + dataType.ToString() + ". Descriptor: " + descriptors[descriptorIndex].Name); + } + + ParseElement(reader, descriptorIndex, dataType); + } + } + } + + throw new Exception("Unexpected end of stream."); + } + + private void ParseElement(DataReader reader, int descriptorIndex, byte dataType) + { + var descriptor = descriptors[descriptorIndex]; + switch (dataType) //(descriptor.Type) + { + case 0: // open element... + { + var structureValue = new RbfStructure(); + structureValue.Name = descriptor.Name; + + if (current != null) + { + current.Children.Add(structureValue); + stack.Push(current); + } + + current = structureValue; + + // 6 bytes + var x1 = reader.ReadInt16(); + var x2 = reader.ReadInt16(); + var x3 = reader.ReadInt16(); + //if (x1 != 0) + // throw new Exception("unexpected"); + //if (x2 != 0) + // throw new Exception("unexpected"); + //if (x3 != 0) + // throw new Exception("unexpected"); + break; + } + case 0x10: + { + var intValue = new RbfUint32(); + intValue.Name = descriptor.Name; + intValue.Value = reader.ReadUInt32(); + current.Children.Add(intValue); + break; + } + case 0x20: + { + var booleanValue = new RbfBoolean(); + booleanValue.Name = descriptor.Name; + booleanValue.Value = true; + current.Children.Add(booleanValue); + break; + } + case 0x30: + { + var booleanValue = new RbfBoolean(); + booleanValue.Name = descriptor.Name; + booleanValue.Value = false; + current.Children.Add(booleanValue); + break; + } + case 0x40: + { + var floatValue = new RbfFloat(); + floatValue.Name = descriptor.Name; + floatValue.Value = reader.ReadSingle(); + current.Children.Add(floatValue); + break; + } + case 0x50: + { + var floatVectorValue = new RbfFloat3(); + floatVectorValue.Name = descriptor.Name; + floatVectorValue.X = reader.ReadSingle(); + floatVectorValue.Y = reader.ReadSingle(); + floatVectorValue.Z = reader.ReadSingle(); + current.Children.Add(floatVectorValue); + break; + } + case 0x60: + { + var valueLength = reader.ReadInt16(); + var valueBytes = reader.ReadBytes(valueLength); + var value = Encoding.ASCII.GetString(valueBytes); + var stringValue = new RbfString(); + stringValue.Name = descriptor.Name; + stringValue.Value = value; + current.Children.Add(stringValue); + break; + } + default: + throw new Exception("Unsupported data type."); + } + } + + public static bool IsRBF(Stream stream) + { + var reader = new DataReader(stream); + var origpos = stream.Position; + var ident = reader.ReadInt32(); + var isrbf = (ident == RBF_IDENT); + stream.Position = origpos; + return isrbf; + } + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfEntryDescription + { + public string Name { get; set; } + public int Type { get; set; } + public override string ToString() { return Name + ": " + Type.ToString(); } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public interface IRbfType + { + string Name { get; set; } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfBoolean : IRbfType + { + public string Name { get; set; } + public bool Value { get; set; } + public override string ToString() { return Name + ": " + Value.ToString(); } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfBytes : IRbfType + { + public string Name { get; set; } + public byte[] Value { get; set; } + public override string ToString() { return Name + ": " + Value.ToString(); } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfFloat : IRbfType + { + public string Name { get; set; } + public float Value { get; set; } + public override string ToString() { return Name + ": " + Value.ToString(); } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfFloat3 : IRbfType + { + public string Name { get; set; } + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + public override string ToString() { return string.Format("{0}: X:{1}, Y:{2}, Z:{3}", Name, X, Y, Z); } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfString : IRbfType + { + public string Name { get; set; } + public string Value { get; set; } + public override string ToString() { return Name + ": " + Value.ToString(); } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfStructure : IRbfType + { + public string Name { get; set; } + public List Children { get; set; } = new List(); + public override string ToString() { return Name + ": {" + Children.Count.ToString() + "}"; } + public IRbfType FindChild(string name) + { + foreach (var child in Children) + { + if (child == null) continue; + if (child.Name == name) return child; + } + return null; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class RbfUint32 : IRbfType + { + public string Name { get; set; } + public uint Value { get; set; } + public override string ToString() { return Name + ": " + Value.ToString(); } + } + + +} \ No newline at end of file diff --git a/GameFiles/Resources/Archetype.cs b/GameFiles/Resources/Archetype.cs new file mode 100644 index 0000000..5f82913 --- /dev/null +++ b/GameFiles/Resources/Archetype.cs @@ -0,0 +1,191 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] + public class Archetype + { + public MetaHash Hash { get; set; } + public YtypFile Ytyp { get; set; } + public CBaseArchetypeDef BaseArchetype { get; set; } + public CTimeArchetypeDef TimeArchetype { get; set; } + public CMloArchetypeDef MloArchetype { get; set; } + public MetaHash DrawableDict { get; set; } + public MetaHash TextureDict { get; set; } + public MetaHash ClipDict { get; set; } + public Vector3 BBMin { get; set; } + public Vector3 BBMax { get; set; } + public Vector3 BSCenter { get; set; } + public float BSRadius { get; set; } + public bool IsTimeArchetype { get; set; } + public bool IsMloArchetype { get; set; } + public float LodDist { get; set; } + public MloArchetypeData MloData { get; set; } + public MetaWrapper[] Extensions { get; set; } + public TimedArchetypeTimes Times { get; set; } + + + public string Name + { + get + { + if (IsTimeArchetype) return TimeArchetype.CBaseArchetypeDef.name.ToString(); + if (IsMloArchetype) return MloArchetype.CBaseArchetypeDef.name.ToString(); + return BaseArchetype.name.ToString(); + } + } + public string AssetName + { + get + { + if (IsTimeArchetype) return TimeArchetype.CBaseArchetypeDef.assetName.ToString(); + if (IsMloArchetype) return MloArchetype.CBaseArchetypeDef.assetName.ToString(); + return BaseArchetype.assetName.ToString(); + } + } + + public void Init(YtypFile ytyp, CBaseArchetypeDef arch) + { + Hash = arch.assetName; + if (Hash.Hash == 0) Hash = arch.name; + Ytyp = ytyp; + BaseArchetype = arch; + DrawableDict = arch.drawableDictionary; + TextureDict = arch.textureDictionary; + ClipDict = arch.clipDictionary; + BBMin = arch.bbMin; + BBMax = arch.bbMax; + BSCenter = arch.bsCentre; + BSRadius = arch.bsRadius; + IsTimeArchetype = false; + IsMloArchetype = false; + LodDist = arch.lodDist; + } + public void Init(YtypFile ytyp, CTimeArchetypeDef arch) + { + Hash = arch.CBaseArchetypeDef.assetName; + if (Hash.Hash == 0) Hash = arch.CBaseArchetypeDef.name; + Ytyp = ytyp; + TimeArchetype = arch; + DrawableDict = arch.CBaseArchetypeDef.drawableDictionary; + TextureDict = arch.CBaseArchetypeDef.textureDictionary; + ClipDict = arch.CBaseArchetypeDef.clipDictionary; + BBMin = arch.CBaseArchetypeDef.bbMin; + BBMax = arch.CBaseArchetypeDef.bbMax; + BSCenter = arch.CBaseArchetypeDef.bsCentre; + BSRadius = arch.CBaseArchetypeDef.bsRadius; + IsTimeArchetype = true; + IsMloArchetype = false; + LodDist = arch.CBaseArchetypeDef.lodDist; + Times = new TimedArchetypeTimes(arch.timeFlags); + } + public void Init(YtypFile ytyp, CMloArchetypeDef arch) + { + Hash = arch.CBaseArchetypeDef.assetName; + if (Hash.Hash == 0) Hash = arch.CBaseArchetypeDef.name; + Ytyp = ytyp; + MloArchetype = arch; + DrawableDict = arch.CBaseArchetypeDef.drawableDictionary; + TextureDict = arch.CBaseArchetypeDef.textureDictionary; + ClipDict = arch.CBaseArchetypeDef.clipDictionary; + BBMin = arch.CBaseArchetypeDef.bbMin; + BBMax = arch.CBaseArchetypeDef.bbMax; + BSCenter = arch.CBaseArchetypeDef.bsCentre; + BSRadius = arch.CBaseArchetypeDef.bsRadius; + IsTimeArchetype = false; + IsMloArchetype = true; + LodDist = arch.CBaseArchetypeDef.lodDist; + } + + public bool IsActive(float hour) + { + if (Times == null) return true; + //if (Times.ExtraFlag) hour -= 0.5f; + //if (hour < 0.0f) hour += 24.0f; + int h = ((int)hour) % 24; + if ((h < 0) || (h > 23)) return true; + return Times.ActiveHours[h]; + } + + public override string ToString() + { + if (IsTimeArchetype) return TimeArchetype.ToString(); + if (IsMloArchetype) return MloArchetype.ToString(); + return BaseArchetype.ToString(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class MloArchetypeData + { + public CEntityDef[] entities { get; set; } + public CMloRoomDef[] rooms { get; set; } + public CMloPortalDef[] portals { get; set; } + public CMloEntitySet[] entitySets { get; set; } + public CMloTimeCycleModifier[] timeCycleModifiers { get; set; } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class MloEntityData + { + public YmapEntityDef[] AllEntities { get; set; } + + public void CreateYmapEntities(YmapEntityDef owner, MloArchetypeData mlod) + { + if (owner == null) return; + if (mlod.entities == null) return; + AllEntities = new YmapEntityDef[mlod.entities.Length]; + for (int i = 0; i < mlod.entities.Length; i++) + { + YmapEntityDef e = new YmapEntityDef(null, i, ref mlod.entities[i]); + + e.MloParent = owner; + e.Position = owner.Position + owner.Orientation.Multiply(e.Position); + e.Orientation = Quaternion.Multiply(owner.Orientation, e.Orientation); + + e.UpdateWidgetPosition(); + e.UpdateWidgetOrientation(); + + if ((owner.Orientation != Quaternion.Identity)&&(owner.Orientation.Z!=1.0f)) + { } + + AllEntities[i] = e; + } + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class TimedArchetypeTimes + { + public uint TimeFlags { get; set; } + public bool[] ActiveHours { get; set; } + public string[] ActiveHoursText { get; set; } + public bool ExtraFlag { get; set; } + + public TimedArchetypeTimes(uint timeFlags) + { + TimeFlags = timeFlags; + ActiveHours = new bool[24]; + ActiveHoursText = new string[24]; + for (int i = 0; i < 24; i++) + { + bool v = ((timeFlags >> i) & 1) == 1; + ActiveHours[i] = v; + + int nxth = (i < 23) ? (i + 1) : 0; + string hrs = string.Format("{0:00}:00 - {1:00}:00", i, nxth); + ActiveHoursText[i] = (hrs + (v ? " - On" : " - Off")); + } + ExtraFlag = ((timeFlags >> 24) & 1) == 1; + } + + } + +} diff --git a/GameFiles/Resources/Bounds.cs b/GameFiles/Resources/Bounds.cs new file mode 100644 index 0000000..f129208 --- /dev/null +++ b/GameFiles/Resources/Bounds.cs @@ -0,0 +1,1413 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen and mangled + + +using SharpDX; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundsDictionary : ResourceFileBase + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000001 + public uint Unknown_14h { get; set; } // 0x00000001 + public uint Unknown_18h { get; set; } // 0x00000001 + public uint Unknown_1Ch { get; set; } // 0x00000001 + //public ResourceSimpleList64 BoundNameHashes; + public ResourceSimpleList64Ptr BoundNameHashesPtr { get; set; } + public uint[] BoundNameHashes { get; set; } + public ResourcePointerList64 Bounds { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + //this.BoundNameHashes = reader.ReadBlock>(); + this.BoundNameHashesPtr = reader.ReadStruct(); + this.BoundNameHashes = reader.ReadUintsAt(this.BoundNameHashesPtr.EntriesPointer, this.BoundNameHashesPtr.EntriesCount); + this.Bounds = reader.ReadBlock>(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + //writer.WriteBlock(this.BoundNameHashes); //TODO: fix! + //writer.WriteBlock(this.Bounds); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(0x20, BoundNameHashes), //TODO: fix! + new Tuple(0x30, Bounds) + }; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Bounds : ResourceFileBase, IResourceXXSystemBlock + { + public override long BlockLength + { + get { return 112; } + } + + // structure data + public byte Type { get; set; } + public byte Unknown_11h { get; set; } + public ushort Unknown_12h { get; set; } + public float BoundingSphereRadius { get; set; } + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + public SharpDX.Vector3 BoundingBoxMax { get; set; } + public float Unknown_2Ch { get; set; } + public SharpDX.Vector3 BoundingBoxMin { get; set; } + public uint Unknown_3Ch { get; set; } + public SharpDX.Vector3 BoundingBoxCenter { get; set; } + public uint Unknown_4Ch { get; set; } + public SharpDX.Vector3 Center { get; set; } + public uint Unknown_5Ch { get; set; } + public float Unknown_60h { get; set; } + public float Unknown_64h { get; set; } + public float Unknown_68h { get; set; } + public uint Unknown_6Ch { get; set; } + + + public Bounds Parent { get; set; } + public string OwnerName { get; set; } + public string GetName() + { + string n = OwnerName; + var p = Parent; + while (p != null) + { + n = p.OwnerName; + p = p.Parent; + } + return n; + } + + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Type = reader.ReadByte(); + this.Unknown_11h = reader.ReadByte(); + this.Unknown_12h = reader.ReadUInt16(); + this.BoundingSphereRadius = reader.ReadSingle(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.BoundingBoxMax = reader.ReadStruct(); + this.Unknown_2Ch = reader.ReadSingle(); + this.BoundingBoxMin = reader.ReadStruct(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.BoundingBoxCenter = reader.ReadStruct(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Center = reader.ReadStruct(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadSingle(); + this.Unknown_64h = reader.ReadSingle(); + this.Unknown_68h = reader.ReadSingle(); + this.Unknown_6Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Type); + writer.Write(this.Unknown_11h); + writer.Write(this.Unknown_12h); + writer.Write(this.BoundingSphereRadius); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + //writer.WriteBlock(this.BoundingBoxMax); //TODO: FIX!! + writer.Write(this.Unknown_2Ch); + //writer.WriteBlock(this.BoundingBoxMin); + writer.Write(this.Unknown_3Ch); + //writer.WriteBlock(this.BoundingBoxCenter); + writer.Write(this.Unknown_4Ch); + //writer.WriteBlock(this.Center); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + + public IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters) + { + reader.Position += 16; + var type = reader.ReadByte(); + reader.Position -= 17; + + switch (type) + { + case 0: return new BoundSphere(); + case 1: return new BoundCapsule(); + case 3: return new BoundBox(); + case 4: return new BoundGeometry(); + case 8: return new BoundBVH(); + case 10: return new BoundComposite(); + case 12: return new BoundDisc(); + case 13: return new BoundCylinder(); + case 15: return null; //TODO: find out what this is! + default: return null; // throw new Exception("Unknown bound type"); + } + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundSphere : Bounds + { } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundCapsule : Bounds + { + public override long BlockLength + { + get { return 128; } + } + + // structure data + public uint Unknown_70h { get; set; } // 0x00000000 + public uint Unknown_74h { get; set; } // 0x00000000 + public uint Unknown_78h { get; set; } // 0x00000000 + public uint Unknown_7Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundBox : Bounds + { } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundGeometry : Bounds + { + public override long BlockLength + { + get { return 304; } + } + + // structure data + public uint Unknown_70h { get; set; } + public uint Unknown_74h { get; set; } + public ulong Unknown_78h_Pointer { get; set; } + public uint Unknown_80h { get; set; } + public uint Count1 { get; set; } + public ulong PolygonsPointer { get; set; } + public Vector3 Quantum { get; set; } + public float Unknown_9Ch { get; set; } + public Vector3 CenterGeom { get; set; } + public float Unknown_ACh { get; set; } + public ulong VerticesPointer { get; set; } + public ulong Unknown_B8h_Pointer { get; set; } + public ulong Unknown_C0h_Pointer { get; set; } + public ulong Unknown_C8h_Pointer { get; set; } + public uint VerticesCount { get; set; } + public uint PolygonsCount { get; set; } + public uint Unknown_D8h { get; set; } // 0x00000000 + public uint Unknown_DCh { get; set; } // 0x00000000 + public uint Unknown_E0h { get; set; } // 0x00000000 + public uint Unknown_E4h { get; set; } // 0x00000000 + public uint Unknown_E8h { get; set; } // 0x00000000 + public uint Unknown_ECh { get; set; } // 0x00000000 + public ulong MaterialsPointer { get; set; } + public ulong MaterialColoursPointer { get; set; } + public uint Unknown_100h { get; set; } // 0x00000000 + public uint Unknown_104h { get; set; } // 0x00000000 + public uint Unknown_108h { get; set; } // 0x00000000 + public uint Unknown_10Ch { get; set; } // 0x00000000 + public uint Unknown_110h { get; set; } // 0x00000000 + public uint Unknown_114h { get; set; } // 0x00000000 + public ulong PolygonMaterialIndicesPointer { get; set; } + public byte MaterialsCount { get; set; } + public byte MaterialColoursCount { get; set; } + public ushort Unknown_122h { get; set; } // 0x0000 + public uint Unknown_124h { get; set; } // 0x00000000 + public uint Unknown_128h { get; set; } // 0x00000000 + public uint Unknown_12Ch { get; set; } // 0x00000000 + + + public BoundVertex_s[] p1data { get; set; } + + public BoundPolygon[] Polygons { get; set; } + + public Vector3[] Vertices { get; set; } + public uint[] Unknown_B8h_Data { get; set; } + public uint[] Unknown_C0h_Data { get; set; } + public uint[][] Unknown_C8h_Data { get; set; } + public BoundMaterial_s[] Materials { get; set; } + public BoundMaterialColour[] MaterialColours { get; set; } + public byte[] PolygonMaterialIndices { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h_Pointer = reader.ReadUInt64(); + this.Unknown_80h = reader.ReadUInt32(); + this.Count1 = reader.ReadUInt32(); + this.PolygonsPointer = reader.ReadUInt64(); + this.Quantum = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); + this.Unknown_9Ch = reader.ReadSingle();//.ReadUInt32(); + this.CenterGeom = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); + this.Unknown_ACh = reader.ReadSingle(); + this.VerticesPointer = reader.ReadUInt64(); + this.Unknown_B8h_Pointer = reader.ReadUInt64(); + this.Unknown_C0h_Pointer = reader.ReadUInt64(); + this.Unknown_C8h_Pointer = reader.ReadUInt64(); + this.VerticesCount = reader.ReadUInt32(); + this.PolygonsCount = reader.ReadUInt32(); + this.Unknown_D8h = reader.ReadUInt32(); + this.Unknown_DCh = reader.ReadUInt32(); + this.Unknown_E0h = reader.ReadUInt32(); + this.Unknown_E4h = reader.ReadUInt32(); + this.Unknown_E8h = reader.ReadUInt32(); + this.Unknown_ECh = reader.ReadUInt32(); + this.MaterialsPointer = reader.ReadUInt64(); + this.MaterialColoursPointer = reader.ReadUInt64(); + this.Unknown_100h = reader.ReadUInt32(); + this.Unknown_104h = reader.ReadUInt32(); + this.Unknown_108h = reader.ReadUInt32(); + this.Unknown_10Ch = reader.ReadUInt32(); + this.Unknown_110h = reader.ReadUInt32(); + this.Unknown_114h = reader.ReadUInt32(); + this.PolygonMaterialIndicesPointer = reader.ReadUInt64(); + this.MaterialsCount = reader.ReadByte(); + this.MaterialColoursCount = reader.ReadByte(); + this.Unknown_122h = reader.ReadUInt16(); + this.Unknown_124h = reader.ReadUInt32(); + this.Unknown_128h = reader.ReadUInt32(); + this.Unknown_12Ch = reader.ReadUInt32(); + + + this.p1data = reader.ReadStructsAt(this.Unknown_78h_Pointer, this.VerticesCount); + if (p1data != null) + { } //seems to be in YFT's + + ReadPolygons(reader); + + var verts = reader.ReadStructsAt(this.VerticesPointer, this.VerticesCount); + if (verts != null) + { + Vertices = new Vector3[verts.Length]; + for (int i = 0; i < verts.Length; i++) + { + var bv = verts[i]; + Vertices[i] = new Vector3(bv.X, bv.Y, bv.Z) * Quantum; + } + } + + this.Unknown_B8h_Data = reader.ReadUintsAt(this.Unknown_B8h_Pointer, this.VerticesCount); + this.Unknown_C0h_Data = reader.ReadUintsAt(this.Unknown_C0h_Pointer, 8); + + if (this.Unknown_C0h_Data != null) + { + ulong[] ptrlist = reader.ReadUlongsAt(this.Unknown_C8h_Pointer, (uint)Unknown_C0h_Data.Length);//8 + //reader.Position += Unknown_C0h_Data.Length * 8; //account for ptrlist read + Unknown_C8h_Data = new uint[Unknown_C0h_Data.Length][]; //8 + for (int i = 0; i < Unknown_C0h_Data.Length; i++) //8 + { + Unknown_C8h_Data[i] = reader.ReadUintsAt(ptrlist[i], Unknown_C0h_Data[i]); + } + } + + this.Materials = reader.ReadStructsAt(this.MaterialsPointer, this.MaterialsCount); + + this.MaterialColours = reader.ReadStructsAt(this.MaterialColoursPointer, this.MaterialColoursCount); + + this.PolygonMaterialIndices = reader.ReadBytesAt(this.PolygonMaterialIndicesPointer, (uint)PolygonsCount); + + } + + private void ReadPolygons(ResourceDataReader reader) + { + if(PolygonsCount==0) + { return; } + + Polygons = new BoundPolygon[PolygonsCount]; + uint polybytecount = PolygonsCount * 16; + var polygonData = reader.ReadBytesAt(PolygonsPointer, polybytecount); + for (int i = 0; i < PolygonsCount; i++) + { + var offset = i * 16; + byte b0 = polygonData[offset]; + polygonData[offset] = (byte)(b0 & 0x7F);//mask it off + BoundPolygonType type = (BoundPolygonType)(b0 & 7); + BoundPolygon p = null; + switch (type) + { + case BoundPolygonType.Triangle: + p = new BoundPolygonTriangle(); + break; + case BoundPolygonType.Sphere: + p = new BoundPolygonSphere(); + break; + case BoundPolygonType.Capsule: + p = new BoundPolygonCapsule(); + break; + case BoundPolygonType.Box: + p = new BoundPolygonBox(); + break; + case BoundPolygonType.Cylinder: + p = new BoundPolygonCylinder(); + break; + default: + break; + } + if (p != null) + { + p.Read(polygonData, offset); + } + Polygons[i] = p; + } + } + + public Vector3 GetVertex(int index) + { + return ((index < 0) || (index >= Vertices.Length)) ? Vector3.Zero : Vertices[index]; + } + + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + //this.Unknown_78h_Pointer = (ulong)(this.p1data != null ? this.p1data.Position : 0); + //this.PolygonsPointer = (ulong)(this.Polygons != null ? this.Polygons.Position : 0); + //this.VerticesPointer = (ulong)(this.Vertices != null ? this.Vertices.Position : 0); + //this.Unknown_B8h_Pointer = (ulong)(this.Unknown_B8h_Data != null ? this.Unknown_B8h_Data.Position : 0); + //this.Unknown_C0h_Pointer = (ulong)(this.Unknown_C0h_Data != null ? this.Unknown_C0h_Data.Position : 0); + //this.Unknown_C8h_Pointer = (ulong)(this.Unknown_C8h_Data != null ? this.Unknown_C8h_Data.Position : 0); + //this.VerticesCount = (uint)(this.Vertices != null ? this.Vertices.Count : 0); + //this.PolygonsCount = (uint)(this.Polygons != null ? this.Polygons.Count : 0); + //this.MaterialsPointer = (ulong)(this.Materials != null ? this.Materials.Position : 0); + //this.Unknown_F8h_Pointer = (ulong)(this.Unknown_F8h_Data != null ? this.Unknown_F8h_Data.Position : 0); + //this.PolygonMaterialIndicesPointer = (ulong)(this.PolygonMaterialIndices != null ? this.PolygonMaterialIndices.Position : 0); + //this.MaterialsCount = (byte)(this.Materials != null ? this.Materials.Count : 0); + //this.Count2 = (byte)(this.Unknown_F8h_Data != null ? this.Unknown_F8h_Data.Count : 0); + //TODO: fix all this + + // write structure data + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h_Pointer); + writer.Write(this.Unknown_80h); + writer.Write(this.Count1); + writer.Write(this.PolygonsPointer); + writer.Write(this.Quantum.X);// this.Unknown_90h); + writer.Write(this.Quantum.Y);// .Unknown_94h); + writer.Write(this.Quantum.Z);// .Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.CenterGeom.X);// .Unknown_A0h); + writer.Write(this.CenterGeom.Y);// .Unknown_A4h); + writer.Write(this.CenterGeom.Z);// .Unknown_A8h); + writer.Write(this.Unknown_ACh); + writer.Write(this.VerticesPointer); + writer.Write(this.Unknown_B8h_Pointer); + writer.Write(this.Unknown_C0h_Pointer); + writer.Write(this.Unknown_C8h_Pointer); + writer.Write(this.VerticesCount); + writer.Write(this.PolygonsCount); + writer.Write(this.Unknown_D8h); + writer.Write(this.Unknown_DCh); + writer.Write(this.Unknown_E0h); + writer.Write(this.Unknown_E4h); + writer.Write(this.Unknown_E8h); + writer.Write(this.Unknown_ECh); + writer.Write(this.MaterialsPointer); + writer.Write(this.MaterialColoursPointer); + writer.Write(this.Unknown_100h); + writer.Write(this.Unknown_104h); + writer.Write(this.Unknown_108h); + writer.Write(this.Unknown_10Ch); + writer.Write(this.Unknown_110h); + writer.Write(this.Unknown_114h); + writer.Write(this.PolygonMaterialIndicesPointer); + writer.Write(this.MaterialsCount); + writer.Write(this.MaterialColoursCount); + writer.Write(this.Unknown_122h); + writer.Write(this.Unknown_124h); + writer.Write(this.Unknown_128h); + writer.Write(this.Unknown_12Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + //if (p1data != null) list.Add(p1data); + //if (Polygons != null) list.Add(Polygons); + //if (Vertices != null) list.Add(Vertices); + //if (Unknown_B8h_Data != null) list.Add(Unknown_B8h_Data); + //if (Unknown_C0h_Data != null) list.Add(Unknown_C0h_Data); + //if (Unknown_C8h_Data != null) list.Add(Unknown_C8h_Data); + //if (Materials != null) list.Add(Materials); + //if (Unknown_F8h_Data != null) list.Add(Unknown_F8h_Data); + //if (PolygonMaterialIndices != null) list.Add(PolygonMaterialIndices); + //TODO: fix all these! + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct BoundMaterial_s + { + public BoundsMaterialType Type { get; set; } + public byte Unk0 { get; set; } + public byte Unk1 { get; set; } + public byte Unk2 { get; set; } + public uint Unk3 { get; set; } + public override string ToString() + { + return Type.ToString() + ", " + Unk0.ToString() + ", " + Unk1.ToString() + ", " + Unk2.ToString() + ", " + Unk3.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct BoundMaterialColour + { + //public BoundsMaterialType Type { get; set; } + public byte Unk0 { get; set; } + public byte Unk1 { get; set; } + public byte Unk2 { get; set; } + public byte Unk3 { get; set; } + public override string ToString() + { + //return Type.ToString() + ", " + Unk0.ToString() + ", " + Unk1.ToString() + ", " + Unk2.ToString(); + return Unk0.ToString() + ", " + Unk1.ToString() + ", " + Unk2.ToString() + ", " + Unk3.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct BoundVertex_s + { + public short X { get; set; } + public short Y { get; set; } + public short Z { get; set; } + } + public enum BoundPolygonType + { + Triangle = 0, + Sphere = 1, + Capsule = 2, + Box = 3, + Cylinder = 4, + } + [TypeConverter(typeof(ExpandableObjectConverter))] public abstract class BoundPolygon + { + public BoundPolygonType Type { get; set; } + public abstract void Read(byte[] bytes, int offset); + + public override string ToString() + { + return Type.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundPolygonTriangle : BoundPolygon + { + public float triArea { get; set; } + public ushort triIndex1 { get; set; } + public ushort triIndex2 { get; set; } + public ushort triIndex3 { get; set; } + public short edgeIndex1 { get; set; } + public short edgeIndex2 { get; set; } + public short edgeIndex3 { get; set; } + + public int vertIndex1 { get { return triIndex1 & 0x7FFF; } } + public int vertIndex2 { get { return triIndex2 & 0x7FFF; } } + public int vertIndex3 { get { return triIndex3 & 0x7FFF; } } + public bool vertFlag1 { get { return (triIndex1 & 0x8000) > 0; } } + public bool vertFlag2 { get { return (triIndex2 & 0x8000) > 0; } } + public bool vertFlag3 { get { return (triIndex3 & 0x8000) > 0; } } + + + public BoundPolygonTriangle() + { + Type = BoundPolygonType.Triangle; + } + public override void Read(byte[] bytes, int offset) + { + triArea = BitConverter.ToSingle(bytes, offset + 0); + triIndex1 = BitConverter.ToUInt16(bytes, offset + 4); + triIndex2 = BitConverter.ToUInt16(bytes, offset + 6); + triIndex3 = BitConverter.ToUInt16(bytes, offset + 8); + edgeIndex1 = BitConverter.ToInt16(bytes, offset + 10); + edgeIndex2 = BitConverter.ToInt16(bytes, offset + 12); + edgeIndex3 = BitConverter.ToInt16(bytes, offset + 14); + } + + public override string ToString() + { + return base.ToString() + ": " + vertIndex1.ToString() + ", " + vertIndex2.ToString() + ", " + vertIndex3.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundPolygonSphere : BoundPolygon + { + public ushort sphereType { get; set; } + public ushort sphereIndex { get; set; } + public float sphereRadius { get; set; } + public uint unused0 { get; set; } + public uint unused1 { get; set; } + + public BoundPolygonSphere() + { + Type = BoundPolygonType.Sphere; + } + public override void Read(byte[] bytes, int offset) + { + sphereType = BitConverter.ToUInt16(bytes, offset + 0); + sphereIndex = BitConverter.ToUInt16(bytes, offset + 2); + sphereRadius = BitConverter.ToSingle(bytes, offset + 4); + unused0 = BitConverter.ToUInt32(bytes, offset + 8); + unused1 = BitConverter.ToUInt32(bytes, offset + 12); + } + + public override string ToString() + { + return base.ToString() + ": " + sphereIndex.ToString() + ", " + sphereRadius.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundPolygonCapsule : BoundPolygon + { + public ushort capsuleType { get; set; } + public ushort capsuleIndex1 { get; set; } + public float capsuleRadius { get; set; } + public ushort capsuleIndex2 { get; set; } + public ushort unused0 { get; set; } + public uint unused1 { get; set; } + + public BoundPolygonCapsule() + { + Type = BoundPolygonType.Capsule; + } + public override void Read(byte[] bytes, int offset) + { + capsuleType = BitConverter.ToUInt16(bytes, offset + 0); + capsuleIndex1 = BitConverter.ToUInt16(bytes, offset + 2); + capsuleRadius = BitConverter.ToSingle(bytes, offset + 4); + capsuleIndex2 = BitConverter.ToUInt16(bytes, offset + 8); + unused0 = BitConverter.ToUInt16(bytes, offset + 10); + unused1 = BitConverter.ToUInt32(bytes, offset + 12); + } + + public override string ToString() + { + return base.ToString() + ": " + capsuleIndex1.ToString() + ", " + capsuleIndex2.ToString() + ", " + capsuleRadius.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundPolygonBox : BoundPolygon + { + public uint boxType { get; set; } + public short boxIndex1 { get; set; } + public short boxIndex2 { get; set; } + public short boxIndex3 { get; set; } + public short boxIndex4 { get; set; } + public uint unused0 { get; set; } + + public BoundPolygonBox() + { + Type = BoundPolygonType.Box; + } + public override void Read(byte[] bytes, int offset) + { + boxType = BitConverter.ToUInt32(bytes, offset + 0); + boxIndex1 = BitConverter.ToInt16(bytes, offset + 4); + boxIndex2 = BitConverter.ToInt16(bytes, offset + 6); + boxIndex3 = BitConverter.ToInt16(bytes, offset + 8); + boxIndex4 = BitConverter.ToInt16(bytes, offset + 10); + unused0 = BitConverter.ToUInt32(bytes, offset + 12); + } + + public override string ToString() + { + return base.ToString() + ": " + boxIndex1.ToString() + ", " + boxIndex2.ToString() + ", " + boxIndex3.ToString() + ", " + boxIndex4.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundPolygonCylinder : BoundPolygon + { + public ushort cylinderType { get; set; } + public ushort cylinderIndex1 { get; set; } + public float cylinderRadius { get; set; } + public ushort cylinderIndex2 { get; set; } + public ushort unused0 { get; set; } + public uint unused1 { get; set; } + + public BoundPolygonCylinder() + { + Type = BoundPolygonType.Cylinder; + } + public override void Read(byte[] bytes, int offset) + { + cylinderType = BitConverter.ToUInt16(bytes, offset + 0); + cylinderIndex1 = BitConverter.ToUInt16(bytes, offset + 2); + cylinderRadius = BitConverter.ToSingle(bytes, offset + 4); + cylinderIndex2 = BitConverter.ToUInt16(bytes, offset + 8); + unused0 = BitConverter.ToUInt16(bytes, offset + 10); + unused1 = BitConverter.ToUInt32(bytes, offset + 12); + } + + public override string ToString() + { + return base.ToString() + ": " + cylinderIndex1.ToString() + ", " + cylinderIndex2.ToString() + ", " + cylinderRadius.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundBVH : BoundGeometry + { + public override long BlockLength + { + get { return 336; } + } + + // structure data + public ulong BvhPointer { get; set; } + public uint Unknown_138h { get; set; } // 0x00000000 + public uint Unknown_13Ch { get; set; } // 0x00000000 + public ushort Unknown_140h { get; set; } // 0xFFFF + public ushort Unknown_142h { get; set; } // 0x0000 + public uint Unknown_144h { get; set; } // 0x00000000 + public uint Unknown_148h { get; set; } // 0x00000000 + public uint Unknown_14Ch { get; set; } // 0x00000000 + + // reference data + public BVH BVH { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.BvhPointer = reader.ReadUInt64(); + this.Unknown_138h = reader.ReadUInt32(); + this.Unknown_13Ch = reader.ReadUInt32(); + this.Unknown_140h = reader.ReadUInt16(); + this.Unknown_142h = reader.ReadUInt16(); + this.Unknown_144h = reader.ReadUInt32(); + this.Unknown_148h = reader.ReadUInt32(); + this.Unknown_14Ch = reader.ReadUInt32(); + + // read reference data + if (this.BvhPointer > 65535) + { + this.BVH = reader.ReadBlockAt( + this.BvhPointer // offset + ); + } + else + { + //this can happen in some ydr's for some reason + } + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + this.BvhPointer = (ulong)(this.BVH != null ? this.BVH.FilePosition : 0); + + // write structure data + writer.Write(this.BvhPointer); + writer.Write(this.Unknown_138h); + writer.Write(this.Unknown_13Ch); + writer.Write(this.Unknown_140h); + writer.Write(this.Unknown_142h); + writer.Write(this.Unknown_144h); + writer.Write(this.Unknown_148h); + writer.Write(this.Unknown_14Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if (BVH != null) list.Add(BVH); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundComposite : Bounds + { + public override long BlockLength + { + get { return 176; } + } + + // structure data + public ulong ChildrenPointer { get; set; } + public ulong ChildrenTransformation1Pointer { get; set; } + public ulong ChildrenTransformation2Pointer { get; set; } + public ulong ChildrenBoundingBoxesPointer { get; set; } + public ulong Unknown_90h_Pointer { get; set; } + public ulong Unknown_98h_Pointer { get; set; } + public ushort ChildrenCount1 { get; set; } + public ushort ChildrenCount2 { get; set; } + public uint Unknown_A4h { get; set; } // 0x00000000 + public ulong BVHPointer { get; set; } + + // reference data + public ResourcePointerArray64 Children { get; set; } + //public ResourceSimpleArray ChildrenTransformation1 { get; set; } + //public ResourceSimpleArray ChildrenTransformation2 { get; set; } + //public ResourceSimpleArray ChildrenBoundingBoxes { get; set; } + //public ResourceSimpleArray Unknown_90h_Data { get; set; } + //public ResourceSimpleArray Unknown_98h_Data { get; set; } + public SharpDX.Matrix[] ChildrenTransformation1 { get; set; } + public SharpDX.Matrix[] ChildrenTransformation2 { get; set; } + public AABB_s[] ChildrenBoundingBoxes { get; set; } + public BoundComposite_Unknown_B_002_s[] Unknown_90h_Data { get; set; } + public BoundComposite_Unknown_B_002_s[] Unknown_98h_Data { get; set; } + + public BVH BVH { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.ChildrenPointer = reader.ReadUInt64(); + this.ChildrenTransformation1Pointer = reader.ReadUInt64(); + this.ChildrenTransformation2Pointer = reader.ReadUInt64(); + this.ChildrenBoundingBoxesPointer = reader.ReadUInt64(); + this.Unknown_90h_Pointer = reader.ReadUInt64(); + this.Unknown_98h_Pointer = reader.ReadUInt64(); + this.ChildrenCount1 = reader.ReadUInt16(); + this.ChildrenCount2 = reader.ReadUInt16(); + this.Unknown_A4h = reader.ReadUInt32(); + this.BVHPointer = reader.ReadUInt64(); + + // read reference data + this.Children = reader.ReadBlockAt>( + this.ChildrenPointer, // offset + this.ChildrenCount1 + ); + + if ((Children != null) && (Children.data_items != null)) + { + foreach (var child in Children.data_items) + { + if (child != null) child.Parent = this; + } + } + + //this.ChildrenTransformation1 = reader.ReadBlockAt>( + // this.ChildrenTransformation1Pointer, // offset + // this.ChildrenCount1 + //); + //this.ChildrenTransformation2 = reader.ReadBlockAt>( + // this.ChildrenTransformation2Pointer, // offset + // this.ChildrenCount1 + //); + //this.ChildrenBoundingBoxes = reader.ReadBlockAt>( + // this.ChildrenBoundingBoxesPointer, // offset + // this.ChildrenCount1 + //); + //this.Unknown_90h_Data = reader.ReadBlockAt>( + // this.Unknown_90h_Pointer, // offset + // this.ChildrenCount1 + //); + //this.Unknown_98h_Data = reader.ReadBlockAt>( + // this.Unknown_98h_Pointer, // offset + // this.ChildrenCount1 + //); + + + this.ChildrenTransformation1 = reader.ReadStructsAt(this.ChildrenTransformation1Pointer, this.ChildrenCount1); + this.ChildrenTransformation2 = reader.ReadStructsAt(this.ChildrenTransformation2Pointer, this.ChildrenCount1); + this.ChildrenBoundingBoxes = reader.ReadStructsAt(this.ChildrenBoundingBoxesPointer, this.ChildrenCount1); + this.Unknown_90h_Data = reader.ReadStructsAt(this.Unknown_90h_Pointer, this.ChildrenCount1); + this.Unknown_98h_Data = reader.ReadStructsAt(this.Unknown_98h_Pointer, this.ChildrenCount1); + + + this.BVH = reader.ReadBlockAt( + this.BVHPointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + this.ChildrenPointer = (ulong)(this.Children != null ? this.Children.FilePosition : 0); + //this.ChildrenTransformation1Pointer = (ulong)(this.ChildrenTransformation1 != null ? this.ChildrenTransformation1.Position : 0); + //this.ChildrenTransformation2Pointer = (ulong)(this.ChildrenTransformation2 != null ? this.ChildrenTransformation2.Position : 0); + //this.ChildrenBoundingBoxesPointer = (ulong)(this.ChildrenBoundingBoxes != null ? this.ChildrenBoundingBoxes.Position : 0); + //this.Unknown_90h_Pointer = (ulong)(this.Unknown_90h_Data != null ? this.Unknown_90h_Data.Position : 0); + //this.Unknown_98h_Pointer = (ulong)(this.Unknown_98h_Data != null ? this.Unknown_98h_Data.Position : 0); + //TODO: fix + this.ChildrenCount1 = (ushort)(this.Children != null ? this.Children.Count : 0); + this.ChildrenCount2 = (ushort)(this.Children != null ? this.Children.Count : 0); + this.BVHPointer = (ulong)(this.BVH != null ? this.BVH.FilePosition : 0); + + // write structure data + writer.Write(this.ChildrenPointer); + writer.Write(this.ChildrenTransformation1Pointer); + writer.Write(this.ChildrenTransformation2Pointer); + writer.Write(this.ChildrenBoundingBoxesPointer); + writer.Write(this.Unknown_90h_Pointer); + writer.Write(this.Unknown_98h_Pointer); + writer.Write(this.ChildrenCount1); + writer.Write(this.ChildrenCount2); + writer.Write(this.Unknown_A4h); + writer.Write(this.BVHPointer); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if (Children != null) list.Add(Children); + //if (ChildrenTransformation1 != null) list.Add(ChildrenTransformation1); //TODO: fix + //if (ChildrenTransformation2 != null) list.Add(ChildrenTransformation2); + //if (ChildrenBoundingBoxes != null) list.Add(ChildrenBoundingBoxes); + //if (Unknown_90h_Data != null) list.Add(Unknown_90h_Data); + //if (Unknown_98h_Data != null) list.Add(Unknown_98h_Data); + if (BVH != null) list.Add(BVH); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct BoundComposite_Unknown_B_002_s + { + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } + public override string ToString() + { + return Unknown_0h.ToString() + ", " + Unknown_4h.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundDisc : Bounds + { + public override long BlockLength + { + get { return 128; } + } + + // structure data + public uint Unknown_70h { get; set; } // 0x00000000 + public uint Unknown_74h { get; set; } // 0x00000000 + public uint Unknown_78h { get; set; } // 0x00000000 + public uint Unknown_7Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundCylinder : Bounds + { + public override long BlockLength + { + get { return 128; } + } + + // structure data + public uint Unknown_70h { get; set; } // 0x00000000 + public uint Unknown_74h { get; set; } // 0x00000000 + public uint Unknown_78h { get; set; } // 0x00000000 + public uint Unknown_7Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class BVH : ResourceSystemBlock + { + public override long BlockLength + { + get { return 128; } + } + + // structure data + public ulong NodesPointer { get; set; } + public uint NodesCount { get; set; } + public uint Count2 { get; set; } + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public SharpDX.Vector4 BoundingBoxMin { get; set; } + public SharpDX.Vector4 BoundingBoxMax { get; set; } + public SharpDX.Vector4 BoundingBoxCenter { get; set; } + public SharpDX.Vector4 QuantumInverse { get; set; } + public SharpDX.Vector4 Quantum { get; set; } // bounding box dimension / 2^16 + //public ResourceSimpleList64 Trees { get; set; } + public ResourceSimpleList64Ptr TreesPtr { get; set; } + public BVHTreeInfo_s[] Trees { get; set; } + + // reference data + //public ResourceSimpleArray2 Nodes; + public BVHNode_s[] Nodes { get; set; } + public BVHNode_s[] Nodes_Unk1 { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.NodesPointer = reader.ReadUInt64(); + this.NodesCount = reader.ReadUInt32(); + this.Count2 = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + //this.BoundingBoxMin = reader.ReadBlock(); + //this.BoundingBoxMax = reader.ReadBlock(); + //this.BoundingBoxCenter = reader.ReadBlock(); + //this.QuantumInverse = reader.ReadBlock(); + //this.Quantum = reader.ReadBlock(); + this.BoundingBoxMin = reader.ReadStruct(); + this.BoundingBoxMax = reader.ReadStruct(); + this.BoundingBoxCenter = reader.ReadStruct(); + this.QuantumInverse = reader.ReadStruct(); + this.Quantum = reader.ReadStruct(); + + //this.Trees = reader.ReadBlock>(); + this.TreesPtr = reader.ReadStruct(); + this.Trees = reader.ReadStructsAt(this.TreesPtr.EntriesPointer, this.TreesPtr.EntriesCount); + + // read reference data + //this.Nodes = reader.ReadBlockAt>( + // this.NodesPointer, // offset + // this.NodesCount, + // this.Count2 - this.NodesCount + //); + + this.Nodes = reader.ReadStructsAt(this.NodesPointer, this.NodesCount); + + this.Nodes_Unk1 = reader.ReadStructsAt(this.NodesPointer + NodesCount * 16 /*sizeof(BVHNode_s)*/, Count2 - NodesCount); + + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.NodesPointer = (ulong)(this.Nodes != null ? this.Nodes.Position : 0); + //this.NodesCount = (uint)(this.Nodes != null ? this.Nodes.Array1.Count : 0); + //this.Count2 = (uint)(this.Nodes != null ? this.Nodes.Array1.Count + this.Nodes.Array2.Count : 0); + //TODO: fix + + // write structure data + writer.Write(this.NodesPointer); + writer.Write(this.NodesCount); + writer.Write(this.Count2); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + //writer.WriteBlock(this.BoundingBoxMin); + //writer.WriteBlock(this.BoundingBoxMax); + //writer.WriteBlock(this.BoundingBoxCenter); + //writer.WriteBlock(this.QuantumInverse); + //writer.WriteBlock(this.Quantum); + //writer.WriteBlock(this.Trees); //TODO: fix + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Nodes != null) list.Add(Nodes); //TODO: fix! + //if (Trees != null) list.Add(Trees); + return list.ToArray(); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(0x20, BoundingBoxMin), + //new Tuple(0x30, BoundingBoxMax), + //new Tuple(0x40, BoundingBoxCenter), + //new Tuple(0x50, QuantumInverse), + //new Tuple(0x60, Quantum), + //new Tuple(0x70, Trees) //TODO: fix! + }; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct BVHTreeInfo_s + { + public short MinX { get; set; } + public short MinY { get; set; } + public short MinZ { get; set; } + public short MaxX { get; set; } + public short MaxY { get; set; } + public short MaxZ { get; set; } + public short NodeIndex1 { get; set; } + public short NodeIndex2 { get; set; } + + public override string ToString() + { + return NodeIndex1.ToString() + ", " + NodeIndex2.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct BVHNode_s + { + public short MinX { get; set; } + public short MinY { get; set; } + public short MinZ { get; set; } + public short MaxX { get; set; } + public short MaxY { get; set; } + public short MaxZ { get; set; } + public short PolyId { get; set; } + public short PolyCount { get; set; } + + public override string ToString() + { + return PolyId.ToString() + ": " + PolyCount.ToString(); + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct BoundsMaterialType + { + public byte Index { get; set; } + + public BoundsMaterialData MaterialData + { + get + { + return BoundsMaterialTypes.GetMaterial(this); + } + } + + public override string ToString() + { + return BoundsMaterialTypes.GetMaterialName(this); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundsMaterialData + { + public string Name { get; set; } + public string Filter { get; set; } + public string FXGroup { get; set; } + public string VFXDisturbanceType { get; set; } + public string RumbleProfile { get; set; } + public string ReactWeaponType { get; set; } + public string Friction { get; set; } + public string Elasticity { get; set; } + public string Density { get; set; } + public string TyreGrip { get; set; } + public string WetGrip { get; set; } + public string TyreDrag { get; set; } + public string TopSpeedMult { get; set; } + public string Softness { get; set; } + public string Noisiness { get; set; } + public string PenetrationResistance { get; set; } + public string SeeThru { get; set; } + public string ShootThru { get; set; } + public string ShootThruFX { get; set; } + public string NoDecal { get; set; } + public string Porous { get; set; } + public string HeatsTyre { get; set; } + public string Material { get; set; } + + public Color4 Colour { get; set; } + + public override string ToString() + { + return Name; + } + } + + public static class BoundsMaterialTypes + { + private static Dictionary ColourDict; + private static List Materials; + + public static void Init(GameFileCache gameFileCache) + { + var rpfman = gameFileCache.RpfMan; + + InitColours(); + + var list = new List(); + string filename = "common.rpf\\data\\materials\\materials.dat"; + if (gameFileCache.EnableDlc) + { + filename = "update\\update.rpf\\common\\data\\materials\\materials.dat"; + } + string txt = rpfman.GetFileUTF8Text(filename); + AddMaterialsDat(txt, list); + + Materials = list; + } + + private static void InitColours() + { + var dict = new Dictionary(); + string txt = File.ReadAllText("Materials.txt"); + string[] lines = txt.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < lines.Length; i++) + { + var line = lines[i]; + if (line.Length < 10) continue; + if (line[0] == '#') continue; + string[] parts = line.Split(new[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length != 2) continue; + string name = parts[0].Trim(); + string cstr = parts[1].Trim(); + uint cval = Convert.ToUInt32(cstr, 16); + Color4 c = new Color4(cval); + dict[name] = c; + } + ColourDict = dict; + } + + private static void AddMaterialsDat(string txt, List list) + { + list.Clear(); + if (txt == null) return; + string[] lines = txt.Split('\n'); + for (int i = 1; i < lines.Length; i++) + { + var line = lines[i]; + if (line.Length < 20) continue; + if (line[0] == '#') continue; + string[] parts = line.Split(new[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length < 10) continue; + int cp = 0; + BoundsMaterialData d = new BoundsMaterialData(); + for (int p = 0; p < parts.Length; p++) + { + string part = parts[p].Trim(); + if (string.IsNullOrWhiteSpace(part)) continue; + switch (cp) + { + case 0: d.Name = part; break; + case 1: d.Filter = part; break; + case 2: d.FXGroup = part; break; + case 3: d.VFXDisturbanceType = part; break; + case 4: d.RumbleProfile = part; break; + case 5: d.ReactWeaponType = part; break; + case 6: d.Friction = part; break; + case 7: d.Elasticity = part; break; + case 8: d.Density = part; break; + case 9: d.TyreGrip = part; break; + case 10: d.WetGrip = part; break; + case 11: d.TyreDrag = part; break; + case 12: d.TopSpeedMult = part; break; + case 13: d.Softness = part; break; + case 14: d.Noisiness = part; break; + case 15: d.PenetrationResistance = part; break; + case 16: d.SeeThru = part; break; + case 17: d.ShootThru = part; break; + case 18: d.ShootThruFX = part; break; + case 19: d.NoDecal = part; break; + case 20: d.Porous = part; break; + case 21: d.HeatsTyre = part; break; + case 22: d.Material = part; break; + } + cp++; + } + if (cp != 23) + { } + + Color4 c; + if ((ColourDict != null) && (ColourDict.TryGetValue(d.Name, out c))) + { + d.Colour = c; + } + else + { + d.Colour = new Color4(0xFFCCCCCC); + } + + + list.Add(d); + } + + + //StringBuilder sb = new StringBuilder(); + //foreach (var d in list) + //{ + // sb.AppendLine(d.Name); + //} + //string names = sb.ToString(); + + } + + + public static BoundsMaterialData GetMaterial(BoundsMaterialType type) + { + if (Materials == null) return null; + if (type.Index >= Materials.Count) return null; + return Materials[type.Index]; + } + + public static string GetMaterialName(BoundsMaterialType type) + { + var m = GetMaterial(type); + if (m == null) return string.Empty; + return m.Name; + } + + public static Color4 GetMaterialColour(BoundsMaterialType type) + { + var m = GetMaterial(type); + if (m == null) return new Color4(0xFFCCCCCC); + return m.Colour; + } + } + + +} diff --git a/GameFiles/Resources/Clip.cs b/GameFiles/Resources/Clip.cs new file mode 100644 index 0000000..5a67d3c --- /dev/null +++ b/GameFiles/Resources/Clip.cs @@ -0,0 +1,1804 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + + +//ruthlessly stolen + + +namespace CodeWalker.GameFiles +{ + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ClipDictionary : ResourceFileBase + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong AnimationsPointer { get; set; } + public uint Unknown_20h { get; set; } // 0x00000101 + public uint Unknown_24h { get; set; } // 0x00000000 + public ulong ClipsPointer { get; set; } + public ushort ClipsMapCapacity { get; set; } + public ushort ClipsMapEntries { get; set; } + public uint Unknown_34h { get; set; } // 0x01000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + // reference data + public AnimationMap Animations { get; set; } + public ResourcePointerArray64 Clips { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.AnimationsPointer = reader.ReadUInt64(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.ClipsPointer = reader.ReadUInt64(); + this.ClipsMapCapacity = reader.ReadUInt16(); + this.ClipsMapEntries = reader.ReadUInt16(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + this.Animations = reader.ReadBlockAt( + this.AnimationsPointer // offset + ); + this.Clips = reader.ReadBlockAt>( + this.ClipsPointer, // offset + this.ClipsMapCapacity + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + this.AnimationsPointer = (ulong)(this.Animations != null ? this.Animations.FilePosition : 0); + this.ClipsPointer = (ulong)(this.Clips != null ? this.Clips.FilePosition : 0); + //this.c1 = (ushort)(this.Clips != null ? this.Clips.Count : 0); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.AnimationsPointer); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.ClipsPointer); + writer.Write(this.ClipsMapCapacity); + writer.Write(this.ClipsMapEntries); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if (Animations != null) list.Add(Animations); + if (Clips != null) list.Add(Clips); + return list.ToArray(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class AnimationMap : ResourceSystemBlock + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong AnimationsPointer { get; set; } + public ushort AnimationsMapCapacity { get; set; } + public ushort AnimationsMapEntries { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } // 0x00000001 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + // reference data + public ResourcePointerArray64 Animations { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.AnimationsPointer = reader.ReadUInt64(); + this.AnimationsMapCapacity = reader.ReadUInt16(); + this.AnimationsMapEntries = reader.ReadUInt16(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + + // read reference data + this.Animations = reader.ReadBlockAt>( + this.AnimationsPointer, // offset + this.AnimationsMapCapacity + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.AnimationsPointer = (ulong)(this.Animations != null ? this.Animations.FilePosition : 0); + //this.c1 = (ushort)(this.Anims != null ? this.Anims.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.AnimationsPointer); + writer.Write(this.AnimationsMapCapacity); + writer.Write(this.AnimationsMapEntries); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Animations != null) list.Add(Animations); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class AnimationMapEntry : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32; } + } + + // structure data + public MetaHash Hash { get; set; } + public uint Unknown_4h { get; set; } // 0x00000000 + public ulong AnimationPtr { get; set; } + public ulong NextEntryPtr { get; set; } + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + + // reference data + public Animation Animation { get; set; } + public AnimationMapEntry NextEntry { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Hash = new MetaHash(reader.ReadUInt32()); + this.Unknown_4h = reader.ReadUInt32(); + this.AnimationPtr = reader.ReadUInt64(); + this.NextEntryPtr = reader.ReadUInt64(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + + // read reference data + this.Animation = reader.ReadBlockAt( + this.AnimationPtr // offset + ); + this.NextEntry = reader.ReadBlockAt( + this.NextEntryPtr // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.AnimationPtr = (ulong)(this.Animation != null ? this.Animation.FilePosition : 0); + this.NextEntryPtr = (ulong)(this.NextEntry != null ? this.NextEntry.FilePosition : 0); + + // write structure data + writer.Write(this.Hash); + writer.Write(this.Unknown_4h); + writer.Write(this.AnimationPtr); + writer.Write(this.NextEntryPtr); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Animation != null) list.Add(Animation); + if (NextEntry != null) list.Add(NextEntry); + return list.ToArray(); + } + + public override string ToString() + { + return Hash.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Animation : ResourceSystemBlock + { + public override long BlockLength + { + get { return 96; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public ushort Unknown_10h { get; set; } + public ushort Unknown_12h { get; set; } + public ushort Unknown_14h { get; set; } + public ushort Unknown_16h { get; set; } + public float Unknown_18h { get; set; } + public byte Unknown_1Ch { get; set; } + public byte Unknown_1Dh { get; set; } + public byte Unknown_1Eh { get; set; } + public byte Unknown_1Fh { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public ResourcePointerList64 Sequences { get; set; } + //public ResourceSimpleList64 Unknown_50h { get; set; } + public ResourceSimpleList64Ptr BoneIdsPtr { get; set; } + public AnimationBoneId[] BoneIds { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); //1 1 1 1 + this.Unknown_8h = reader.ReadUInt32(); //0 0 0 0 + this.Unknown_Ch = reader.ReadUInt32(); //0 0 0 0 + this.Unknown_10h = reader.ReadUInt16(); //257 257 257 257 flags? + this.Unknown_12h = reader.ReadUInt16(); //0 0 0 0 + this.Unknown_14h = reader.ReadUInt16(); //221 17 151 201 frames + this.Unknown_16h = reader.ReadUInt16(); //223 31 159 207 sequence limit? + this.Unknown_18h = reader.ReadSingle(); //7.34 0.53 5.0 6.66 duration + this.Unknown_1Ch = reader.ReadByte(); //118 0 216 116 + this.Unknown_1Dh = reader.ReadByte(); //152 36 130 182 + this.Unknown_1Eh = reader.ReadByte(); //99 0 66 180 + this.Unknown_1Fh = reader.ReadByte(); //205 107 44 26 + this.Unknown_20h = reader.ReadUInt32(); //0 0 0 0 + this.Unknown_24h = reader.ReadUInt32(); //0 0 0 0 + this.Unknown_28h = reader.ReadUInt32(); //0 0 0 0 + this.Unknown_2Ch = reader.ReadUInt32(); //0 0 0 0 + this.Unknown_30h = reader.ReadUInt32(); //0 0 0 0 + this.Unknown_34h = reader.ReadUInt32(); //0 0 0 0 + this.Unknown_38h = reader.ReadUInt32(); //314 174 1238 390 sequences length? + this.Unknown_3Ch = reader.ReadUInt32(); //2 2 2 2 material/type? + this.Sequences = reader.ReadBlock>(); + //this.Unknown_50h = reader.ReadBlock>(); + this.BoneIdsPtr = reader.ReadStruct(); + //this.BoneIds = reader.ReadUintsAt(this.BoneIdsPtr.EntriesPointer, this.BoneIdsPtr.EntriesCount); + this.BoneIds = reader.ReadStructsAt(this.BoneIdsPtr.EntriesPointer, this.BoneIdsPtr.EntriesCount); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_12h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_16h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_1Eh); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.WriteBlock(this.Sequences); + //writer.WriteBlock(this.Unknown_50h);//todo: fix!! + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0x40, Sequences), + //new Tuple(0x50, Unknown_50h)//todo: fix! + }; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct AnimationBoneId + { + public ushort BoneId { get; set; } + public byte Unk0 { get; set; } + public byte Unk1 { get; set; } + public override string ToString() + { + return BoneId.ToString() + ": " + Unk0.ToString() + ", " + Unk1.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Sequence : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32 + Data.Length; } + } + + // structure data + public byte Unknown_00h { get; set; } + public byte Unknown_01h { get; set; } + public byte Unknown_02h { get; set; } + public byte Unknown_03h { get; set; } + public uint DataLength { get; set; } + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } + public uint Unknown_10h { get; set; } + public ushort Unknown_14h { get; set; } + public ushort Unknown_16h { get; set; } + //public uint Unknown_18h { get; set; } + public ushort Unknown_18h { get; set; } + public ushort Unknown_1Ah { get; set; } + public ushort Unknown_1Ch { get; set; } + public ushort Unknown_1Eh { get; set; } + public byte[] Data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + //this.Unknown_00h = reader.ReadUInt32();//2965995365 2837183178 + this.Unknown_00h = reader.ReadByte(); //101 202 97 120 + this.Unknown_01h = reader.ReadByte(); //127 250 202 168 + this.Unknown_02h = reader.ReadByte(); //201 27 115 126 + this.Unknown_03h = reader.ReadByte(); //176 169 131 74 + this.DataLength = reader.ReadUInt32(); //282 142 1206 358 + this.Unknown_08h = reader.ReadUInt32();//0 0 0 0 + this.Unknown_0Ch = reader.ReadUInt32();//224 (E0) 32 (20) 536 (218) 300 offset in data to? + this.Unknown_10h = reader.ReadUInt32();//314 174 1238 390 (=Length) + this.Unknown_14h = reader.ReadUInt16();//0 0 0 0 + this.Unknown_16h = reader.ReadUInt16();//221 (DD) 17 (11) 151 (97) 201 + this.Unknown_18h = reader.ReadUInt16();//0 4 4 0 type? + this.Unknown_1Ah = reader.ReadUInt16();//0 0 106 0 + this.Unknown_1Ch = reader.ReadUInt16();//0 17 0 0 bone? + this.Unknown_1Eh = reader.ReadUInt16();//64 255 255 64 + + + var pos = reader.Position; + + this.Data = reader.ReadBytes((int)DataLength); + + reader.Position = pos; + float[] fvals = reader.ReadFloatsAt((ulong)pos, DataLength / 4); + ushort[] svals = reader.ReadUshortsAt((ulong)pos, DataLength / 2); + if (fvals != null) + { } + + //reader.Position = pos; + //float f0 = reader.ReadSingle(); // 0 0 0 0 + //var v0 = reader.ReadStruct();// 0,0,0 1,1,1 0,0,0 0,0,0 + //float f1 = reader.ReadSingle(); // 0 0 0 0 + //uint u0 = reader.ReadUInt32(); // 0 17 0 0 + //short s1 = reader.ReadInt16(); // 0 112 0 0 + //short s2 = reader.ReadInt16(); // 0 14048 0 0 + ////float f2 = reader.ReadSingle(); // 0 6.675771E-06 0 + //float f3 = reader.ReadSingle(); // 0 -0.875 0 + //short u2 = reader.ReadInt16(); // 0 -1 + //short u3 = reader.ReadInt16(); // 0 1 + //short u4 = reader.ReadInt16(); // 0 -1 + //short u5 = reader.ReadInt16(); // 0 1 + //short u6 = reader.ReadInt16(); // 0 -18725 + //short u7 = reader.ReadInt16(); // 0 1 + //short u8 = reader.ReadInt16(); // 23 -18725 + //short u9 = reader.ReadInt16(); // 0 1 + //short uA = reader.ReadInt16(); // 2825 28086 + //short uB = reader.ReadInt16(); // 0 1 + + + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_00h); + writer.Write(this.DataLength); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_1Eh); + writer.Write(this.Data); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ClipMapEntry : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32; } + } + + // structure data + public MetaHash Hash { get; set; } + public uint Unknown_4h { get; set; } // 0x00000000 + public ulong ClipPointer { get; set; } + public ulong NextPointer { get; set; } + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + + // reference data + public ClipBase Clip { get; set; } + public ClipMapEntry Next { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Hash = new MetaHash(reader.ReadUInt32()); + this.Unknown_4h = reader.ReadUInt32(); + this.ClipPointer = reader.ReadUInt64(); + this.NextPointer = reader.ReadUInt64(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + + // read reference data + this.Clip = reader.ReadBlockAt( + this.ClipPointer // offset + ); + this.Next = reader.ReadBlockAt( + this.NextPointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.ClipPointer = (ulong)(this.Clip != null ? this.Clip.FilePosition : 0); + this.NextPointer = (ulong)(this.Next != null ? this.Next.FilePosition : 0); + + // write structure data + writer.Write(this.Hash); + writer.Write(this.Unknown_4h); + writer.Write(this.ClipPointer); + writer.Write(this.NextPointer); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Clip != null) list.Add(Clip); + if (Next != null) list.Add(Next); + return list.ToArray(); + } + + public override string ToString() + { + return Hash.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class ClipBase : ResourceSystemBlock, IResourceXXSystemBlock + { + public override long BlockLength + { + get { return 112; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong NamePointer { get; set; } + //public uint Unknown_20h { get; set; } // short, short -> name length (+1) + public ushort Unknown_20h { get; set; } // short, name length + public ushort Unknown_22h { get; set; } // short, name length +1 + public uint Unknown_24h { get; set; } // 0x00000000 + public ulong Unknown_28hPtr { get; set; } // 0x50000000 + //public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } // 0x00000000 + public ulong p2 { get; set; } + public ulong p3 { get; set; } + public uint Unknown_48h { get; set; } // 0x00000001 + public uint Unknown_4Ch { get; set; } // 0x00000000 + + // reference data + public string Name { get; set; } + public Unknown_CL_200 p2data { get; set; } + public Unknown_CL_001 p3data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + //this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt16(); + this.Unknown_22h = reader.ReadUInt16(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28hPtr = reader.ReadUInt64(); + //this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.p2 = reader.ReadUInt64(); + this.p3 = reader.ReadUInt64(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + + // read reference data + //this.Name = reader.ReadBlockAt( + // this.NamePointer // offset + //); + this.Name = reader.ReadStringAt(this.NamePointer); + this.p2data = reader.ReadBlockAt( + this.p2 // offset + ); + this.p3data = reader.ReadBlockAt( + this.p3 // offset + ); + + if ((Unknown_28hPtr != 0) && (Unknown_28hPtr != 0x50000000)) + { + } + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); + this.p2 = (ulong)(this.p2data != null ? this.p2data.FilePosition : 0); + this.p3 = (ulong)(this.p3data != null ? this.p3data.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.NamePointer); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28hPtr); + //writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.p2); + writer.Write(this.p3); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Name != null) list.Add(Name); + if (p2data != null) list.Add(p2data); + if (p3data != null) list.Add(p3data); + return list.ToArray(); + } + + public IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters) + { + reader.Position += 16; + var type = reader.ReadByte(); + reader.Position -= 17; + + switch (type) + { + case 1: return new ClipAnimation(); + case 2: return new ClipAnimations(); + default: return null;// throw new Exception("Unknown type"); + } + } + + + public override string ToString() + { + return Name; + } + + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class ClipAnimation : ClipBase + { + public override long BlockLength + { + get { return 112; } + } + + // structure data + public ulong AnimationPointer { get; set; } + public float Unknown_58h { get; set; } + public float Unknown_5Ch { get; set; } + public float Unknown_60h { get; set; } + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + + // reference data + public Animation Animation { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + this.AnimationPointer = reader.ReadUInt64(); + this.Unknown_58h = reader.ReadSingle(); + this.Unknown_5Ch = reader.ReadSingle(); + this.Unknown_60h = reader.ReadSingle(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + + this.Animation = reader.ReadBlockAt( + this.AnimationPointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + this.AnimationPointer = (ulong)(this.Animation != null ? this.Animation.FilePosition : 0); + + writer.Write(this.AnimationPointer); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + list.AddRange(base.GetReferences()); + if (Animation != null) list.Add(Animation); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class ClipAnimations : ClipBase + { + public override long BlockLength + { + get { return 112; } + } + + // structure data + public ulong AnimationsPointer { get; set; } + public ushort AnimationsCount1 { get; set; } + public ushort AnimationsCount2 { get; set; } + public uint Unknown_5Ch { get; set; } // 0x00000000 + public uint Unknown_60h { get; set; } + public uint Unknown_64h { get; set; } // 0x00000001 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + + // reference data + public ResourceSimpleArray Animations { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + this.AnimationsPointer = reader.ReadUInt64(); + this.AnimationsCount1 = reader.ReadUInt16(); + this.AnimationsCount2 = reader.ReadUInt16(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + + this.Animations = reader.ReadBlockAt>( + this.AnimationsPointer, // offset + this.AnimationsCount1 + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + this.AnimationsPointer = (ulong)(this.Animations != null ? this.Animations.FilePosition : 0); + //this.p4 = (ulong)(this.p4data != null ? this.p4data.Position : 0); + //this.c1 = (ushort)(this.p4data != null ? this.p4data.Count : 0); + + writer.Write(this.AnimationsPointer); + writer.Write(this.AnimationsCount1); + writer.Write(this.AnimationsCount2); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + list.AddRange(base.GetReferences()); + if (Animations != null) list.Add(Animations); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class ClipAnimationsEntry : ResourceSystemBlock + { + public override long BlockLength + { + get { return 24; } + } + + // structure data + public float Unknown_0h { get; set; } + public float Unknown_4h { get; set; } + public float Unknown_8h { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000000 + public ulong AnimationPointer { get; set; } + + // reference data + public Animation Animation { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadSingle(); + this.Unknown_4h = reader.ReadSingle(); + this.Unknown_8h = reader.ReadSingle(); + this.Unknown_Ch = reader.ReadUInt32(); + this.AnimationPointer = reader.ReadUInt64(); + + // read reference data + this.Animation = reader.ReadBlockAt( + this.AnimationPointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.AnimationPointer = (ulong)(this.Animation != null ? this.Animation.FilePosition : 0); + + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.AnimationPointer); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Animation != null) list.Add(Animation); + return list.ToArray(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_001 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public ulong p1 { get; set; } + public ushort c1 { get; set; } + public ushort c2 { get; set; } + public uint Unknown_Ch { get; set; } // 0x01000000 + + // reference data + public ResourcePointerArray64 p1data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.p1 = reader.ReadUInt64(); + this.c1 = reader.ReadUInt16(); + this.c2 = reader.ReadUInt16(); + this.Unknown_Ch = reader.ReadUInt32(); + + // read reference data + this.p1data = reader.ReadBlockAt>( + this.p1, // offset + this.c1 + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0); + //this.c1 = (ushort)(this.p1data != null ? this.p1data.Count : 0); + + // write structure data + writer.Write(this.p1); + writer.Write(this.c1); + writer.Write(this.c2); + writer.Write(this.Unknown_Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_002 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32; } + } + + // structure data + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } // 0x00000000 + public ulong DataPointer { get; set; } + public ulong NextPointer { get; set; } + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + + // reference data + public Unknown_CL_003 Data { get; set; } + public Unknown_CL_002 Next { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.DataPointer = reader.ReadUInt64(); + this.NextPointer = reader.ReadUInt64(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + + // read reference data + this.Data = reader.ReadBlockAt( + this.DataPointer // offset + ); + this.Next = reader.ReadBlockAt( + this.NextPointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.DataPointer = (ulong)(this.Data != null ? this.Data.FilePosition : 0); + this.NextPointer = (ulong)(this.Next != null ? this.Next.FilePosition : 0); + + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.DataPointer); + writer.Write(this.NextPointer); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Data != null) list.Add(Data); + if (Next != null) list.Add(Next); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_003 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong p1 { get; set; } + public ushort c1 { get; set; } + public ushort c2 { get; set; } + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } // 0x00000000 + + // reference data + public ResourcePointerArray64 p1data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.p1 = reader.ReadUInt64(); + this.c1 = reader.ReadUInt16(); + this.c2 = reader.ReadUInt16(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + this.p1data = reader.ReadBlockAt>( + this.p1, // offset + this.c1 + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0); + //this.c1 = (ushort)(this.p1data != null ? this.p1data.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.p1); + writer.Write(this.c1); + writer.Write(this.c2); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_004 : ResourceSystemBlock, IResourceXXSystemBlock + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public byte type { get; set; } + public byte Unknown_9h { get; set; } + public ushort Unknown_Ah { get; set; } + public uint Unknown_Ch { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.type = reader.ReadByte(); + this.Unknown_9h = reader.ReadByte(); + this.Unknown_Ah = reader.ReadUInt16(); + this.Unknown_Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.type); + writer.Write(this.Unknown_9h); + writer.Write(this.Unknown_Ah); + writer.Write(this.Unknown_Ch); + } + + public IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters) + { + reader.Position += 8; + var type = reader.ReadByte(); + reader.Position -= 9; + + switch (type) + { + case 1: return new Unknown_CL_004_type1(); + case 2: return new Unknown_CL_004_type2(); + case 3: return new Unknown_CL_004_type3(); + case 4: return new Unknown_CL_004_type4(); + case 6: return new Unknown_CL_004_type6(); + case 8: return new Unknown_CL_004_type8(); + default: return null;// throw new Exception("Unknown type"); + } + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_004_type1 : Unknown_CL_004 + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_004_type2 : Unknown_CL_004 + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_004_type3 : Unknown_CL_004 + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x6D7255E7 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_004_type4 : Unknown_CL_004 + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong p1 { get; set; } + public ushort c1 { get; set; } + public ushort c2 { get; set; } + public uint Unknown_2Ch { get; set; } // 0x00000000 + + // reference data + //public ResourceSimpleArray p1data { get; set; } // string (byte array...) + public byte[] p1data { get; set; } // string (byte array...) + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.p1 = reader.ReadUInt64(); + this.c1 = reader.ReadUInt16(); + this.c2 = reader.ReadUInt16(); + this.Unknown_2Ch = reader.ReadUInt32(); + + // read reference data + //this.p1data = reader.ReadBlockAt>( + // this.p1, // offset + // this.c2 + //); + this.p1data = reader.ReadBytesAt(this.p1, this.c2); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + //this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0);//todo:fix!~ + ////this.c2 = (ushort)(this.p1data != null ? this.p1data.Count : 0); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.p1); + writer.Write(this.c1); + writer.Write(this.c2); + writer.Write(this.Unknown_2Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + //if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_004_type6 : Unknown_CL_004 + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_004_type8 : Unknown_CL_004 + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x443D96E7 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_200 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32; } + } + + // structure data + public ulong p1 { get; set; } + public ushort c1 { get; set; } + public ushort c2 { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + + // reference data + public ResourcePointerArray64 p1data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.p1 = reader.ReadUInt64(); + this.c1 = reader.ReadUInt16(); + this.c2 = reader.ReadUInt16(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + + // read reference data + this.p1data = reader.ReadBlockAt>( + this.p1, // offset + this.c1 + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0); + //this.c1 = (ushort)(this.p1data != null ? this.p1data.Count : 0); + + // write structure data + writer.Write(this.p1); + writer.Write(this.c1); + writer.Write(this.c2); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_201 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 80; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong p0 { get; set; } + public ushort c1 { get; set; } + public ushort c2 { get; set; } + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public ulong p1 { get; set; } + + // reference data + public ResourcePointerArray64 p0data { get; set; } + public Unknown_CL_200 p1data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.p0 = reader.ReadUInt64(); + this.c1 = reader.ReadUInt16(); + this.c2 = reader.ReadUInt16(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.p1 = reader.ReadUInt64(); + + // read reference data + this.p0data = reader.ReadBlockAt>( + this.p0, // offset + this.c1 + ); + this.p1data = reader.ReadBlockAt( + this.p1 // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.p0 = (ulong)(this.p0data != null ? this.p0data.FilePosition : 0); + //this.c1 = (ushort)(this.p0data != null ? this.p0data.Count : 0); + this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.p0); + writer.Write(this.c1); + writer.Write(this.c2); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.p1); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (p0data != null) list.Add(p0data); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class Unknown_CL_202 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + + + +} diff --git a/GameFiles/Resources/Data.cs b/GameFiles/Resources/Data.cs new file mode 100644 index 0000000..755f942 --- /dev/null +++ b/GameFiles/Resources/Data.cs @@ -0,0 +1,483 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen + + + +using SharpDX; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public enum Endianess + { + LittleEndian, + BigEndian + } + + public enum DataType + { + Byte = 0, + Int16 = 1, + Int32 = 2, + Int64 = 3, + Uint16 = 4, + Uint32 = 5, + Uint64 = 6, + Float = 7, + Double = 8, + String = 9, + } + + public class DataReader + { + private Stream baseStream; + + /// + /// Gets or sets the endianess of the underlying stream. + /// + public Endianess Endianess + { + get; + set; + } + + /// + /// Gets the length of the underlying stream. + /// + public virtual long Length + { + get + { + return baseStream.Length; + } + } + + /// + /// Gets or sets the position within the underlying stream. + /// + public virtual long Position + { + get + { + return baseStream.Position; + } + set + { + baseStream.Position = value; + } + } + + /// + /// Initializes a new data reader for the specified stream. + /// + public DataReader(Stream stream, Endianess endianess = Endianess.LittleEndian) + { + this.baseStream = stream; + this.Endianess = endianess; + } + + /// + /// Reads data from the underlying stream. This is the only method that directly accesses + /// the data in the underlying stream. + /// + protected virtual byte[] ReadFromStream(int count, bool ignoreEndianess = false) + { + var buffer = new byte[count]; + baseStream.Read(buffer, 0, count); + + // handle endianess + if (!ignoreEndianess && (Endianess == Endianess.BigEndian)) + { + Array.Reverse(buffer); + } + + return buffer; + } + + /// + /// Reads a byte. + /// + public byte ReadByte() + { + return ReadFromStream(1)[0]; + } + + /// + /// Reads a sequence of bytes. + /// + public byte[] ReadBytes(int count) + { + return ReadFromStream(count, true); + } + + /// + /// Reads a signed 16-bit value. + /// + public short ReadInt16() + { + return BitConverter.ToInt16(ReadFromStream(2), 0); + } + + /// + /// Reads a signed 32-bit value. + /// + public int ReadInt32() + { + return BitConverter.ToInt32(ReadFromStream(4), 0); + } + + /// + /// Reads a signed 64-bit value. + /// + public long ReadInt64() + { + return BitConverter.ToInt64(ReadFromStream(8), 0); + } + + /// + /// Reads an unsigned 16-bit value. + /// + public ushort ReadUInt16() + { + return BitConverter.ToUInt16(ReadFromStream(2), 0); + } + + /// + /// Reads an unsigned 32-bit value. + /// + public uint ReadUInt32() + { + return BitConverter.ToUInt32(ReadFromStream(4), 0); + } + + /// + /// Reads an unsigned 64-bit value. + /// + public ulong ReadUInt64() + { + return BitConverter.ToUInt64(ReadFromStream(8), 0); + } + + /// + /// Reads a single precision floating point value. + /// + public float ReadSingle() + { + return BitConverter.ToSingle(ReadFromStream(4), 0); + } + + /// + /// Reads a double precision floating point value. + /// + public double ReadDouble() + { + return BitConverter.ToDouble(ReadFromStream(8), 0); + } + + /// + /// Reads a string. + /// + public string ReadString() + { + var bytes = new List(); + var temp = ReadFromStream(1)[0]; + while (temp != 0) + { + bytes.Add(temp); + temp = ReadFromStream(1)[0]; + } + + return Encoding.UTF8.GetString(bytes.ToArray()); + } + + + public Vector3 ReadVector3() + { + Vector3 v = new Vector3(); + v.X = ReadSingle(); + v.Y = ReadSingle(); + v.Z = ReadSingle(); + return v; + } + public Vector4 ReadVector4() + { + Vector4 v = new Vector4(); + v.X = ReadSingle(); + v.Y = ReadSingle(); + v.Z = ReadSingle(); + v.W = ReadSingle(); + return v; + } + + public Matrix ReadMatrix() + { + Matrix m = new Matrix(); + m.M11 = ReadSingle(); + m.M21 = ReadSingle(); + m.M31 = ReadSingle(); + m.M41 = ReadSingle(); + m.M12 = ReadSingle(); + m.M22 = ReadSingle(); + m.M32 = ReadSingle(); + m.M42 = ReadSingle(); + m.M13 = ReadSingle(); + m.M23 = ReadSingle(); + m.M33 = ReadSingle(); + m.M43 = ReadSingle(); + m.M14 = ReadSingle(); + m.M24 = ReadSingle(); + m.M34 = ReadSingle(); + m.M44 = ReadSingle(); + return m; + } + + + + + //TODO: put this somewhere else... + public static uint SizeOf(DataType type) + { + switch (type) + { + default: + case DataType.Byte: return 1; + case DataType.Int16: return 2; + case DataType.Int32: return 4; + case DataType.Int64: return 8; + case DataType.Uint16: return 2; + case DataType.Uint32: return 4; + case DataType.Uint64: return 8; + case DataType.Float: return 4; + case DataType.Double: return 8; + case DataType.String: return 0; //how long is a string..? + } + } + + + + + } + + public class DataWriter + { + private Stream baseStream; + + /// + /// Gets or sets the endianess of the underlying stream. + /// + public Endianess Endianess + { + get; + set; + } + + /// + /// Gets the length of the underlying stream. + /// + public virtual long Length + { + get + { + return baseStream.Length; + } + } + + /// + /// Gets or sets the position within the underlying stream. + /// + public virtual long Position + { + get + { + return baseStream.Position; + } + set + { + baseStream.Position = value; + } + } + + /// + /// Initializes a new data writer for the specified stream. + /// + public DataWriter(Stream stream, Endianess endianess = Endianess.LittleEndian) + { + this.baseStream = stream; + this.Endianess = endianess; + } + + /// + /// Writes data to the underlying stream. This is the only method that directly accesses + /// the data in the underlying stream. + /// + protected virtual void WriteToStream(byte[] value, bool ignoreEndianess = false) + { + if (!ignoreEndianess && (Endianess == Endianess.BigEndian)) + { + var buffer = (byte[])value.Clone(); + Array.Reverse(buffer); + baseStream.Write(buffer, 0, buffer.Length); + } + else + { + baseStream.Write(value, 0, value.Length); + } + } + + /// + /// Writes a byte. + /// + public void Write(byte value) + { + WriteToStream(new byte[] { value }); + } + + /// + /// Writes a sequence of bytes. + /// + public void Write(byte[] value) + { + WriteToStream(value, true); + } + + /// + /// Writes a signed 16-bit value. + /// + public void Write(short value) + { + WriteToStream(BitConverter.GetBytes(value)); + } + + /// + /// Writes a signed 32-bit value. + /// + public void Write(int value) + { + WriteToStream(BitConverter.GetBytes(value)); + } + + /// + /// Writes a signed 64-bit value. + /// + public void Write(long value) + { + WriteToStream(BitConverter.GetBytes(value)); + } + + /// + /// Writes an unsigned 16-bit value. + /// + public void Write(ushort value) + { + WriteToStream(BitConverter.GetBytes(value)); + } + + /// + /// Writes an unsigned 32-bit value. + /// + public void Write(uint value) + { + WriteToStream(BitConverter.GetBytes(value)); + } + + /// + /// Writes an unsigned 64-bit value. + /// + public void Write(ulong value) + { + WriteToStream(BitConverter.GetBytes(value)); + } + + /// + /// Writes a single precision floating point value. + /// + public void Write(float value) + { + WriteToStream(BitConverter.GetBytes(value)); + } + + /// + /// Writes a double precision floating point value. + /// + public void Write(double value) + { + WriteToStream(BitConverter.GetBytes(value)); + } + + /// + /// Writes a string. + /// + public void Write(string value) + { + foreach (var c in value) + Write((byte)c); + Write((byte)0); + } + + + + public void Write(Vector3 value) + { + Write(value.X); + Write(value.Y); + Write(value.Z); + } + public void Write(Vector4 value) + { + Write(value.X); + Write(value.Y); + Write(value.Z); + Write(value.W); + } + + public void Write(Matrix value) + { + Write(value.M11); + Write(value.M21); + Write(value.M31); + Write(value.M41); + Write(value.M12); + Write(value.M22); + Write(value.M32); + Write(value.M42); + Write(value.M13); + Write(value.M23); + Write(value.M33); + Write(value.M43); + Write(value.M14); + Write(value.M24); + Write(value.M34); + Write(value.M44); + } + + } + + + +} diff --git a/GameFiles/Resources/Drawable.cs b/GameFiles/Resources/Drawable.cs new file mode 100644 index 0000000..e4f3ad3 --- /dev/null +++ b/GameFiles/Resources/Drawable.cs @@ -0,0 +1,2642 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ShaderGroup : ResourceSystemBlock + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public ulong TextureDictionaryPointer { get; set; } + public ulong ShadersPointer { get; set; } + public ushort ShadersCount1 { get; set; } + public ushort ShadersCount2 { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + // reference data + public TextureDictionary TextureDictionary { get; set; } + public ResourcePointerArray64 Shaders { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.TextureDictionaryPointer = reader.ReadUInt64(); + this.ShadersPointer = reader.ReadUInt64(); + this.ShadersCount1 = reader.ReadUInt16(); + this.ShadersCount2 = reader.ReadUInt16(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + this.TextureDictionary = reader.ReadBlockAt( + this.TextureDictionaryPointer // offset + ); + this.Shaders = reader.ReadBlockAt>( + this.ShadersPointer, // offset + this.ShadersCount1 + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.TextureDictionaryPointer = (ulong)(this.TextureDictionary != null ? this.TextureDictionary.FilePosition : 0); + this.ShadersPointer = (ulong)(this.Shaders != null ? this.Shaders.FilePosition : 0); + // this.ShadersCount1 = (ushort)(this.Shaders != null ? this.Shaders.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.TextureDictionaryPointer); + writer.Write(this.ShadersPointer); + writer.Write(this.ShadersCount1); + writer.Write(this.ShadersCount2); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (TextureDictionary != null) list.Add(TextureDictionary); + if (Shaders != null) list.Add(Shaders); + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ShaderFX : ResourceSystemBlock + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public ulong ParametersPointer { get; set; } + public MetaHash Name { get; set; } //530103687, 2401522793, 1912906641 + public uint Unknown_Ch { get; set; } // 0x00000000 + public byte ParameterCount { get; set; } + public byte Unknown_11h { get; set; } // 2, 0, + public ushort Unknown_12h { get; set; } // 32768 + public uint Unknown_14h { get; set; } //10485872, 17826000, 26214720 + public MetaHash FileName { get; set; } //2918136469, 2635608835, 2247429097 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } //65284, 65281 + public ushort Unknown_24h { get; set; } //0 + public byte Unknown_26h { get; set; } //0 + public byte TextureParametersCount { get; set; } + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + // reference data + //public ResourceSimpleArray Parameters { get; set; } + //public SimpleArrayOFFSET ParameterHashes { get; set; } + public ShaderParametersBlock ParametersList { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.ParametersPointer = reader.ReadUInt64(); + this.Name = new MetaHash(reader.ReadUInt32()); + this.Unknown_Ch = reader.ReadUInt32(); + this.ParameterCount = reader.ReadByte(); + this.Unknown_11h = reader.ReadByte(); + this.Unknown_12h = reader.ReadUInt16(); + this.Unknown_14h = reader.ReadUInt32(); + this.FileName = new MetaHash(reader.ReadUInt32()); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt16(); + this.Unknown_26h = reader.ReadByte(); + this.TextureParametersCount = reader.ReadByte(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + + // read reference data + //this.Parameters = reader.ReadBlockAt>( + // this.ParametersPointer, // offset + // this.ParameterCount + //); + //this.ParameterHashes = reader.ReadBlockAt>( + // this.ParametersPointer, // offset + // this.ParameterCount, + // this.TextureParametersCount + //); + + + this.ParametersList = reader.ReadBlockAt( + this.ParametersPointer, // offset + this.ParameterCount + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.ParametersPointer = (ulong)(this.ParametersList != null ? this.ParametersList.FilePosition : 0); + //this.ParametersPointer = (ulong)(this.Parameters != null ? this.Parameters.Position : 0); + //this.ParameterCount = (byte)(this.Parameters != null ? this.Parameters.Count : 0); + + // write structure data + writer.Write(this.ParametersPointer); + writer.Write(this.Name.Hash); + writer.Write(this.Unknown_Ch); + writer.Write(this.ParameterCount); + writer.Write(this.Unknown_11h); + writer.Write(this.Unknown_12h); + writer.Write(this.Unknown_14h); + writer.Write(this.FileName.Hash); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_26h); + writer.Write(this.TextureParametersCount); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (ParametersList != null) list.Add(ParametersList); + // if (ParameterHashes != null) list.Add(ParameterHashes); + return list.ToArray(); + } + + + public override string ToString() + { + return Name.ToString() + " (" + FileName.ToString() + ")"; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ShaderParameter : ResourceSystemBlock + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public byte DataType { get; set; } + public byte Unknown_1h { get; set; } + public ushort Unknown_2h { get; set; } + public uint Unknown_4h { get; set; } + public ulong DataPointer { get; set; } + + //public IResourceBlock Data { get; set; } + public object Data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.DataType = reader.ReadByte(); + this.Unknown_1h = reader.ReadByte(); + this.Unknown_2h = reader.ReadUInt16(); + this.Unknown_4h = reader.ReadUInt32(); + this.DataPointer = reader.ReadUInt64(); + + // DONT READ DATA... + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.DataType); + writer.Write(this.Unknown_1h); + writer.Write(this.Unknown_2h); + writer.Write(this.Unknown_4h); + writer.Write(this.DataPointer); + + // DONT WRITE DATA + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + //if (Data != null) list.Add(Data); + return list.ToArray(); + } + + public override string ToString() + { + return (Data != null) ? Data.ToString() : (DataType.ToString() + ": " + DataPointer.ToString()); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ShaderParametersBlock : ResourceSystemBlock + { + + public override long BlockLength + { + get + { + long offset = 0; + foreach (var x in Parameters) + { + offset += 16; + } + + foreach (var x in Parameters) + { + offset += 16 * x.DataType; + } + + offset += Parameters.Length * 4; + + return offset; + } + } + + public ShaderParameter[] Parameters { get; set; } + public MetaName[] Hashes { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + int cnt = Convert.ToInt32(parameters[0]); + + var paras = new List(); + for (int i = 0; i < cnt; i++) + { + paras.Add(reader.ReadBlock()); + } + + int offset = 0; + for (int i = 0; i < cnt; i++) + { + var p = paras[i]; + + // read reference data + switch (p.DataType) + { + case 0: + offset += 0; + p.Data = reader.ReadBlockAt( + p.DataPointer // offset + ); + break; + case 1: + offset += 16; + //p.Data = reader.ReadBlockAt( + // p.DataPointer // offset + //); + p.Data = reader.ReadStructAt( + (long)p.DataPointer // offset + ); + + break; + //case 2: + // offset += 32; + // p.Data = reader.ReadBlockAt>( + // p.DataPointer, // offset + // 2 + // ); + // break; + //case 4: + // offset += 64; + // p.Data = reader.ReadBlockAt>( + // p.DataPointer, // offset + // 4 + // ); + // break; + + default: + offset += 16 * p.DataType; + //p.Data = reader.ReadBlockAt>( + // p.DataPointer, // offset + // p.DataType + // ); + p.Data = reader.ReadStructsAt(p.DataPointer, p.DataType); + + break; + } + } + + reader.Position += offset; + var hashes = new List(); + for (int i = 0; i < cnt; i++) + { + hashes.Add((MetaName)reader.ReadUInt32()); + } + + Parameters = paras.ToArray(); + Hashes = hashes.ToArray(); + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + //TODO: fix all this + + // update pointers... + //foreach (var f in Parameters) + // if (f.Data != null) + // f.DataPointer = (ulong)f.Data.Position; + // else + // f.DataPointer = 0; + + + // write parameter infos + foreach (var f in Parameters) + writer.WriteBlock(f); + + // write vector data + //foreach (var f in Parameters) + //{ + // if (f.DataType != 0) + // writer.WriteBlock(f.Data); + //} + + // write hashes + foreach (var h in Hashes) + writer.Write((uint)h); + } + + + + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + list.AddRange(base.GetReferences()); + + //TODO: fix this + //foreach (var x in Parameters) + // if (x.DataType == 0) + // list.Add(x.Data); + + return list.ToArray(); + } + + public override Tuple[] GetParts() + { + var list = new List>(); + list.AddRange(base.GetParts()); + + long offset = 0; + foreach (var x in Parameters) + { + list.Add(new Tuple(offset, x)); + offset += 16; + } + + //TODO: fix this + //foreach (var x in Parameters) + //{ + // if (x.DataType != 0) + // list.Add(new Tuple(offset, x.Data)); + // offset += 16 * x.DataType; + //} + + return list.ToArray(); + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Skeleton : ResourceSystemBlock + { + public override long BlockLength + { + get { return 112; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public ulong Unknown_10h_Pointer { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unknown_1Ch { get; set; } + public ulong BonesPointer { get; set; } + public ulong TransformationsInvertedPointer { get; set; } + public ulong TransformationsPointer { get; set; } + public ulong ParentIndicesPointer { get; set; } + public ulong Unknown_40h_Pointer { get; set; } + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public MetaHash Unknown_50h { get; set; } + public MetaHash Unknown_54h { get; set; } + public MetaHash Unknown_58h { get; set; } + public ushort Unknown_5Ch { get; set; } // 0x0001 + public ushort BonesCount { get; set; } + public ushort Count4 { get; set; } + public ushort Unknown_62h { get; set; } // 0x0000 + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + + // reference data + public ResourcePointerArray64 Unknown_10h_Data { get; set; } + public ResourceSimpleArray Bones { get; set; } + //public ResourceSimpleArray TransformationsInverted { get; set; } + //public ResourceSimpleArray Transformations { get; set; } + //public ResourceSimpleArray ParentIndices { get; set; } + //public ResourceSimpleArray Unknown_40h_Data { get; set; } + + public SharpDX.Matrix[] TransformationsInverted { get; set; } + public SharpDX.Matrix[] Transformations { get; set; } + public ushort[] ParentIndices { get; set; } + public ushort[] Unknown_40h_Data { get; set; } + + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h_Pointer = reader.ReadUInt64(); + this.Count1 = reader.ReadUInt16(); + this.Count2 = reader.ReadUInt16(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.BonesPointer = reader.ReadUInt64(); + this.TransformationsInvertedPointer = reader.ReadUInt64(); + this.TransformationsPointer = reader.ReadUInt64(); + this.ParentIndicesPointer = reader.ReadUInt64(); + this.Unknown_40h_Pointer = reader.ReadUInt64(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = new MetaHash(reader.ReadUInt32()); + this.Unknown_54h = new MetaHash(reader.ReadUInt32()); + this.Unknown_58h = new MetaHash(reader.ReadUInt32()); + this.Unknown_5Ch = reader.ReadUInt16(); + this.BonesCount = reader.ReadUInt16(); + this.Count4 = reader.ReadUInt16(); + this.Unknown_62h = reader.ReadUInt16(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + + // read reference data + this.Unknown_10h_Data = reader.ReadBlockAt>( + this.Unknown_10h_Pointer, // offset + this.Count1 + ); + this.Bones = reader.ReadBlockAt>( + this.BonesPointer, // offset + this.BonesCount + ); + //this.TransformationsInverted = reader.ReadBlockAt>( + // this.TransformationsInvertedPointer, // offset + // this.BonesCount + //); + //this.Transformations = reader.ReadBlockAt>( + // this.TransformationsPointer, // offset + // this.BonesCount + //); + //this.ParentIndices = reader.ReadBlockAt>( + // this.ParentIndicesPointer, // offset + // this.BonesCount + //); + //this.Unknown_40h_Data = reader.ReadBlockAt>( + // this.Unknown_40h_Pointer, // offset + // this.Count4 + //); + this.TransformationsInverted = reader.ReadStructsAt(this.TransformationsInvertedPointer, this.BonesCount); + this.Transformations = reader.ReadStructsAt(this.TransformationsPointer, this.BonesCount); + this.ParentIndices = reader.ReadUshortsAt(this.ParentIndicesPointer, this.BonesCount); + this.Unknown_40h_Data = reader.ReadUshortsAt(this.Unknown_40h_Pointer, this.Count4); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.Unknown_10h_Pointer = (ulong)(this.Unknown_10h_Data != null ? this.Unknown_10h_Data.FilePosition : 0); + // this.c1 = (ushort)(this.arr1 != null ? this.arr1.Count : 0); + this.BonesPointer = (ulong)(this.Bones != null ? this.Bones.FilePosition : 0); + //this.TransformationsInvertedPointer = (ulong)(this.TransformationsInverted != null ? this.TransformationsInverted.Position : 0); + //this.TransformationsPointer = (ulong)(this.Transformations != null ? this.Transformations.Position : 0); + //this.ParentIndicesPointer = (ulong)(this.ParentIndices != null ? this.ParentIndices.Position : 0); + //this.Unknown_40h_Pointer = (ulong)(this.Unknown_40h_Data != null ? this.Unknown_40h_Data.Position : 0); + ///// this.c3 = (ushort)(this.Bones != null ? this.Bones.Count : 0); + //this.Count4 = (ushort)(this.Unknown_40h_Data != null ? this.Unknown_40h_Data.Count : 0); + //TODO: fix/update + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h_Pointer); + writer.Write(this.Count1); + writer.Write(this.Count2); + writer.Write(this.Unknown_1Ch); + writer.Write(this.BonesPointer); + writer.Write(this.TransformationsInvertedPointer); + writer.Write(this.TransformationsPointer); + writer.Write(this.ParentIndicesPointer); + writer.Write(this.Unknown_40h_Pointer); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.BonesCount); + writer.Write(this.Count4); + writer.Write(this.Unknown_62h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Unknown_10h_Data != null) list.Add(Unknown_10h_Data); + if (Bones != null) list.Add(Bones); + //if (TransformationsInverted != null) list.Add(TransformationsInverted); + //if (Transformations != null) list.Add(Transformations); + //if (ParentIndices != null) list.Add(ParentIndices); + //if (Unknown_40h_Data != null) list.Add(Unknown_40h_Data); //TODO: fix + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Skeleton_Unknown_D_001 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } + public ulong Unknown_8h_Pointer { get; set; } + + // reference data + public Skeleton_Unknown_D_001 p1data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h_Pointer = reader.ReadUInt64(); + + // read reference data + this.p1data = reader.ReadBlockAt( + this.Unknown_8h_Pointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.Unknown_8h_Pointer = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0); + + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h_Pointer); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Bone : ResourceSystemBlock + { + public override long BlockLength + { + get { return 80; } + } + + // structure data + public float RotationX { get; set; } + public float RotationY { get; set; } + public float RotationZ { get; set; } + public float RotationW { get; set; } + public float TranslationX { get; set; } + public float TranslationY { get; set; } + public float TranslationZ { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public float Unknown_20h { get; set; } // 1.0 + public float Unknown_24h { get; set; } // 1.0 + public float Unknown_28h { get; set; } // 1.0 + public float Unknown_2Ch { get; set; } // 1.0 + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } // 0x00000000 + public ulong NamePointer { get; set; } + public ushort Unknown_40h { get; set; } + public ushort Unknown_42h { get; set; } + public ushort Id { get; set; } + public ushort Unknown_46h { get; set; } + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + + // reference data + public string Name { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.RotationX = reader.ReadSingle(); + this.RotationY = reader.ReadSingle(); + this.RotationZ = reader.ReadSingle(); + this.RotationW = reader.ReadSingle(); + this.TranslationX = reader.ReadSingle(); + this.TranslationY = reader.ReadSingle(); + this.TranslationZ = reader.ReadSingle(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadSingle(); + this.Unknown_24h = reader.ReadSingle(); + this.Unknown_28h = reader.ReadSingle(); + this.Unknown_2Ch = reader.ReadSingle(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + this.Unknown_40h = reader.ReadUInt16(); + this.Unknown_42h = reader.ReadUInt16(); + this.Id = reader.ReadUInt16(); + this.Unknown_46h = reader.ReadUInt16(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + + // read reference data + this.Name = reader.ReadStringAt(//BlockAt( + this.NamePointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); //TODO: fix + + // write structure data + writer.Write(this.RotationX); + writer.Write(this.RotationY); + writer.Write(this.RotationZ); + writer.Write(this.RotationW); + writer.Write(this.TranslationX); + writer.Write(this.TranslationY); + writer.Write(this.TranslationZ); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.NamePointer); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_42h); + writer.Write(this.Id); + writer.Write(this.Unknown_46h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Name != null) list.Add(Name); //TODO: fix + return list.ToArray(); + } + + public override string ToString() + { + return Id.ToString() + ": " + Name; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Joints : ResourceSystemBlock + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public ulong RotationLimitsPointer { get; set; } + public ulong TranslationLimitsPointer { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ushort RotationLimitsCount { get; set; } + public ushort TranslationLimitsCount { get; set; } + public ushort Unknown_34h { get; set; } // 0x0000 + public ushort Unknown_36h { get; set; } // 0x0001 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + // reference data + //public ResourceSimpleArray RotationLimits { get; set; } + //public ResourceSimpleArray TranslationLimits { get; set; } + public JointRotationLimit_s[] RotationLimits { get; set; } + public JointTranslationLimit_s[] TranslationLimits { get; set; } + + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.RotationLimitsPointer = reader.ReadUInt64(); + this.TranslationLimitsPointer = reader.ReadUInt64(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.RotationLimitsCount = reader.ReadUInt16(); + this.TranslationLimitsCount = reader.ReadUInt16(); + this.Unknown_34h = reader.ReadUInt16(); + this.Unknown_36h = reader.ReadUInt16(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + //this.RotationLimits = reader.ReadBlockAt>( + // this.RotationLimitsPointer, // offset + // this.RotationLimitsCount + //); + //this.TranslationLimits = reader.ReadBlockAt>( + // this.TranslationLimitsPointer, // offset + // this.TranslationLimitsCount + //); + this.RotationLimits = reader.ReadStructsAt(this.RotationLimitsPointer, this.RotationLimitsCount); + this.TranslationLimits = reader.ReadStructsAt(this.TranslationLimitsPointer, this.TranslationLimitsCount); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.RotationLimitsPointer = (ulong)(this.RotationLimits != null ? this.RotationLimits.Position : 0); + //this.TranslationLimitsPointer = (ulong)(this.TranslationLimits != null ? this.TranslationLimits.Position : 0); + //this.RotationLimitsCount = (ushort)(this.RotationLimits != null ? this.RotationLimits.Count : 0); + //this.TranslationLimitsCount = (ushort)(this.TranslationLimits != null ? this.TranslationLimits.Count : 0); + //TODO: fix this + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.RotationLimitsPointer); + writer.Write(this.TranslationLimitsPointer); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.RotationLimitsCount); + writer.Write(this.TranslationLimitsCount); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_36h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (RotationLimits != null) list.Add(RotationLimits); + //if (TranslationLimits != null) list.Add(TranslationLimits); + //TODO: fix this + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct JointRotationLimit_s + { + // structure data + public uint Unknown_0h { get; set; } // 0x00000000 + public uint Unknown_4h { get; set; } // 0x00000000 + public ushort BoneId { get; set; } + public ushort Unknown_Ah { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000001 + public uint Unknown_10h { get; set; } // 0x00000003 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public float Unknown_2Ch { get; set; } // 1.0 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public float Unknown_40h { get; set; } // 1.0 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public float Unknown_50h { get; set; } // -pi + public float Unknown_54h { get; set; } // pi + public float Unknown_58h { get; set; } // 1.0 + public float Unknown_5Ch { get; set; } + public float Unknown_60h { get; set; } + public float Unknown_64h { get; set; } + public float Unknown_68h { get; set; } + public float Unknown_6Ch { get; set; } + public float Unknown_70h { get; set; } + public float Unknown_74h { get; set; } // pi + public float Unknown_78h { get; set; } // -pi + public float Unknown_7Ch { get; set; } // pi + public float Unknown_80h { get; set; } // pi + public float Unknown_84h { get; set; } // -pi + public float Unknown_88h { get; set; } // pi + public float Unknown_8Ch { get; set; } // pi + public float Unknown_90h { get; set; } // -pi + public float Unknown_94h { get; set; } // pi + public float Unknown_98h { get; set; } // pi + public float Unknown_9Ch { get; set; } // -pi + public float Unknown_A0h { get; set; } // pi + public float Unknown_A4h { get; set; } // pi + public float Unknown_A8h { get; set; } // -pi + public float Unknown_ACh { get; set; } // pi + public float Unknown_B0h { get; set; } // pi + public float Unknown_B4h { get; set; } // -pi + public float Unknown_B8h { get; set; } // pi + public uint Unknown_BCh { get; set; } // 0x00000100 + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct JointTranslationLimit_s + { + public uint Unknown_0h { get; set; } // 0x00000000 + public uint Unknown_4h { get; set; } // 0x00000000 + public uint BoneId { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public SharpDX.Vector3 Min { get; set; } + public uint Unknown_2Ch { get; set; } // 0x00000000 + public SharpDX.Vector3 Max { get; set; } + public uint Unknown_3Ch { get; set; } // 0x00000000 + } + + + + + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class DrawableModel : ResourceSystemBlock + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public ulong GeometriesPointer { get; set; } + public ushort GeometriesCount1 { get; set; } + public ushort GeometriesCount2 { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong Unknown_18h_Pointer { get; set; } + public ulong ShaderMappingPointer { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + + // reference data + public ResourcePointerArray64 Geometries { get; set; } + //public ResourceSimpleArray Unknown_18h_Data; + //public ResourceSimpleArray ShaderMapping; + public AABB_s[] Unknown_18h_Data { get; set; } + public ushort[] ShaderMapping { get; set; } + + public long MemoryUsage + { + get + { + long val = 0; + if ((Geometries != null) && (Geometries.data_items != null)) + { + foreach(var geom in Geometries.data_items) + { + if (geom == null) continue; + if (geom.VertexData != null) + { + val += geom.VertexData.MemoryUsage; + } + if (geom.IndexBuffer != null) + { + val += geom.IndexBuffer.IndicesCount * 4; + } + if (geom.VertexBuffer != null) + { + if ((geom.VertexBuffer.Data1 != null) && (geom.VertexBuffer.Data1 != geom.VertexData)) + { + val += geom.VertexBuffer.Data1.MemoryUsage; + } + if ((geom.VertexBuffer.Data2 != null) && (geom.VertexBuffer.Data2 != geom.VertexData)) + { + val += geom.VertexBuffer.Data2.MemoryUsage; + } + } + } + } + if (Unknown_18h_Data != null) + { + val += Unknown_18h_Data.Length * 32; + } + return val; + } + } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.GeometriesPointer = reader.ReadUInt64(); + this.GeometriesCount1 = reader.ReadUInt16(); + this.GeometriesCount2 = reader.ReadUInt16(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h_Pointer = reader.ReadUInt64(); + this.ShaderMappingPointer = reader.ReadUInt64(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + + // read reference data + this.Geometries = reader.ReadBlockAt>( + this.GeometriesPointer, // offset + this.GeometriesCount1 + ); + //this.Unknown_18h_Data = reader.ReadBlockAt>( + // this.Unknown_18h_Pointer, // offset + // this.GeometriesCount1 > 1 ? this.GeometriesCount1 + 1 : this.GeometriesCount1 + //); + //this.ShaderMapping = reader.ReadBlockAt>( + // this.ShaderMappingPointer, // offset + // this.GeometriesCount1 + //); + this.Unknown_18h_Data = reader.ReadStructsAt(this.Unknown_18h_Pointer, (uint)(this.GeometriesCount1 > 1 ? this.GeometriesCount1 + 1 : this.GeometriesCount1)); + this.ShaderMapping = reader.ReadUshortsAt(this.ShaderMappingPointer, this.GeometriesCount1); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.GeometriesPointer = (ulong)(this.Geometries != null ? this.Geometries.FilePosition : 0); + // this.GeometriesCount1 = (ushort)(this.Geometries != null ? this.Geometries.Count : 0); + //this.Unknown_18h_Pointer = (ulong)(this.Unknown_18h_Data != null ? this.Unknown_18h_Data.Position : 0); + //this.ShaderMappingPointer = (ulong)(this.ShaderMapping != null ? this.ShaderMapping.Position : 0); + //TODO: fix + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.GeometriesPointer); + writer.Write(this.GeometriesCount1); + writer.Write(this.GeometriesCount2); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h_Pointer); + writer.Write(this.ShaderMappingPointer); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Geometries != null) list.Add(Geometries); + //if (Unknown_18h_Data != null) list.Add(Unknown_18h_Data); + //if (ShaderMapping != null) list.Add(ShaderMapping); //TODO: fix + return list.ToArray(); + } + + public override string ToString() + { + return "(" + Geometries.Count + " geometr" + (Geometries.Count != 1 ? "ies)" : "y)"); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class DrawableGeometry : ResourceSystemBlock + { + public override long BlockLength + { + get { return 152; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong VertexBufferPointer { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public ulong IndexBufferPointer { get; set; } + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public uint IndicesCount { get; set; } + public uint Unknown_5Ch { get; set; } + public ushort VerticesCount { get; set; } + public ushort Unknown_62h { get; set; } // 0x0003 + public uint Unknown_64h { get; set; } // 0x00000000 + public ulong BoneIdsPointer { get; set; } + public ushort VertexStride { get; set; } + public ushort Count1 { get; set; } + public uint Unknown_74h { get; set; } // 0x00000000 + public ulong VertexDataPointer { get; set; } + public uint Unknown_80h { get; set; } // 0x00000000 + public uint Unknown_84h { get; set; } // 0x00000000 + public uint Unknown_88h { get; set; } // 0x00000000 + public uint Unknown_8Ch { get; set; } // 0x00000000 + public uint Unknown_90h { get; set; } // 0x00000000 + public uint Unknown_94h { get; set; } // 0x00000000 + + // reference data + public VertexBuffer VertexBuffer { get; set; } + public IndexBuffer IndexBuffer { get; set; } + public ushort[] BoneIds { get; set; } + public VertexData VertexData { get; set; } + public ShaderFX Shader { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.VertexBufferPointer = reader.ReadUInt64(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.IndexBufferPointer = reader.ReadUInt64(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.IndicesCount = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.VerticesCount = reader.ReadUInt16(); + this.Unknown_62h = reader.ReadUInt16(); + this.Unknown_64h = reader.ReadUInt32(); + this.BoneIdsPointer = reader.ReadUInt64(); + this.VertexStride = reader.ReadUInt16(); + this.Count1 = reader.ReadUInt16(); + this.Unknown_74h = reader.ReadUInt32(); + this.VertexDataPointer = reader.ReadUInt64(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + + // read reference data + this.VertexBuffer = reader.ReadBlockAt( + this.VertexBufferPointer // offset + ); + this.IndexBuffer = reader.ReadBlockAt( + this.IndexBufferPointer // offset + ); + //this.Unknown_68h_Data = reader.ReadBlockAt>( + // this.Unknown_68h_Pointer, // offset + // this.Count1 + //); + this.BoneIds = reader.ReadUshortsAt(this.BoneIdsPointer, this.Count1); + if (this.BoneIds != null) //skinned mesh bones to use? peds, also yft props... + { + } + + if (this.VertexBuffer != null) + { + this.VertexData = this.VertexBuffer.Data1; + if (this.VertexData == null) + { + this.VertexData = this.VertexBuffer.Data2; + } + if ((this.VertexDataPointer != 0) && (VertexDataPointer != VertexBuffer.DataPointer1)) + { + //some mods hit here! + // try + // { + // this.VertexData = reader.ReadBlockAt( + // this.VertexDataPointer, // offset + // this.VertexStride, + // this.VerticesCount, + // this.VertexBuffer.Info + // ); + // } + // catch + // { } + } + } + else + { } + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.VertexBufferPointer = (ulong)(this.VertexBuffer != null ? this.VertexBuffer.FilePosition : 0); + this.IndexBufferPointer = (ulong)(this.IndexBuffer != null ? this.IndexBuffer.FilePosition : 0); + //this.Unknown_68h_Pointer = (ulong)(this.Unknown_68h_Data != null ? this.Unknown_68h_Data.Position : 0); + //this.VertexStride = (ushort)(this.VertexData != null ? this.VertexData.Count : 0); //TODO: fix + //this.c1 = (ushort)(this.p1data != null ? this.p1data.Count : 0); + this.VertexDataPointer = (ulong)(this.VertexData != null ? this.VertexData.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.VertexBufferPointer); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.IndexBufferPointer); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.IndicesCount); + writer.Write(this.Unknown_5Ch); + writer.Write(this.VerticesCount); + writer.Write(this.Unknown_62h); + writer.Write(this.Unknown_64h); + writer.Write(this.BoneIdsPointer); + writer.Write(this.VertexStride); + writer.Write(this.Count1); + writer.Write(this.Unknown_74h); + writer.Write(this.VertexDataPointer); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (VertexBuffer != null) list.Add(VertexBuffer); + if (IndexBuffer != null) list.Add(IndexBuffer); + //if (Unknown_68h_Data != null) list.Add(Unknown_68h_Data); //TODO: fix + if (VertexData != null) list.Add(VertexData); + return list.ToArray(); + } + + public override string ToString() + { + return VerticesCount.ToString() + " verts, " + Shader.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class VertexBuffer : ResourceSystemBlock + { + public override long BlockLength + { + get { return 128; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public ushort VertexStride { get; set; } + public ushort Unknown_Ah { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000000 + public ulong DataPointer1 { get; set; } + public uint VertexCount { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong DataPointer2 { get; set; } + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ulong InfoPointer { get; set; } + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + public uint Unknown_60h { get; set; } // 0x00000000 + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + public uint Unknown_70h { get; set; } // 0x00000000 + public uint Unknown_74h { get; set; } // 0x00000000 + public uint Unknown_78h { get; set; } // 0x00000000 + public uint Unknown_7Ch { get; set; } // 0x00000000 + + // reference data + public VertexData Data1 { get; set; } + public VertexData Data2 { get; set; } + public VertexDeclaration Info { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.VertexStride = reader.ReadUInt16(); + this.Unknown_Ah = reader.ReadUInt16(); + this.Unknown_Ch = reader.ReadUInt32(); + this.DataPointer1 = reader.ReadUInt64(); + this.VertexCount = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.DataPointer2 = reader.ReadUInt64(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.InfoPointer = reader.ReadUInt64(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + + // read reference data + this.Info = reader.ReadBlockAt( + this.InfoPointer // offset + ); + this.Data1 = reader.ReadBlockAt( + this.DataPointer1, // offset + this.VertexStride, + this.VertexCount, + this.Info + ); + this.Data2 = reader.ReadBlockAt( + this.DataPointer2, // offset + this.VertexStride, + this.VertexCount, + this.Info + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.VertexStride = (uint)(this.Data1 != null ? this.Data1.Count : 0); + this.DataPointer1 = (ulong)(this.Data1 != null ? this.Data1.FilePosition : 0); + this.DataPointer2 = (ulong)(this.Data2 != null ? this.Data2.FilePosition : 0); + this.InfoPointer = (ulong)(this.Info != null ? this.Info.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.VertexStride); + writer.Write(this.Unknown_Ah); + writer.Write(this.Unknown_Ch); + writer.Write(this.DataPointer1); + writer.Write(this.VertexCount); + writer.Write(this.Unknown_1Ch); + writer.Write(this.DataPointer2); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.InfoPointer); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Data1 != null) list.Add(Data1); + if (Data2 != null) list.Add(Data2); + if (Info != null) list.Add(Info); + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class VertexData : ResourceSystemBlock + { + + + private int length = 0; + public override long BlockLength + { + get + { + return this.length; + } + } + + + + public int cnt { get; set; } + public VertexDeclaration info { get; set; } + public object[] Data { get; set; } + public uint[] Types { get; set; } + + + public VertexType VertexType { get; set; } + public byte[] VertexBytes { get; set; } + + public int VertexCount { get; set; } + public int VertexStride { get; set; } + + public long MemoryUsage + { + get + { + return (long)VertexCount * (long)VertexStride; + } + } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + VertexStride = Convert.ToInt32(parameters[0]); + VertexCount = Convert.ToInt32(parameters[1]); + var info = (VertexDeclaration)parameters[2]; + this.cnt = VertexCount; + this.info = info; + + VertexType = (VertexType)info.Flags; + + VertexBytes = reader.ReadBytes(VertexCount * VertexStride); + + + switch (info.Types) + { + case 8598872888530528662: //YDR - 0x7755555555996996 + break; + case 216172782140628998: //YFT - 0x030000000199A006 + switch (info.Flags) + { + case 16473: VertexType = VertexType.PCCH2H4; break; // PCCH2H4 + default:break; + } + break; + case 216172782140612614: //YFT - 0x0300000001996006 PNCH2H4 + switch (info.Flags) + { + case 89: VertexType = VertexType.PNCH2; break; // PNCH2 + default: break; + } + break; + default: + break; + } + + } + + public /*override*/ void ReadOrig(ResourceDataReader reader, params object[] parameters) + { + int stride = Convert.ToInt32(parameters[0]); + int count = Convert.ToInt32(parameters[1]); + var info = (VertexDeclaration)parameters[2]; + this.cnt = count; + this.info = info; + + + bool[] IsUsed = new bool[16]; + for (int i = 0; i < 16; i++) + IsUsed[i] = ((info.Flags >> i) & 0x1) == 1; + + Types = new uint[16]; + for (int i = 0; i < 16; i++) + Types[i] = (uint)((info.Types >> (int)(4 * i)) & 0xF); + + + + Data = new object[16]; + for (int i = 0; i < 16; i++) + { + if (IsUsed[i]) + { + switch (Types[i]) + { + case 0: Data[i] = new ushort[1 * count]; break; + case 1: Data[i] = new ushort[2 * count]; break; + case 2: Data[i] = new ushort[3 * count]; break; + case 3: Data[i] = new ushort[4 * count]; break; + case 4: Data[i] = new float[1 * count]; break; + case 5: Data[i] = new float[2 * count]; break; + case 6: Data[i] = new float[3 * count]; break; + case 7: Data[i] = new float[4 * count]; break; + case 8: Data[i] = new uint[count]; break; + case 9: Data[i] = new uint[count]; break; + case 10: Data[i] = new uint[count]; break; + default: + throw new Exception(); + } + } + } + + + + long pos = reader.Position; + + // read... + for (int i = 0; i < count; i++) + { + + for (int k = 0; k < 16; k++) + { + if (IsUsed[k]) + { + switch (Types[k]) + { + // float16 + case 0: + { + var buf = Data[k] as ushort[]; + buf[i * 1 + 0] = reader.ReadUInt16(); + break; + } + case 1: + { + var buf = Data[k] as ushort[]; + buf[i * 2 + 0] = reader.ReadUInt16(); + buf[i * 2 + 1] = reader.ReadUInt16(); + break; + } + case 2: + { + var buf = Data[k] as ushort[]; + buf[i * 3 + 0] = reader.ReadUInt16(); + buf[i * 3 + 1] = reader.ReadUInt16(); + buf[i * 3 + 2] = reader.ReadUInt16(); + break; + } + case 3: + { + var buf = Data[k] as ushort[]; + buf[i * 4 + 0] = reader.ReadUInt16(); + buf[i * 4 + 1] = reader.ReadUInt16(); + buf[i * 4 + 2] = reader.ReadUInt16(); + buf[i * 4 + 3] = reader.ReadUInt16(); + break; + } + + // float32 + case 4: + { + var buf = Data[k] as float[]; + buf[i * 1 + 0] = reader.ReadSingle(); + break; + } + case 5: + { + var buf = Data[k] as float[]; + buf[i * 2 + 0] = reader.ReadSingle(); + buf[i * 2 + 1] = reader.ReadSingle(); + break; + } + case 6: + { + var buf = Data[k] as float[]; + buf[i * 3 + 0] = reader.ReadSingle(); + buf[i * 3 + 1] = reader.ReadSingle(); + buf[i * 3 + 2] = reader.ReadSingle(); + break; + } + case 7: + { + var buf = Data[k] as float[]; + buf[i * 4 + 0] = reader.ReadSingle(); + buf[i * 4 + 1] = reader.ReadSingle(); + buf[i * 4 + 2] = reader.ReadSingle(); + buf[i * 4 + 3] = reader.ReadSingle(); + break; + } + + case 8: + case 9: + case 10: + { + var buf = Data[k] as uint[]; + buf[i * 1 + 0] = reader.ReadUInt32(); + break; + } + + default: + throw new Exception(); + } + } + } + + } + + this.length = stride * count; + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + + // write... + for (int i = 0; i < cnt; i++) + { + + for (int k = 0; k < 16; k++) + { + if (Data[k] != null) + { + switch (Types[k]) + { + // float16 + case 0: + { + var buf = Data[k] as ushort[]; + writer.Write(buf[i * 1 + 0]); + break; + } + case 1: + { + var buf = Data[k] as ushort[]; + writer.Write(buf[i * 2 + 0]); + writer.Write(buf[i * 2 + 1]); + break; + } + case 2: + { + var buf = Data[k] as ushort[]; + writer.Write(buf[i * 3 + 0]); + writer.Write(buf[i * 3 + 1]); + writer.Write(buf[i * 3 + 2]); + break; + } + case 3: + { + var buf = Data[k] as ushort[]; + writer.Write(buf[i * 4 + 0]); + writer.Write(buf[i * 4 + 1]); + writer.Write(buf[i * 4 + 2]); + writer.Write(buf[i * 4 + 3]); + break; + } + + // float32 + case 4: + { + var buf = Data[k] as float[]; + writer.Write(buf[i * 1 + 0]); + break; + } + case 5: + { + var buf = Data[k] as float[]; + writer.Write(buf[i * 2 + 0]); + writer.Write(buf[i * 2 + 1]); + break; + } + case 6: + { + var buf = Data[k] as float[]; + writer.Write(buf[i * 3 + 0]); + writer.Write(buf[i * 3 + 1]); + writer.Write(buf[i * 3 + 2]); + break; + } + case 7: + { + var buf = Data[k] as float[]; + writer.Write(buf[i * 4 + 0]); + writer.Write(buf[i * 4 + 1]); + writer.Write(buf[i * 4 + 2]); + writer.Write(buf[i * 4 + 3]); + break; + } + + case 8: + case 9: + case 10: + { + var buf = Data[k] as uint[]; + writer.Write(buf[i * 1 + 0]); + break; + } + + default: + throw new Exception(); + } + } + } + + } + + } + + public override string ToString() + { + return "Type: " + VertexType.ToString() + ", Count: " + cnt.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class VertexDeclaration : ResourceSystemBlock + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public uint Flags { get; set; } + public ushort Stride { get; set; } + public byte Unknown_6h { get; set; } + public byte Count { get; set; } + public ulong Types { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Flags = reader.ReadUInt32(); + this.Stride = reader.ReadUInt16(); + this.Unknown_6h = reader.ReadByte(); + this.Count = reader.ReadByte(); + this.Types = reader.ReadUInt64(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Flags); + writer.Write(this.Stride); + writer.Write(this.Unknown_6h); + writer.Write(this.Count); + writer.Write(this.Types); + } + + public ulong GetDeclarationId() + { + ulong res = 0; + for(int i=0; i < 16; i++) + { + if (((Flags >> i) & 1) == 1) + { + res += (Types & (0xFu << (i * 4))); + } + } + return res; + } + + public override string ToString() + { + return Stride.ToString() + ": " + Count.ToString() + ": " + Flags.ToString() + ": " + Types.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class IndexBuffer : ResourceSystemBlock + { + public override long BlockLength + { + get { return 96; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint IndicesCount { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000000 + public ulong IndicesPointer { get; set; } + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + + // reference data + //public ResourceSimpleArray Indices; + public ushort[] Indices { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.IndicesCount = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.IndicesPointer = reader.ReadUInt64(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + + // read reference data + //this.Indices = reader.ReadBlockAt>( + // this.IndicesPointer, // offset + // this.IndicesCount + //); + this.Indices = reader.ReadUshortsAt(this.IndicesPointer, this.IndicesCount); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.IndicesCount = (uint)(this.Indices != null ? this.Indices.Count : 0); + //this.IndicesPointer = (ulong)(this.Indices != null ? this.Indices.Position : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.IndicesCount); + writer.Write(this.Unknown_Ch); + writer.Write(this.IndicesPointer); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Indices != null) list.Add(Indices); //TODO: fix.. + return list.ToArray(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct LightAttributes_s + { + // structure data + public uint Unknown_0h { get; set; } // 0x00000000 + public uint Unknown_4h { get; set; } // 0x00000000 + public float PositionX { get; set; } + public float PositionY { get; set; } + public float PositionZ { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public byte ColorR { get; set; } + public byte ColorG { get; set; } + public byte ColorB { get; set; } + public byte Unknown_1Bh { get; set; } + public float Intensity { get; set; } + public uint Unknown_20h { get; set; } + public ushort BoneId { get; set; } + public ushort Type { get; set; } + public uint Unknown_28h { get; set; } + public float Falloff { get; set; } + public float FalloffExponent { get; set; } + public float CullingPlaneNormalX { get; set; } + public float CullingPlaneNormalY { get; set; } + public float CullingPlaneNormalZ { get; set; } + public float CullingPlaneOffset { get; set; } + public byte ShadowBlur { get; set; } + public byte Unknown_45h { get; set; } + public ushort Unknown_46h { get; set; } + public uint Unknown_48h { get; set; } // 0x00000000 + public float VolumeIntensity { get; set; } + public float VolumeSizeScale { get; set; } + public byte VolumeOuterColorR { get; set; } + public byte VolumeOuterColorG { get; set; } + public byte VolumeOuterColorB { get; set; } + public byte LightHash { get; set; } + public float VolumeOuterIntensity { get; set; } + public float CoronaSize { get; set; } + public float VolumeOuterExponent { get; set; } + public byte LightFadeDistance { get; set; } + public byte ShadowFadeDistance { get; set; } + public byte SpecularFadeDistance { get; set; } + public byte VolumetricFadeDistance { get; set; } + public float ShadowNearClip { get; set; } + public float CoronaIntensity { get; set; } + public float CoronaZBias { get; set; } + public float DirectionX { get; set; } + public float DirectionY { get; set; } + public float DirectionZ { get; set; } + public float TangentX { get; set; } + public float TangentY { get; set; } + public float TangentZ { get; set; } + public float ConeInnerAngle { get; set; } + public float ConeOuterAngle { get; set; } + public float ExtentX { get; set; } + public float ExtentY { get; set; } + public float ExtentZ { get; set; } + public uint ProjectedTextureHash { get; set; } + public uint Unknown_A4h { get; set; } // 0x00000000 + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class DrawableBase : ResourceFileBase + { + public override long BlockLength + { + get { return 168; } + } + + // structure data + public ulong ShaderGroupPointer { get; set; } + public ulong SkeletonPointer { get; set; } + public SharpDX.Vector3 BoundingCenter { get; set; } + public float BoundingSphereRadius { get; set; } + public SharpDX.Vector4 BoundingBoxMin { get; set; } + public SharpDX.Vector4 BoundingBoxMax { get; set; } + public ulong DrawableModelsHighPointer { get; set; } + public ulong DrawableModelsMediumPointer { get; set; } + public ulong DrawableModelsLowPointer { get; set; } + public ulong DrawableModelsVeryLowPointer { get; set; } + public float Unknown_70h { get; set; } + public float Unknown_74h { get; set; } + public float Unknown_78h { get; set; } + public float Unknown_7Ch { get; set; } + public uint Unknown_80h { get; set; } + public uint Unknown_84h { get; set; } + public uint Unknown_88h { get; set; } + public uint Unknown_8Ch { get; set; } + public ulong JointsPointer { get; set; } + public uint Unknown_98h { get; set; } + public uint Unknown_9Ch { get; set; } // 0x00000000 + public ulong DrawableModelsXPointer { get; set; } + + // reference data + public ShaderGroup ShaderGroup { get; set; } + public Skeleton Skeleton { get; set; } + public ResourcePointerList64 DrawableModelsHigh { get; set; } + public ResourcePointerList64 DrawableModelsMedium { get; set; } + public ResourcePointerList64 DrawableModelsLow { get; set; } + public ResourcePointerList64 DrawableModelsVeryLow { get; set; } + public Joints Joints { get; set; } + public ResourcePointerList64 DrawableModelsX { get; set; } + + public DrawableModel[] AllModels { get; set; } + public Dictionary VertexDecls { get; set; } + + public object Owner { get; set; } + + public long MemoryUsage + { + get + { + long val = 0; + if (AllModels != null) + { + foreach(DrawableModel m in AllModels) + { + if (m != null) + { + val += m.MemoryUsage; + } + } + } + if ((ShaderGroup != null) && (ShaderGroup.TextureDictionary != null)) + { + val += ShaderGroup.TextureDictionary.MemoryUsage; + } + return val; + } + } + + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.ShaderGroupPointer = reader.ReadUInt64(); + this.SkeletonPointer = reader.ReadUInt64(); + this.BoundingCenter = reader.ReadStruct(); + this.BoundingSphereRadius = reader.ReadSingle(); + this.BoundingBoxMin = reader.ReadStruct(); + this.BoundingBoxMax = reader.ReadStruct(); + this.DrawableModelsHighPointer = reader.ReadUInt64(); + this.DrawableModelsMediumPointer = reader.ReadUInt64(); + this.DrawableModelsLowPointer = reader.ReadUInt64(); + this.DrawableModelsVeryLowPointer = reader.ReadUInt64(); + this.Unknown_70h = reader.ReadSingle(); + this.Unknown_74h = reader.ReadSingle(); + this.Unknown_78h = reader.ReadSingle(); + this.Unknown_7Ch = reader.ReadSingle(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + this.JointsPointer = reader.ReadUInt64(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.DrawableModelsXPointer = reader.ReadUInt64(); + + // read reference data + this.ShaderGroup = reader.ReadBlockAt( + this.ShaderGroupPointer // offset + ); + this.Skeleton = reader.ReadBlockAt( + this.SkeletonPointer // offset + ); + this.DrawableModelsHigh = reader.ReadBlockAt>( + this.DrawableModelsHighPointer // offset + ); + this.DrawableModelsMedium = reader.ReadBlockAt>( + this.DrawableModelsMediumPointer // offset + ); + this.DrawableModelsLow = reader.ReadBlockAt>( + this.DrawableModelsLowPointer // offset + ); + this.DrawableModelsVeryLow = reader.ReadBlockAt>( + this.DrawableModelsVeryLowPointer // offset + ); + this.Joints = reader.ReadBlockAt( + this.JointsPointer // offset + ); + this.DrawableModelsX = reader.ReadBlockAt>( + this.DrawableModelsXPointer // offset + ); + + + var allModels = new List(); + if (DrawableModelsHigh != null) allModels.AddRange(DrawableModelsHigh.data_items); + if (DrawableModelsMedium != null) allModels.AddRange(DrawableModelsMedium.data_items); + if (DrawableModelsLow != null) allModels.AddRange(DrawableModelsLow.data_items); + if (DrawableModelsVeryLow != null) allModels.AddRange(DrawableModelsVeryLow.data_items); + if ((DrawableModelsX != null) && (DrawableModelsX != DrawableModelsHigh)) + { + allModels.AddRange(DrawableModelsX.data_items); + } + AllModels = allModels.ToArray(); + + + var vds = new Dictionary(); + foreach (DrawableModel model in AllModels) + { + foreach (var geom in model.Geometries.data_items) + { + var info = geom.VertexBuffer.Info; + var declid = info.GetDeclarationId(); + + if (!vds.ContainsKey(declid)) + { + vds.Add(declid, info); + } + //else //debug test + //{ + // if ((VertexDecls[declid].Stride != info.Stride)||(VertexDecls[declid].Types != info.Types)) + // { + // } + //} + } + } + VertexDecls = new Dictionary(vds); + + AssignGeometryShaders(ShaderGroup); + } + + public void AssignGeometryShaders(ShaderGroup shaderGrp) + { + if (shaderGrp != null) + { + ShaderGroup = shaderGrp; + } + + //map the shaders to the geometries + if (ShaderGroup != null) + { + var shaders = ShaderGroup.Shaders.data_items; + foreach (DrawableModel model in AllModels) + { + if (model.Geometries == null) continue; + if (model.Geometries.data_items == null) continue; + if (model.ShaderMapping == null) continue; + + int geomcount = model.Geometries.data_items.Length; + for (int i = 0; i < geomcount; i++) + { + var geom = model.Geometries.data_items[i]; + ushort sid = (i < model.ShaderMapping.Length) ? model.ShaderMapping[i] : (ushort)0; + geom.Shader = (sid < shaders.Length) ? shaders[sid] : null; + } + } + } + else + { + } + + } + + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + this.ShaderGroupPointer = (ulong)(this.ShaderGroup != null ? this.ShaderGroup.FilePosition : 0); + this.SkeletonPointer = (ulong)(this.Skeleton != null ? this.Skeleton.FilePosition : 0); + this.DrawableModelsHighPointer = (ulong)(this.DrawableModelsHigh != null ? this.DrawableModelsHigh.FilePosition : 0); + this.DrawableModelsMediumPointer = (ulong)(this.DrawableModelsMedium != null ? this.DrawableModelsMedium.FilePosition : 0); + this.DrawableModelsLowPointer = (ulong)(this.DrawableModelsLow != null ? this.DrawableModelsLow.FilePosition : 0); + this.DrawableModelsVeryLowPointer = (ulong)(this.DrawableModelsVeryLow != null ? this.DrawableModelsVeryLow.FilePosition : 0); + this.JointsPointer = (ulong)(this.Joints != null ? this.Joints.FilePosition : 0); + this.DrawableModelsXPointer = (ulong)(this.DrawableModelsX != null ? this.DrawableModelsX.FilePosition : 0); + + // write structure data + writer.Write(this.ShaderGroupPointer); + writer.Write(this.SkeletonPointer); + //writer.WriteBlock(this.BoundingCenter); //TODO: fix! + writer.Write(this.BoundingSphereRadius); + //writer.WriteBlock(this.BoundingBoxMin); //TODO: fix! + //writer.WriteBlock(this.BoundingBoxMax); + writer.Write(this.DrawableModelsHighPointer); + writer.Write(this.DrawableModelsMediumPointer); + writer.Write(this.DrawableModelsLowPointer); + writer.Write(this.DrawableModelsVeryLowPointer); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + writer.Write(this.JointsPointer); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.DrawableModelsXPointer); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if (ShaderGroup != null) list.Add(ShaderGroup); + if (Skeleton != null) list.Add(Skeleton); + if (DrawableModelsHigh != null) list.Add(DrawableModelsHigh); + if (DrawableModelsMedium != null) list.Add(DrawableModelsMedium); + if (DrawableModelsLow != null) list.Add(DrawableModelsLow); + if (DrawableModelsVeryLow != null) list.Add(DrawableModelsVeryLow); + if (Joints != null) list.Add(Joints); + if (DrawableModelsX != null) list.Add(DrawableModelsX); + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Drawable : DrawableBase + { + public override long BlockLength + { + get { return 208; } + } + + // structure data + public ulong NamePointer { get; set; } + public ulong LightAttributesPointer { get; set; } + public ushort LightAttributesCount1 { get; set; } + public ushort LightAttributesCount2 { get; set; } + public uint Unknown_BCh { get; set; } // 0x00000000 + public uint Unknown_C0h { get; set; } // 0x00000000 + public uint Unknown_C4h { get; set; } // 0x00000000 + public ulong BoundPointer { get; set; } + + // reference data + public string Name { get; set; } + //public ResourceSimpleArray LightAttributes { get; set; } + public LightAttributes_s[] LightAttributes { get; set; } + public Bounds Bound { get; set; } + + public string ErrorMessage { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.NamePointer = reader.ReadUInt64(); + this.LightAttributesPointer = reader.ReadUInt64(); + this.LightAttributesCount1 = reader.ReadUInt16(); + this.LightAttributesCount2 = reader.ReadUInt16(); + this.Unknown_BCh = reader.ReadUInt32(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.BoundPointer = reader.ReadUInt64(); + + try + { + + // read reference data + this.Name = reader.ReadStringAt(//BlockAt( + this.NamePointer // offset + ); + //this.LightAttributes = reader.ReadBlockAt>( + // this.LightAttributesPointer, // offset + // this.LightAttributesCount1 + //); + this.LightAttributes = reader.ReadStructsAt(this.LightAttributesPointer, this.LightAttributesCount1); + + this.Bound = reader.ReadBlockAt( + this.BoundPointer // offset + ); + } + catch (Exception ex) //sometimes error here for loading particles! different drawable type? base only? + { + ErrorMessage = ex.ToString(); + } + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); //TODO: fix + //this.LightAttributesPointer = (ulong)(this.LightAttributes != null ? this.LightAttributes.Position : 0); + this.BoundPointer = (ulong)(this.Bound != null ? this.Bound.FilePosition : 0); + //TODO: fix + + // write structure data + writer.Write(this.NamePointer); + writer.Write(this.LightAttributesPointer); + writer.Write(this.LightAttributesCount1); + writer.Write(this.LightAttributesCount2); + writer.Write(this.Unknown_BCh); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.BoundPointer); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + //if (Name != null) list.Add(Name); //TODO: fix + //if (LightAttributes != null) list.Add(LightAttributes); //TODO: fix + if (Bound != null) list.Add(Bound); + return list.ToArray(); + } + + + public override string ToString() + { + return Name; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class DrawableBaseDictionary : ResourceFileBase + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + public ulong HashesPointer { get; set; } + public ushort HashesCount1 { get; set; } + public ushort HashesCount2 { get; set; } + public uint Unknown_2Ch { get; set; } + public ulong DrawablesPointer { get; set; } + public ushort DrawablesCount1 { get; set; } + public ushort DrawablesCount2 { get; set; } + public uint Unknown_3Ch { get; set; } + + // reference data + //public ResourceSimpleArray Hashes { get; set; } + public uint[] Hashes { get; set; } + public ResourcePointerArray64 Drawables { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.HashesPointer = reader.ReadUInt64(); + this.HashesCount1 = reader.ReadUInt16(); + this.HashesCount2 = reader.ReadUInt16(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.DrawablesPointer = reader.ReadUInt64(); + this.DrawablesCount1 = reader.ReadUInt16(); + this.DrawablesCount2 = reader.ReadUInt16(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + //this.Hashes = reader.ReadBlockAt>( + // this.HashesPointer, // offset + // this.HashesCount1 + //); + this.Hashes = reader.ReadUintsAt(this.HashesPointer, this.HashesCount1); + + this.Drawables = reader.ReadBlockAt>( + this.DrawablesPointer, // offset + this.DrawablesCount1 + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + //this.HashesPointer = (ulong)(this.Hashes != null ? this.Hashes.Position : 0); //TODO:: FIX THIS + // this.HashesCount1 = (ushort)(this.Hashes != null ? this.Hashes.Count : 0); + // this.HashesCount2 = (ushort)(this.Hashes != null ? this.Hashes.Count : 0); + this.DrawablesPointer = (ulong)(this.Drawables != null ? this.Drawables.FilePosition : 0); + // this.DrawablesCount1 = (ushort)(this.Drawables != null ? this.Drawables.Count : 0); + // this.DrawablesCount2 = (ushort)(this.Drawables != null ? this.Drawables.Count : 0); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.HashesPointer); + writer.Write(this.HashesCount1); + writer.Write(this.HashesCount2); + writer.Write(this.Unknown_2Ch); + writer.Write(this.DrawablesPointer); + writer.Write(this.DrawablesCount1); + writer.Write(this.DrawablesCount2); + writer.Write(this.Unknown_3Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + //if (Hashes != null) list.Add(Hashes); //TODO: fix + if (Drawables != null) list.Add(Drawables); + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class DrawableDictionary : ResourceFileBase + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000001 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong HashesPointer { get; set; } + public ushort HashesCount1 { get; set; } + public ushort HashesCount2 { get; set; } + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ulong DrawablesPointer { get; set; } + public ushort DrawablesCount1 { get; set; } + public ushort DrawablesCount2 { get; set; } + public uint Unknown_3Ch { get; set; } // 0x00000000 + + // reference data + //public ResourceSimpleArray Hashes { get; set; } + public uint[] Hashes { get; set; } + public ResourcePointerArray64 Drawables { get; set; } + + public long MemoryUsage + { + get + { + long val = 0; + if ((Drawables != null) && (Drawables.data_items != null)) + { + foreach(var drawable in Drawables.data_items) + { + val += drawable.MemoryUsage; + } + } + return val; + } + } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.HashesPointer = reader.ReadUInt64(); + this.HashesCount1 = reader.ReadUInt16(); + this.HashesCount2 = reader.ReadUInt16(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.DrawablesPointer = reader.ReadUInt64(); + this.DrawablesCount1 = reader.ReadUInt16(); + this.DrawablesCount2 = reader.ReadUInt16(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + //this.Hashes = reader.ReadBlockAt>( + // this.HashesPointer, // offset + // this.HashesCount1 + //); + this.Hashes = reader.ReadUintsAt(this.HashesPointer, this.HashesCount1); + + this.Drawables = reader.ReadBlockAt>( + this.DrawablesPointer, // offset + this.DrawablesCount1 + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + //this.HashesPointer = (ulong)(this.Hashes != null ? this.Hashes.Position : 0); //TODO: fix update this + // this.HashesCount1 = (ushort)(this.Hashes != null ? this.Hashes.Count : 0); + // this.HashesCount2 = (ushort)(this.Hashes != null ? this.Hashes.Count : 0); + this.DrawablesPointer = (ulong)(this.Drawables != null ? this.Drawables.FilePosition : 0); + // this.DrawablesCount1 = (ushort)(this.Drawables != null ? this.Drawables.Count : 0); + // this.DrawablesCount2 = (ushort)(this.Drawables != null ? this.Drawables.Count : 0); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.HashesPointer); + writer.Write(this.HashesCount1); + writer.Write(this.HashesCount2); + writer.Write(this.Unknown_2Ch); + writer.Write(this.DrawablesPointer); + writer.Write(this.DrawablesCount1); + writer.Write(this.DrawablesCount2); + writer.Write(this.Unknown_3Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + //if (Hashes != null) list.Add(Hashes); //TODO: fix + if (Drawables != null) list.Add(Drawables); + return list.ToArray(); + } + } + + +} diff --git a/GameFiles/Resources/Frag.cs b/GameFiles/Resources/Frag.cs new file mode 100644 index 0000000..a8ddf04 --- /dev/null +++ b/GameFiles/Resources/Frag.cs @@ -0,0 +1,3742 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen and mangled + + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +namespace CodeWalker.GameFiles +{ + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragType : ResourceFileBase + { + public override long BlockLength + { + get { return 304; } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + public ulong DrawablePointer { get; set; } + public ulong Unknown_28h_Pointer { get; set; } + public ulong Unknown_30h_Pointer { get; set; } + public uint Count0 { get; set; } + public uint Unknown_4Ch { get; set; } + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public ulong NamePointer { get; set; } + public ResourcePointerList64 Clothes { get; set; } + public uint Unknown_70h { get; set; } // 0x00000000 + public uint Unknown_74h { get; set; } // 0x00000000 + public uint Unknown_78h { get; set; } // 0x00000000 + public uint Unknown_7Ch { get; set; } // 0x00000000 + public uint Unknown_80h { get; set; } // 0x00000000 + public uint Unknown_84h { get; set; } // 0x00000000 + public uint Unknown_88h { get; set; } // 0x00000000 + public uint Unknown_8Ch { get; set; } // 0x00000000 + public uint Unknown_90h { get; set; } // 0x00000000 + public uint Unknown_94h { get; set; } // 0x00000000 + public uint Unknown_98h { get; set; } // 0x00000000 + public uint Unknown_9Ch { get; set; } // 0x00000000 + public uint Unknown_A0h { get; set; } // 0x00000000 + public uint Unknown_A4h { get; set; } // 0x00000000 + public ulong Unknown_A8h_Pointer { get; set; } + public uint Unknown_B0h { get; set; } // 0x00000000 + public uint Unknown_B4h { get; set; } // 0x00000000 + public uint Unknown_B8h { get; set; } + public uint Unknown_BCh { get; set; } + public uint Unknown_C0h { get; set; } + public uint Unknown_C4h { get; set; } + public uint Unknown_C8h { get; set; } + public uint Unknown_CCh { get; set; } + public uint Unknown_D0h { get; set; } + public uint Unknown_D4h { get; set; } + public byte Unknown_D8h { get; set; } + public byte Count3 { get; set; } + public ushort Unknown_DAh { get; set; } + public uint Unknown_DCh { get; set; } // 0x00000000 + public ulong Unknown_E0h_Pointer { get; set; } + public uint Unknown_E8h { get; set; } // 0x00000000 + public uint Unknown_ECh { get; set; } // 0x00000000 + public ulong PhysicsLODGroupPointer { get; set; } + public ulong Unknown_F8h_Pointer { get; set; } + public uint Unknown_100h { get; set; } // 0x00000000 + public uint Unknown_104h { get; set; } // 0x00000000 + public uint Unknown_108h { get; set; } // 0x00000000 + public uint Unknown_10Ch { get; set; } // 0x00000000 + //public ResourceSimpleList64 LightAttributes { get; set; } + public ResourceSimpleList64Ptr LightAttributesPtr { get; set; } + public LightAttributes_s[] LightAttributes { get; set; } + public ulong Unknown_120h_Pointer { get; set; } + public uint Unknown_128h { get; set; } // 0x00000000 + public uint Unknown_12Ch { get; set; } // 0x00000000 + + // reference data + public FragDrawable Drawable { get; set; } + public ResourcePointerArray64 Unknown_28h_Data { get; set; } + public ResourcePointerArray64 Unknown_30h_Data { get; set; } + public string Name { get; set; } + public FragUnknown_F_004 Unknown_A8h_Data { get; set; } + public ResourcePointerArray64 Unknown_E0h_Data { get; set; } + public FragPhysicsLODGroup PhysicsLODGroup { get; set; } + public FragDrawable Unknown_F8h_Data { get; set; } + public FragUnknown_F_003 Unknown_120h_Data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.DrawablePointer = reader.ReadUInt64(); + this.Unknown_28h_Pointer = reader.ReadUInt64(); + this.Unknown_30h_Pointer = reader.ReadUInt64(); + this.Count0 = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + this.Clothes = reader.ReadBlock>(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.Unknown_A0h = reader.ReadUInt32(); + this.Unknown_A4h = reader.ReadUInt32(); + this.Unknown_A8h_Pointer = reader.ReadUInt64(); + this.Unknown_B0h = reader.ReadUInt32(); + this.Unknown_B4h = reader.ReadUInt32(); + this.Unknown_B8h = reader.ReadUInt32(); + this.Unknown_BCh = reader.ReadUInt32(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.Unknown_C8h = reader.ReadUInt32(); + this.Unknown_CCh = reader.ReadUInt32(); + this.Unknown_D0h = reader.ReadUInt32(); + this.Unknown_D4h = reader.ReadUInt32(); + this.Unknown_D8h = reader.ReadByte(); + this.Count3 = reader.ReadByte(); + this.Unknown_DAh = reader.ReadUInt16(); + this.Unknown_DCh = reader.ReadUInt32(); + this.Unknown_E0h_Pointer = reader.ReadUInt64(); + this.Unknown_E8h = reader.ReadUInt32(); + this.Unknown_ECh = reader.ReadUInt32(); + this.PhysicsLODGroupPointer = reader.ReadUInt64(); + this.Unknown_F8h_Pointer = reader.ReadUInt64(); + this.Unknown_100h = reader.ReadUInt32(); + this.Unknown_104h = reader.ReadUInt32(); + this.Unknown_108h = reader.ReadUInt32(); + this.Unknown_10Ch = reader.ReadUInt32(); + //this.LightAttributes = reader.ReadBlock>(); + this.LightAttributesPtr = reader.ReadStruct(); + this.LightAttributes = reader.ReadStructsAt(LightAttributesPtr.EntriesPointer, LightAttributesPtr.EntriesCount); + this.Unknown_120h_Pointer = reader.ReadUInt64(); + this.Unknown_128h = reader.ReadUInt32(); + this.Unknown_12Ch = reader.ReadUInt32(); + + // read reference data + this.Drawable = reader.ReadBlockAt( + this.DrawablePointer // offset + ); + if (this.Drawable != null) + { + this.Drawable.OwnerFragment = this; + } + + this.Unknown_28h_Data = reader.ReadBlockAt>( + this.Unknown_28h_Pointer, // offset + this.Count0 + ); + if ((this.Unknown_28h_Data != null) && (this.Unknown_28h_Data.data_items != null)) + { + for (int i = 0; i < this.Unknown_28h_Data.data_items.Length; i++) + { + var drwbl = Unknown_28h_Data.data_items[i]; + if (drwbl != null) + { + drwbl.OwnerFragment = this; + } + } + } + this.Unknown_30h_Data = reader.ReadBlockAt>( + this.Unknown_30h_Pointer, // offset + this.Count0 + ); + this.Name = reader.ReadStringAt(//BlockAt( + this.NamePointer // offset + ); + this.Unknown_A8h_Data = reader.ReadBlockAt( + this.Unknown_A8h_Pointer // offset + ); + this.Unknown_E0h_Data = reader.ReadBlockAt>( + this.Unknown_E0h_Pointer, // offset + this.Count3 + ); + this.PhysicsLODGroup = reader.ReadBlockAt( + this.PhysicsLODGroupPointer // offset + ); + this.Unknown_F8h_Data = reader.ReadBlockAt( + this.Unknown_F8h_Pointer // offset + ); + if (this.Unknown_F8h_Data != null) + { + this.Unknown_F8h_Data.OwnerFragment = this; + } + + this.Unknown_120h_Data = reader.ReadBlockAt( + this.Unknown_120h_Pointer // offset + ); + + + + + //for vehicle wheels, the shaderGroup in the model seems to be missing, but have to use the main drawable's shaders. + if ((Drawable != null) && (PhysicsLODGroup != null) && (PhysicsLODGroup.PhysicsLOD1 != null)) + { + var pl1 = PhysicsLODGroup.PhysicsLOD1; + if ((pl1.Children != null) && (pl1.Children.data_items != null)) + { + for (int i = 0; i < pl1.Children.data_items.Length; i++) + { + var pch = pl1.Children.data_items[i]; + if ((pch.Drawable1 != null)) + { + pch.Drawable1.AssignGeometryShaders(Drawable.ShaderGroup); + } + } + } + } + + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + this.DrawablePointer = (ulong)(this.Drawable != null ? this.Drawable.FilePosition : 0); + this.Unknown_28h_Pointer = (ulong)(this.Unknown_28h_Data != null ? this.Unknown_28h_Data.FilePosition : 0); + this.Unknown_30h_Pointer = (ulong)(this.Unknown_30h_Data != null ? this.Unknown_30h_Data.FilePosition : 0); + //this.cc00 = (uint)(this.pxxxxx_0data != null ? this.pxxxxx_0data.Count : 0); + ////this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); //TODO: fix!!! + //this.cnt1 = (ushort)(this.pxxxxx_2data != null ? this.pxxxxx_2data.Count : 0); + this.Unknown_A8h_Pointer = (ulong)(this.Unknown_A8h_Data != null ? this.Unknown_A8h_Data.FilePosition : 0); + //this.anotherCount = (byte)(this.pxxxxx_3data != null ? this.pxxxxx_3data.Count : 0); + this.Unknown_E0h_Pointer = (ulong)(this.Unknown_E0h_Data != null ? this.Unknown_E0h_Data.FilePosition : 0); + this.PhysicsLODGroupPointer = (ulong)(this.PhysicsLODGroup != null ? this.PhysicsLODGroup.FilePosition : 0); + this.Unknown_F8h_Pointer = (ulong)(this.Unknown_F8h_Data != null ? this.Unknown_F8h_Data.FilePosition : 0); + //this.cntxx51a = (ushort)(this.pxxxxx_5data != null ? this.pxxxxx_5data.Count : 0); + this.Unknown_120h_Pointer = (ulong)(this.Unknown_120h_Data != null ? this.Unknown_120h_Data.FilePosition : 0); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.DrawablePointer); + writer.Write(this.Unknown_28h_Pointer); + writer.Write(this.Unknown_30h_Pointer); + writer.Write(this.Count0); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.NamePointer); + writer.WriteBlock(this.Clothes); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.Unknown_A0h); + writer.Write(this.Unknown_A4h); + writer.Write(this.Unknown_A8h_Pointer); + writer.Write(this.Unknown_B0h); + writer.Write(this.Unknown_B4h); + writer.Write(this.Unknown_B8h); + writer.Write(this.Unknown_BCh); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.Unknown_C8h); + writer.Write(this.Unknown_CCh); + writer.Write(this.Unknown_D0h); + writer.Write(this.Unknown_D4h); + writer.Write(this.Unknown_D8h); + writer.Write(this.Count3); + writer.Write(this.Unknown_DAh); + writer.Write(this.Unknown_DCh); + writer.Write(this.Unknown_E0h_Pointer); + writer.Write(this.Unknown_E8h); + writer.Write(this.Unknown_ECh); + writer.Write(this.PhysicsLODGroupPointer); + writer.Write(this.Unknown_F8h_Pointer); + writer.Write(this.Unknown_100h); + writer.Write(this.Unknown_104h); + writer.Write(this.Unknown_108h); + writer.Write(this.Unknown_10Ch); + //writer.WriteBlock(this.LightAttributes); //TODO: fix! + writer.Write(this.Unknown_120h_Pointer); + writer.Write(this.Unknown_128h); + writer.Write(this.Unknown_12Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if (Drawable != null) list.Add(Drawable); + if (Unknown_28h_Data != null) list.Add(Unknown_28h_Data); + if (Unknown_30h_Data != null) list.Add(Unknown_30h_Data); + //if (Name != null) list.Add(Name); //TODO: fix! + if (Unknown_A8h_Data != null) list.Add(Unknown_A8h_Data); + if (Unknown_E0h_Data != null) list.Add(Unknown_E0h_Data); + if (PhysicsLODGroup != null) list.Add(PhysicsLODGroup); + if (Unknown_F8h_Data != null) list.Add(Unknown_F8h_Data); + if (Unknown_120h_Data != null) list.Add(Unknown_120h_Data); + return list.ToArray(); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0x60, Clothes), + //new Tuple(0x110, LightAttributes) //TODO: fix! + }; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragCloth : ResourceSystemBlock + { + public override long BlockLength + { + get { return 128; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public ulong InstanceTuningPointer { get; set; } + public ulong DrawablePointer { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public ulong ControllerPointer { get; set; } + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + public ulong pxxxxx_2 { get; set; } + public ushort cntxx51a { get; set; } + public ushort cntxx51b { get; set; } + public uint Unknown_6Ch { get; set; } // 0x00000000 + public uint Unknown_70h { get; set; } // 0x00000000 + public uint Unknown_74h { get; set; } // 0x00000000 + public uint Unknown_78h { get; set; } + public uint Unknown_7Ch { get; set; } // 0x00000000 + + // reference data + public FragClothInstanceTuning InstanceTuning { get; set; } + public FragDrawable Drawable { get; set; } + public FragClothController Controller { get; set; } + public uint[] pxxxxx_2data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.InstanceTuningPointer = reader.ReadUInt64(); + this.DrawablePointer = reader.ReadUInt64(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.ControllerPointer = reader.ReadUInt64(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.pxxxxx_2 = reader.ReadUInt64(); + this.cntxx51a = reader.ReadUInt16(); + this.cntxx51b = reader.ReadUInt16(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + + // read reference data + this.InstanceTuning = reader.ReadBlockAt( + this.InstanceTuningPointer // offset + ); + this.Drawable = reader.ReadBlockAt( + this.DrawablePointer // offset + ); + if (this.Drawable != null) + { + this.Drawable.OwnerFragmentCloth = this; + } + + this.Controller = reader.ReadBlockAt( + this.ControllerPointer // offset + ); + //this.pxxxxx_2data = reader.ReadBlockAt>( + // this.pxxxxx_2, // offset + // this.cntxx51a + //); + this.pxxxxx_2data = reader.ReadUintsAt(this.pxxxxx_2, this.cntxx51a); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.InstanceTuningPointer = (ulong)(this.InstanceTuning != null ? this.InstanceTuning.FilePosition : 0); + this.DrawablePointer = (ulong)(this.Drawable != null ? this.Drawable.FilePosition : 0); + this.ControllerPointer = (ulong)(this.Controller != null ? this.Controller.FilePosition : 0); + //this.pxxxxx_2 = (ulong)(this.pxxxxx_2data != null ? this.pxxxxx_2data.Position : 0); //TODO: fix + //this.cntxx51a = (ushort)(this.pxxxxx_2data != null ? this.pxxxxx_2data.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.InstanceTuningPointer); + writer.Write(this.DrawablePointer); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.ControllerPointer); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.pxxxxx_2); + writer.Write(this.cntxx51a); + writer.Write(this.cntxx51b); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (InstanceTuning != null) list.Add(InstanceTuning); + if (Drawable != null) list.Add(Drawable); + if (Controller != null) list.Add(Controller); + //if (pxxxxx_2data != null) list.Add(pxxxxx_2data); //TODO: fix + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragClothInstanceTuning : ResourceSystemBlock + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // float + public uint Unknown_14h { get; set; } + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } // float + public uint Unknown_2Ch { get; set; } + public uint Unknown_30h { get; set; } // no float + public uint Unknown_34h { get; set; } // float + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragClothController : ResourceSystemBlock + { + public override long BlockLength + { + get { return 128; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public ulong BridgeSimGfxPointer { get; set; } // pointer + public ulong MorphControllerPointer { get; set; } // pointer + public ulong VerletCloth1Pointer { get; set; } // pointer + public ulong VerletCloth2Pointer { get; set; } // pointer + public ulong VerletCloth3Pointer { get; set; } // pointer + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public uint Unknown_50h { get; set; } // 0x00000003 + public uint Unknown_54h { get; set; } // 0x00000000 + public uint Unknown_58h { get; set; } // no float + public uint Unknown_5Ch { get; set; } // no float + public uint Unknown_60h { get; set; } // no float + public uint Unknown_64h { get; set; } // no float + public uint Unknown_68h { get; set; } // no float + public uint Unknown_6Ch { get; set; } // no float + public uint Unknown_70h { get; set; } // no float + public uint Unknown_74h { get; set; } // 0x00000000 + public uint Unknown_78h { get; set; } // 0x00000000 + public uint Unknown_7Ch { get; set; } // 0x00000000 + + // reference data + public FragClothBridgeSimGfx BridgeSimGfx { get; set; } + public FragClothMorphController MorphController { get; set; } + public FragClothVerletCloth VerletCloth1 { get; set; } + public FragClothVerletCloth VerletCloth2 { get; set; } + public FragClothVerletCloth VerletCloth3 { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.BridgeSimGfxPointer = reader.ReadUInt64(); + this.MorphControllerPointer = reader.ReadUInt64(); + this.VerletCloth1Pointer = reader.ReadUInt64(); + this.VerletCloth2Pointer = reader.ReadUInt64(); + this.VerletCloth3Pointer = reader.ReadUInt64(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + + // read reference data + this.BridgeSimGfx = reader.ReadBlockAt( + this.BridgeSimGfxPointer // offset + ); + this.MorphController = reader.ReadBlockAt( + this.MorphControllerPointer // offset + ); + this.VerletCloth1 = reader.ReadBlockAt( + this.VerletCloth1Pointer // offset + ); + this.VerletCloth2 = reader.ReadBlockAt( + this.VerletCloth2Pointer // offset + ); + this.VerletCloth3 = reader.ReadBlockAt( + this.VerletCloth3Pointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.BridgeSimGfxPointer = (ulong)(this.BridgeSimGfx != null ? this.BridgeSimGfx.FilePosition : 0); + this.MorphControllerPointer = (ulong)(this.MorphController != null ? this.MorphController.FilePosition : 0); + this.VerletCloth1Pointer = (ulong)(this.VerletCloth1 != null ? this.VerletCloth1.FilePosition : 0); + this.VerletCloth2Pointer = (ulong)(this.VerletCloth2 != null ? this.VerletCloth2.FilePosition : 0); + this.VerletCloth3Pointer = (ulong)(this.VerletCloth3 != null ? this.VerletCloth3.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.BridgeSimGfxPointer); + writer.Write(this.MorphControllerPointer); + writer.Write(this.VerletCloth1Pointer); + writer.Write(this.VerletCloth2Pointer); + writer.Write(this.VerletCloth3Pointer); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (BridgeSimGfx != null) list.Add(BridgeSimGfx); + if (MorphController != null) list.Add(MorphController); + if (VerletCloth1 != null) list.Add(VerletCloth1); + if (VerletCloth2 != null) list.Add(VerletCloth2); + if (VerletCloth3 != null) list.Add(VerletCloth3); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragClothBridgeSimGfx : ResourceSystemBlock + { + public override long BlockLength + { + get { return 320; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_20h { get; set; } + //public ResourceSimpleList64 Unknown_30h { get; set; } + //public ResourceSimpleList64 Unknown_40h { get; set; } + public ResourceSimpleList64Ptr Unknown_20hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_30hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_40hPtr { get; set; } + public float[] Unknown_20h { get; set; } + public float[] Unknown_30h { get; set; } + public float[] Unknown_40h { get; set; } + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_60h { get; set; } + //public ResourceSimpleList64 Unknown_70h { get; set; } + //public ResourceSimpleList64 Unknown_80h { get; set; } + public ResourceSimpleList64Ptr Unknown_60hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_70hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_80hPtr { get; set; } + public float[] Unknown_60h { get; set; } + public uint[] Unknown_70h { get; set; } + public uint[] Unknown_80h { get; set; } + public uint Unknown_90h { get; set; } // 0x00000000 + public uint Unknown_94h { get; set; } // 0x00000000 + public uint Unknown_98h { get; set; } // 0x00000000 + public uint Unknown_9Ch { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_A0h { get; set; } + //public ResourceSimpleList64 Unknown_B0h { get; set; } + //public ResourceSimpleList64 Unknown_C0h { get; set; } + public ResourceSimpleList64Ptr Unknown_A0hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_B0hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_C0hPtr { get; set; } + public float[] Unknown_A0h { get; set; } + public uint[] Unknown_B0h { get; set; } + public uint[] Unknown_C0h { get; set; } + public uint Unknown_D0h { get; set; } // 0x00000000 + public uint Unknown_D4h { get; set; } // 0x00000000 + public uint Unknown_D8h { get; set; } // 0x00000000 + public uint Unknown_DCh { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_E0h { get; set; } + //public ResourceSimpleList64 Unknown_F0h { get; set; } + //public ResourceSimpleList64 Unknown_100h { get; set; } + public ResourceSimpleList64Ptr Unknown_E0hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_F0hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_100hPtr { get; set; } + public ushort[] Unknown_E0h { get; set; } + public ushort[] Unknown_F0h { get; set; } + public ushort[] Unknown_100h { get; set; } + public uint Unknown_110h { get; set; } // 0x00000000 + public uint Unknown_114h { get; set; } // 0x00000000 + public uint Unknown_118h { get; set; } // 0x00000000 + public uint Unknown_11Ch { get; set; } // 0x00000000 + public uint Unknown_120h { get; set; } // 0x00000000 + public uint Unknown_124h { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_128h { get; set; } + public ResourceSimpleList64Ptr Unknown_128hPtr { get; set; } + public uint[] Unknown_128h { get; set; } + public uint Unknown_138h { get; set; } // 0x00000000 + public uint Unknown_13Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20hPtr = reader.ReadStruct(); + this.Unknown_30hPtr = reader.ReadStruct(); + this.Unknown_40hPtr = reader.ReadStruct(); + this.Unknown_20h = reader.ReadFloatsAt(Unknown_20hPtr.EntriesPointer, Unknown_20hPtr.EntriesCount); + this.Unknown_30h = reader.ReadFloatsAt(Unknown_30hPtr.EntriesPointer, Unknown_30hPtr.EntriesCount); + this.Unknown_40h = reader.ReadFloatsAt(Unknown_40hPtr.EntriesPointer, Unknown_40hPtr.EntriesCount); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60hPtr = reader.ReadStruct(); + this.Unknown_70hPtr = reader.ReadStruct(); + this.Unknown_80hPtr = reader.ReadStruct(); + this.Unknown_60h = reader.ReadFloatsAt(Unknown_60hPtr.EntriesPointer, Unknown_60hPtr.EntriesCount); + this.Unknown_70h = reader.ReadUintsAt(Unknown_70hPtr.EntriesPointer, Unknown_70hPtr.EntriesCount); + this.Unknown_80h = reader.ReadUintsAt(Unknown_80hPtr.EntriesPointer, Unknown_80hPtr.EntriesCount); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.Unknown_A0hPtr = reader.ReadStruct(); + this.Unknown_B0hPtr = reader.ReadStruct(); + this.Unknown_C0hPtr = reader.ReadStruct(); + this.Unknown_A0h = reader.ReadFloatsAt(Unknown_A0hPtr.EntriesPointer, Unknown_A0hPtr.EntriesCount); + this.Unknown_B0h = reader.ReadUintsAt(Unknown_B0hPtr.EntriesPointer, Unknown_B0hPtr.EntriesCount); + this.Unknown_C0h = reader.ReadUintsAt(Unknown_C0hPtr.EntriesPointer, Unknown_C0hPtr.EntriesCount); + this.Unknown_D0h = reader.ReadUInt32(); + this.Unknown_D4h = reader.ReadUInt32(); + this.Unknown_D8h = reader.ReadUInt32(); + this.Unknown_DCh = reader.ReadUInt32(); + this.Unknown_E0hPtr = reader.ReadStruct(); + this.Unknown_F0hPtr = reader.ReadStruct(); + this.Unknown_100hPtr = reader.ReadStruct(); + this.Unknown_E0h = reader.ReadUshortsAt(Unknown_E0hPtr.EntriesPointer, Unknown_E0hPtr.EntriesCount); + this.Unknown_F0h = reader.ReadUshortsAt(Unknown_F0hPtr.EntriesPointer, Unknown_F0hPtr.EntriesCount); + this.Unknown_100h = reader.ReadUshortsAt(Unknown_100hPtr.EntriesPointer, Unknown_100hPtr.EntriesCount); + this.Unknown_110h = reader.ReadUInt32(); + this.Unknown_114h = reader.ReadUInt32(); + this.Unknown_118h = reader.ReadUInt32(); + this.Unknown_11Ch = reader.ReadUInt32(); + this.Unknown_120h = reader.ReadUInt32(); + this.Unknown_124h = reader.ReadUInt32(); + this.Unknown_128hPtr = reader.ReadStruct(); + this.Unknown_128h = reader.ReadUintsAt(Unknown_128hPtr.EntriesPointer, Unknown_128hPtr.EntriesCount); + this.Unknown_138h = reader.ReadUInt32(); + this.Unknown_13Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + //writer.WriteBlock(this.Unknown_20h); //TODO: fix! + //writer.WriteBlock(this.Unknown_30h); + //writer.WriteBlock(this.Unknown_40h); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + //writer.WriteBlock(this.Unknown_60h); + //writer.WriteBlock(this.Unknown_70h); + //writer.WriteBlock(this.Unknown_80h); + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + //writer.WriteBlock(this.Unknown_A0h); + //writer.WriteBlock(this.Unknown_B0h); + //writer.WriteBlock(this.Unknown_C0h); + writer.Write(this.Unknown_D0h); + writer.Write(this.Unknown_D4h); + writer.Write(this.Unknown_D8h); + writer.Write(this.Unknown_DCh); + //writer.WriteBlock(this.Unknown_E0h); + //writer.WriteBlock(this.Unknown_F0h); + //writer.WriteBlock(this.Unknown_100h); + writer.Write(this.Unknown_110h); + writer.Write(this.Unknown_114h); + writer.Write(this.Unknown_118h); + writer.Write(this.Unknown_11Ch); + writer.Write(this.Unknown_120h); + writer.Write(this.Unknown_124h); + //writer.WriteBlock(this.Unknown_128h); + writer.Write(this.Unknown_138h); + writer.Write(this.Unknown_13Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(0x20, Unknown_20h), //TODO: fix! + //new Tuple(0x30, Unknown_30h), + //new Tuple(0x40, Unknown_40h), + //new Tuple(0x60, Unknown_60h), + //new Tuple(0x70, Unknown_70h), + //new Tuple(0x80, Unknown_80h), + //new Tuple(0xA0, Unknown_A0h), + //new Tuple(0xB0, Unknown_B0h), + //new Tuple(0xC0, Unknown_C0h), + //new Tuple(0xE0, Unknown_E0h), + //new Tuple(0xF0, Unknown_F0h), + //new Tuple(0x100, Unknown_100h), + //new Tuple(0x128, Unknown_128h) + }; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragClothMorphController : ResourceSystemBlock + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong Unknown_18h_Pointer { get; set; } + public ulong Unknown_20h_Pointer { get; set; } + public ulong Unknown_28h_Pointer { get; set; } + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + // reference data + public FragClothUnknown_F_007 Unknown_18h_Data { get; set; } + public FragClothUnknown_F_007 Unknown_20h_Data { get; set; } + public FragClothUnknown_F_007 Unknown_28h_Data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h_Pointer = reader.ReadUInt64(); + this.Unknown_20h_Pointer = reader.ReadUInt64(); + this.Unknown_28h_Pointer = reader.ReadUInt64(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + this.Unknown_18h_Data = reader.ReadBlockAt( + this.Unknown_18h_Pointer // offset + ); + this.Unknown_20h_Data = reader.ReadBlockAt( + this.Unknown_20h_Pointer // offset + ); + this.Unknown_28h_Data = reader.ReadBlockAt( + this.Unknown_28h_Pointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.Unknown_18h_Pointer = (ulong)(this.Unknown_18h_Data != null ? this.Unknown_18h_Data.FilePosition : 0); + this.Unknown_20h_Pointer = (ulong)(this.Unknown_20h_Data != null ? this.Unknown_20h_Data.FilePosition : 0); + this.Unknown_28h_Pointer = (ulong)(this.Unknown_28h_Data != null ? this.Unknown_28h_Data.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h_Pointer); + writer.Write(this.Unknown_20h_Pointer); + writer.Write(this.Unknown_28h_Pointer); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Unknown_18h_Data != null) list.Add(Unknown_18h_Data); + if (Unknown_20h_Data != null) list.Add(Unknown_20h_Data); + if (Unknown_28h_Data != null) list.Add(Unknown_28h_Data); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragClothUnknown_F_007 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 400; } + } + + // structure data + public uint Unknown_00h { get; set; } // 0x00000000 + public uint Unknown_04h { get; set; } // 0x00000000 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_50h { get; set; } + //public ResourceSimpleList64 Unknown_60h { get; set; } + //public ResourceSimpleList64 Unknown_70h { get; set; } + //public ResourceSimpleList64 Unknown_80h { get; set; } + //public ResourceSimpleList64 Unknown_90h { get; set; } + //public ResourceSimpleList64 Unknown_A0h { get; set; } + //public ResourceSimpleList64 Unknown_B0h { get; set; } + //public ResourceSimpleList64 Unknown_C0h { get; set; } + //public ResourceSimpleList64 Unknown_D0h { get; set; } + //public ResourceSimpleList64 Unknown_E0h { get; set; } + public ResourceSimpleList64Ptr Unknown_50hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_60hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_70hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_80hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_90hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_A0hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_B0hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_C0hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_D0hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_E0hPtr { get; set; } + public SharpDX.Vector4[] Unknown_50h { get; set; } + public ushort[] Unknown_60h { get; set; } + public ushort[] Unknown_70h { get; set; } + public ushort[] Unknown_80h { get; set; } + public ushort[] Unknown_90h { get; set; } + public SharpDX.Vector4[] Unknown_A0h { get; set; } + public ushort[] Unknown_B0h { get; set; } + public ushort[] Unknown_C0h { get; set; } + public ushort[] Unknown_D0h { get; set; } + public ushort[] Unknown_E0h { get; set; } + public uint Unknown_F0h { get; set; } // 0x00000000 + public uint Unknown_F4h { get; set; } // 0x00000000 + public uint Unknown_F8h { get; set; } // 0x00000000 + public uint Unknown_FCh { get; set; } // 0x00000000 + public uint Unknown_100h { get; set; } // 0x00000000 + public uint Unknown_104h { get; set; } // 0x00000000 + public uint Unknown_108h { get; set; } // 0x00000000 + public uint Unknown_10Ch { get; set; } // 0x00000000 + public uint Unknown_110h { get; set; } // 0x00000000 + public uint Unknown_114h { get; set; } // 0x00000000 + public uint Unknown_118h { get; set; } // 0x00000000 + public uint Unknown_11Ch { get; set; } // 0x00000000 + public uint Unknown_120h { get; set; } // 0x00000000 + public uint Unknown_124h { get; set; } // 0x00000000 + public uint Unknown_128h { get; set; } // 0x00000000 + public uint Unknown_12Ch { get; set; } // 0x00000000 + public uint Unknown_130h { get; set; } // 0x00000000 + public uint Unknown_134h { get; set; } // 0x00000000 + public uint Unknown_138h { get; set; } // 0x00000000 + public uint Unknown_13Ch { get; set; } // 0x00000000 + public uint Unknown_140h { get; set; } // 0x00000000 + public uint Unknown_144h { get; set; } // 0x00000000 + public uint Unknown_148h { get; set; } // 0x00000000 + public uint Unknown_14Ch { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_150h { get; set; } + //public ResourceSimpleList64 Unknown_160h { get; set; } + public ResourceSimpleList64Ptr Unknown_150hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_160hPtr { get; set; } + public ushort[] Unknown_150h { get; set; } + public ushort[] Unknown_160h { get; set; } + public uint Unknown_170h { get; set; } // 0x00000000 + public uint Unknown_174h { get; set; } // 0x00000000 + public uint Unknown_178h { get; set; } // 0x00000000 + public uint Unknown_17Ch { get; set; } // 0x00000000 + public uint Unknown_180h { get; set; } + public uint Unknown_184h { get; set; } // 0x00000000 + public uint Unknown_188h { get; set; } // 0x00000000 + public uint Unknown_18Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_00h = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + //this.Unknown_50h = reader.ReadBlock>(); + //this.Unknown_60h = reader.ReadBlock>(); + //this.Unknown_70h = reader.ReadBlock>(); + //this.Unknown_80h = reader.ReadBlock>(); + //this.Unknown_90h = reader.ReadBlock>(); + //this.Unknown_A0h = reader.ReadBlock>(); + //this.Unknown_B0h = reader.ReadBlock>(); + //this.Unknown_C0h = reader.ReadBlock>(); + //this.Unknown_D0h = reader.ReadBlock>(); + //this.Unknown_E0h = reader.ReadBlock>(); + this.Unknown_50hPtr = reader.ReadStruct(); + this.Unknown_60hPtr = reader.ReadStruct(); + this.Unknown_70hPtr = reader.ReadStruct(); + this.Unknown_80hPtr = reader.ReadStruct(); + this.Unknown_90hPtr = reader.ReadStruct(); + this.Unknown_A0hPtr = reader.ReadStruct(); + this.Unknown_B0hPtr = reader.ReadStruct(); + this.Unknown_C0hPtr = reader.ReadStruct(); + this.Unknown_D0hPtr = reader.ReadStruct(); + this.Unknown_E0hPtr = reader.ReadStruct(); + this.Unknown_50h = reader.ReadStructsAt(Unknown_50hPtr.EntriesPointer, Unknown_50hPtr.EntriesCount); + this.Unknown_60h = reader.ReadUshortsAt(Unknown_60hPtr.EntriesPointer, Unknown_60hPtr.EntriesCount); + this.Unknown_70h = reader.ReadUshortsAt(Unknown_70hPtr.EntriesPointer, Unknown_70hPtr.EntriesCount); + this.Unknown_80h = reader.ReadUshortsAt(Unknown_80hPtr.EntriesPointer, Unknown_80hPtr.EntriesCount); + this.Unknown_90h = reader.ReadUshortsAt(Unknown_90hPtr.EntriesPointer, Unknown_90hPtr.EntriesCount); + this.Unknown_A0h = reader.ReadStructsAt(Unknown_A0hPtr.EntriesPointer, Unknown_A0hPtr.EntriesCount); + this.Unknown_B0h = reader.ReadUshortsAt(Unknown_B0hPtr.EntriesPointer, Unknown_B0hPtr.EntriesCount); + this.Unknown_C0h = reader.ReadUshortsAt(Unknown_C0hPtr.EntriesPointer, Unknown_C0hPtr.EntriesCount); + this.Unknown_D0h = reader.ReadUshortsAt(Unknown_D0hPtr.EntriesPointer, Unknown_D0hPtr.EntriesCount); + this.Unknown_E0h = reader.ReadUshortsAt(Unknown_E0hPtr.EntriesPointer, Unknown_E0hPtr.EntriesCount); + this.Unknown_F0h = reader.ReadUInt32(); + this.Unknown_F4h = reader.ReadUInt32(); + this.Unknown_F8h = reader.ReadUInt32(); + this.Unknown_FCh = reader.ReadUInt32(); + this.Unknown_100h = reader.ReadUInt32(); + this.Unknown_104h = reader.ReadUInt32(); + this.Unknown_108h = reader.ReadUInt32(); + this.Unknown_10Ch = reader.ReadUInt32(); + this.Unknown_110h = reader.ReadUInt32(); + this.Unknown_114h = reader.ReadUInt32(); + this.Unknown_118h = reader.ReadUInt32(); + this.Unknown_11Ch = reader.ReadUInt32(); + this.Unknown_120h = reader.ReadUInt32(); + this.Unknown_124h = reader.ReadUInt32(); + this.Unknown_128h = reader.ReadUInt32(); + this.Unknown_12Ch = reader.ReadUInt32(); + this.Unknown_130h = reader.ReadUInt32(); + this.Unknown_134h = reader.ReadUInt32(); + this.Unknown_138h = reader.ReadUInt32(); + this.Unknown_13Ch = reader.ReadUInt32(); + this.Unknown_140h = reader.ReadUInt32(); + this.Unknown_144h = reader.ReadUInt32(); + this.Unknown_148h = reader.ReadUInt32(); + this.Unknown_14Ch = reader.ReadUInt32(); + //this.Unknown_150h = reader.ReadBlock>(); + //this.Unknown_160h = reader.ReadBlock>(); + this.Unknown_150hPtr = reader.ReadStruct(); + this.Unknown_160hPtr = reader.ReadStruct(); + this.Unknown_150h = reader.ReadUshortsAt(Unknown_150hPtr.EntriesPointer, Unknown_150hPtr.EntriesCount); + this.Unknown_160h = reader.ReadUshortsAt(Unknown_160hPtr.EntriesPointer, Unknown_160hPtr.EntriesCount); + this.Unknown_170h = reader.ReadUInt32(); + this.Unknown_174h = reader.ReadUInt32(); + this.Unknown_178h = reader.ReadUInt32(); + this.Unknown_17Ch = reader.ReadUInt32(); + this.Unknown_180h = reader.ReadUInt32(); + this.Unknown_184h = reader.ReadUInt32(); + this.Unknown_188h = reader.ReadUInt32(); + this.Unknown_18Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_00h); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + //writer.WriteBlock(this.Unknown_50h); //TODO: fix this! + //writer.WriteBlock(this.Unknown_60h); + //writer.WriteBlock(this.Unknown_70h); + //writer.WriteBlock(this.Unknown_80h); + //writer.WriteBlock(this.Unknown_90h); + //writer.WriteBlock(this.Unknown_A0h); + //writer.WriteBlock(this.Unknown_B0h); + //writer.WriteBlock(this.Unknown_C0h); + //writer.WriteBlock(this.Unknown_D0h); + //writer.WriteBlock(this.Unknown_E0h); + writer.Write(this.Unknown_F0h); + writer.Write(this.Unknown_F4h); + writer.Write(this.Unknown_F8h); + writer.Write(this.Unknown_FCh); + writer.Write(this.Unknown_100h); + writer.Write(this.Unknown_104h); + writer.Write(this.Unknown_108h); + writer.Write(this.Unknown_10Ch); + writer.Write(this.Unknown_110h); + writer.Write(this.Unknown_114h); + writer.Write(this.Unknown_118h); + writer.Write(this.Unknown_11Ch); + writer.Write(this.Unknown_120h); + writer.Write(this.Unknown_124h); + writer.Write(this.Unknown_128h); + writer.Write(this.Unknown_12Ch); + writer.Write(this.Unknown_130h); + writer.Write(this.Unknown_134h); + writer.Write(this.Unknown_138h); + writer.Write(this.Unknown_13Ch); + writer.Write(this.Unknown_140h); + writer.Write(this.Unknown_144h); + writer.Write(this.Unknown_148h); + writer.Write(this.Unknown_14Ch); + //writer.WriteBlock(this.Unknown_150h); //TODO: fix + //writer.WriteBlock(this.Unknown_160h); + writer.Write(this.Unknown_170h); + writer.Write(this.Unknown_174h); + writer.Write(this.Unknown_178h); + writer.Write(this.Unknown_17Ch); + writer.Write(this.Unknown_180h); + writer.Write(this.Unknown_184h); + writer.Write(this.Unknown_188h); + writer.Write(this.Unknown_18Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(0x50, Unknown_50h), //TODO: fix this + //new Tuple(0x60, Unknown_60h), + //new Tuple(0x70, Unknown_70h), + //new Tuple(0x80, Unknown_80h), + //new Tuple(0x90, Unknown_90h), + //new Tuple(0xA0, Unknown_A0h), + //new Tuple(0xB0, Unknown_B0h), + //new Tuple(0xC0, Unknown_C0h), + //new Tuple(0xD0, Unknown_D0h), + //new Tuple(0xE0, Unknown_E0h), + //new Tuple(0x150, Unknown_150h), + //new Tuple(0x160, Unknown_160h) + }; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragClothVerletCloth : ResourceSystemBlock + { + public override long BlockLength + { + get { return 384; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong BoundsPointer { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public uint Unknown_48h { get; set; } + public uint Unknown_4Ch { get; set; } + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } // 0x00000001 + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + public uint Unknown_60h { get; set; } // 0x00000000 + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + public ResourceSimpleList64Ptr Unknown_70hPtr { get; set; } + public SharpDX.Vector4[] Unknown_70h { get; set; } + //public uint Unknown_70h { get; set; } // 0x00000000 + //public uint Unknown_74h { get; set; } // 0x00000000 + //public uint Unknown_78h { get; set; } // 0x00000000 + //public uint Unknown_7Ch { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_80h { get; set; } + public ResourceSimpleList64Ptr Unknown_80hPtr { get; set; } + public SharpDX.Vector4[] Unknown_80h { get; set; } + public uint Unknown_90h { get; set; } // 0x00000000 + public uint Unknown_94h { get; set; } // 0x00000000 + public uint Unknown_98h { get; set; } // 0x00000000 + public uint Unknown_9Ch { get; set; } // 0x00000000 + public uint Unknown_A0h { get; set; } // 0x00000000 + public uint Unknown_A4h { get; set; } // 0x00000000 + public uint Unknown_A8h { get; set; } + public uint Unknown_ACh { get; set; } + public uint Unknown_B0h { get; set; } // 0x00000000 + public uint Unknown_B4h { get; set; } // 0x00000000 + public uint Unknown_B8h { get; set; } // 0x00000000 + public uint Unknown_BCh { get; set; } // 0x00000000 + public uint Unknown_C0h { get; set; } // 0x00000000 + public uint Unknown_C4h { get; set; } // 0x00000000 + public uint Unknown_C8h { get; set; } // 0x00000000 + public uint Unknown_CCh { get; set; } // 0x00000000 + public uint Unknown_D0h { get; set; } // 0x00000000 + public uint Unknown_D4h { get; set; } // 0x00000000 + public uint Unknown_D8h { get; set; } // 0x00000000 + public uint Unknown_DCh { get; set; } // 0x00000000 + public uint Unknown_E0h { get; set; } // 0x00000000 + public uint Unknown_E4h { get; set; } // 0x00000000 + public uint Unknown_E8h { get; set; } + public uint Unknown_ECh { get; set; } + public uint Unknown_F0h { get; set; } + public uint Unknown_F4h { get; set; } // 0x00000000 + public uint Unknown_F8h { get; set; } + public uint Unknown_FCh { get; set; } // 0x00000000 + //public ResourceSimpleList64 Unknown_100h { get; set; } + //public ResourceSimpleList64 Unknown_110h { get; set; } + public ResourceSimpleList64Ptr Unknown_100hPtr { get; set; } + public ResourceSimpleList64Ptr Unknown_110hPtr { get; set; } + public SharpDX.Vector4[] Unknown_100h { get; set; } + public SharpDX.Vector4[] Unknown_110h { get; set; } + public uint Unknown_120h { get; set; } // 0x00000000 + public uint Unknown_124h { get; set; } // 0x00000000 + public uint Unknown_128h { get; set; } // 0x00000000 + public uint Unknown_12Ch { get; set; } // 0x00000000 + public ulong BehaviorPointer { get; set; } + public uint Unknown_138h { get; set; } // 0x00100000 + public uint Unknown_13Ch { get; set; } // 0x00000000 + public ulong Unknown_140h_Pointer { get; set; } + public uint Unknown_148h { get; set; } + public uint Unknown_14Ch { get; set; } // 0x00000000 + public uint Unknown_150h { get; set; } // 0x00000000 + public uint Unknown_154h { get; set; } // 0x00000000 + public uint Unknown_158h { get; set; } + public uint Unknown_15Ch { get; set; } // 0x00000000 + public uint Unknown_160h { get; set; } // 0x00000000 + public uint Unknown_164h { get; set; } // 0x00000000 + public uint Unknown_168h { get; set; } // 0x00000000 + public uint Unknown_16Ch { get; set; } // 0x00000000 + public uint Unknown_170h { get; set; } // 0x00000000 + public uint Unknown_174h { get; set; } // 0x00000000 + public uint Unknown_178h { get; set; } // 0x00000000 + public uint Unknown_17Ch { get; set; } // 0x00000000 + + // reference data + public Bounds Bounds { get; set; } + public FragClothVerletBehavior Behavior { get; set; } + public FragClothUnknown_F_023 Unknown_140h_Data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.BoundsPointer = reader.ReadUInt64(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70hPtr = reader.ReadStruct(); + this.Unknown_70h = reader.ReadStructsAt(Unknown_70hPtr.EntriesPointer, Unknown_70hPtr.EntriesCount); + //this.Unknown_70h = reader.ReadUInt32(); + //this.Unknown_74h = reader.ReadUInt32(); + //this.Unknown_78h = reader.ReadUInt32(); + //this.Unknown_7Ch = reader.ReadUInt32(); + //this.Unknown_80h = reader.ReadBlock>(); + this.Unknown_80hPtr = reader.ReadStruct(); + this.Unknown_80h = reader.ReadStructsAt(Unknown_80hPtr.EntriesPointer, Unknown_80hPtr.EntriesCount); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.Unknown_A0h = reader.ReadUInt32(); + this.Unknown_A4h = reader.ReadUInt32(); + this.Unknown_A8h = reader.ReadUInt32(); + this.Unknown_ACh = reader.ReadUInt32(); + this.Unknown_B0h = reader.ReadUInt32(); + this.Unknown_B4h = reader.ReadUInt32(); + this.Unknown_B8h = reader.ReadUInt32(); + this.Unknown_BCh = reader.ReadUInt32(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.Unknown_C8h = reader.ReadUInt32(); + this.Unknown_CCh = reader.ReadUInt32(); + this.Unknown_D0h = reader.ReadUInt32(); + this.Unknown_D4h = reader.ReadUInt32(); + this.Unknown_D8h = reader.ReadUInt32(); + this.Unknown_DCh = reader.ReadUInt32(); + this.Unknown_E0h = reader.ReadUInt32(); + this.Unknown_E4h = reader.ReadUInt32(); + this.Unknown_E8h = reader.ReadUInt32(); + this.Unknown_ECh = reader.ReadUInt32(); + this.Unknown_F0h = reader.ReadUInt32(); + this.Unknown_F4h = reader.ReadUInt32(); + this.Unknown_F8h = reader.ReadUInt32(); + this.Unknown_FCh = reader.ReadUInt32(); + //this.Unknown_100h = reader.ReadBlock>(); + //this.Unknown_110h = reader.ReadBlock>(); + this.Unknown_100hPtr = reader.ReadStruct(); + this.Unknown_110hPtr = reader.ReadStruct(); + this.Unknown_100h = reader.ReadStructsAt(Unknown_100hPtr.EntriesPointer, Unknown_100hPtr.EntriesCount); + this.Unknown_110h = reader.ReadStructsAt(Unknown_110hPtr.EntriesPointer, Unknown_110hPtr.EntriesCount); + this.Unknown_120h = reader.ReadUInt32(); + this.Unknown_124h = reader.ReadUInt32(); + this.Unknown_128h = reader.ReadUInt32(); + this.Unknown_12Ch = reader.ReadUInt32(); + this.BehaviorPointer = reader.ReadUInt64(); + this.Unknown_138h = reader.ReadUInt32(); + this.Unknown_13Ch = reader.ReadUInt32(); + this.Unknown_140h_Pointer = reader.ReadUInt64(); + this.Unknown_148h = reader.ReadUInt32(); + this.Unknown_14Ch = reader.ReadUInt32(); + this.Unknown_150h = reader.ReadUInt32(); + this.Unknown_154h = reader.ReadUInt32(); + this.Unknown_158h = reader.ReadUInt32(); + this.Unknown_15Ch = reader.ReadUInt32(); + this.Unknown_160h = reader.ReadUInt32(); + this.Unknown_164h = reader.ReadUInt32(); + this.Unknown_168h = reader.ReadUInt32(); + this.Unknown_16Ch = reader.ReadUInt32(); + this.Unknown_170h = reader.ReadUInt32(); + this.Unknown_174h = reader.ReadUInt32(); + this.Unknown_178h = reader.ReadUInt32(); + this.Unknown_17Ch = reader.ReadUInt32(); + + // read reference data + this.Bounds = reader.ReadBlockAt( + this.BoundsPointer // offset + ); + this.Behavior = reader.ReadBlockAt( + this.BehaviorPointer // offset + ); + this.Unknown_140h_Data = reader.ReadBlockAt( + this.Unknown_140h_Pointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.BoundsPointer = (ulong)(this.Bounds != null ? this.Bounds.FilePosition : 0); + this.BehaviorPointer = (ulong)(this.Behavior != null ? this.Behavior.FilePosition : 0); + this.Unknown_140h_Pointer = (ulong)(this.Unknown_140h_Data != null ? this.Unknown_140h_Data.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.BoundsPointer); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + //writer.Write(this.Unknown_70h); + //writer.Write(this.Unknown_74h); + //writer.Write(this.Unknown_78h); + //writer.Write(this.Unknown_7Ch); + //writer.WriteBlock(this.Unknown_80h); //TODO: fix + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.Unknown_A0h); + writer.Write(this.Unknown_A4h); + writer.Write(this.Unknown_A8h); + writer.Write(this.Unknown_ACh); + writer.Write(this.Unknown_B0h); + writer.Write(this.Unknown_B4h); + writer.Write(this.Unknown_B8h); + writer.Write(this.Unknown_BCh); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.Unknown_C8h); + writer.Write(this.Unknown_CCh); + writer.Write(this.Unknown_D0h); + writer.Write(this.Unknown_D4h); + writer.Write(this.Unknown_D8h); + writer.Write(this.Unknown_DCh); + writer.Write(this.Unknown_E0h); + writer.Write(this.Unknown_E4h); + writer.Write(this.Unknown_E8h); + writer.Write(this.Unknown_ECh); + writer.Write(this.Unknown_F0h); + writer.Write(this.Unknown_F4h); + writer.Write(this.Unknown_F8h); + writer.Write(this.Unknown_FCh); + //writer.WriteBlock(this.Unknown_100h); //TODO: fix + //writer.WriteBlock(this.Unknown_110h); + writer.Write(this.Unknown_120h); + writer.Write(this.Unknown_124h); + writer.Write(this.Unknown_128h); + writer.Write(this.Unknown_12Ch); + writer.Write(this.BehaviorPointer); + writer.Write(this.Unknown_138h); + writer.Write(this.Unknown_13Ch); + writer.Write(this.Unknown_140h_Pointer); + writer.Write(this.Unknown_148h); + writer.Write(this.Unknown_14Ch); + writer.Write(this.Unknown_150h); + writer.Write(this.Unknown_154h); + writer.Write(this.Unknown_158h); + writer.Write(this.Unknown_15Ch); + writer.Write(this.Unknown_160h); + writer.Write(this.Unknown_164h); + writer.Write(this.Unknown_168h); + writer.Write(this.Unknown_16Ch); + writer.Write(this.Unknown_170h); + writer.Write(this.Unknown_174h); + writer.Write(this.Unknown_178h); + writer.Write(this.Unknown_17Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Bounds != null) list.Add(Bounds); + if (Behavior != null) list.Add(Behavior); + if (Unknown_140h_Data != null) list.Add(Unknown_140h_Data); + return list.ToArray(); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(0x80, Unknown_80h), //TODO: fix + //new Tuple(0x100, Unknown_100h), + //new Tuple(0x110, Unknown_110h) + }; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragClothVerletBehavior : ResourceSystemBlock + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint Unknown_00h { get; set; } // 0x00000000 + public uint Unknown_04h { get; set; } // 0x00000000 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_00h = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_00h); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragClothUnknown_F_023 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public uint Unknown_0h { get; set; } // 0x00000000 + public uint Unknown_4h { get; set; } // 0x00000000 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragDrawable : DrawableBase + { + public override long BlockLength + { + get { return 336; } + } + + // structure data + public uint Unknown_0A8h { get; set; } + public uint Unknown_0ACh { get; set; } + public SharpDX.Matrix Unknown_0B0h { get; set; } + public ulong BoundPointer { get; set; } + public ulong Unknown_0F8h_Pointer { get; set; } + public ushort Count1 { get; set; } + public ushort Count2 { get; set; } + public uint Unknown_104h { get; set; } // 0x00000000 + public ulong Unknown_108h_Pointer { get; set; } + public ushort Count3 { get; set; } + public ushort Count4 { get; set; } + public uint Unknown_114h { get; set; } // 0x00000000 + public uint Unknown_118h { get; set; } // 0x00000000 + public uint Unknown_11Ch { get; set; } // 0x00000000 + public uint Unknown_120h { get; set; } // 0x00000000 + public uint Unknown_124h { get; set; } // 0x00000000 + public uint Unknown_128h { get; set; } // 0x00000000 + public uint Unknown_12Ch { get; set; } // 0x00000000 + public ulong NamePointer { get; set; } + public uint Unknown_138h { get; set; } // 0x00000000 + public uint Unknown_13Ch { get; set; } // 0x00000000 + public uint Unknown_140h { get; set; } // 0x00000000 + public uint Unknown_144h { get; set; } // 0x00000000 + public uint Unknown_148h { get; set; } // 0x00000000 + public uint Unknown_14Ch { get; set; } // 0x00000000 + + // reference data + public Bounds Bound { get; set; } + //public ResourceSimpleArray Unknown_F8h_Data { get; set; } + public ulong[] Unknown_F8h_Data { get; set; } + //public ResourceSimpleArray Unknown_108h_Data { get; set; } + public SharpDX.Matrix[] Unknown_108h_Data { get; set; } + public string Name { get; set; } + + public FragType OwnerFragment { get; set; } //for handy use + public FragCloth OwnerFragmentCloth { get; set; } + public FragPhysTypeChild OwnerFragmentPhys { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_0A8h = reader.ReadUInt32(); + this.Unknown_0ACh = reader.ReadUInt32(); + this.Unknown_0B0h = reader.ReadStruct(); + this.BoundPointer = reader.ReadUInt64(); + this.Unknown_0F8h_Pointer = reader.ReadUInt64(); + this.Count1 = reader.ReadUInt16(); + this.Count2 = reader.ReadUInt16(); + this.Unknown_104h = reader.ReadUInt32(); + this.Unknown_108h_Pointer = reader.ReadUInt64(); + this.Count3 = reader.ReadUInt16(); + this.Count4 = reader.ReadUInt16(); + this.Unknown_114h = reader.ReadUInt32(); + this.Unknown_118h = reader.ReadUInt32(); + this.Unknown_11Ch = reader.ReadUInt32(); + this.Unknown_120h = reader.ReadUInt32(); + this.Unknown_124h = reader.ReadUInt32(); + this.Unknown_128h = reader.ReadUInt32(); + this.Unknown_12Ch = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + this.Unknown_138h = reader.ReadUInt32(); + this.Unknown_13Ch = reader.ReadUInt32(); + this.Unknown_140h = reader.ReadUInt32(); + this.Unknown_144h = reader.ReadUInt32(); + this.Unknown_148h = reader.ReadUInt32(); + this.Unknown_14Ch = reader.ReadUInt32(); + + // read reference data + this.Bound = reader.ReadBlockAt( + this.BoundPointer // offset + ); + //this.Unknown_F8h_Data = reader.ReadBlockAt>( + // this.Unknown_F8h_Pointer, // offset + // this.Count1 + //); + this.Unknown_F8h_Data = reader.ReadUlongsAt(this.Unknown_0F8h_Pointer, this.Count1); + + //this.Unknown_108h_Data = reader.ReadBlockAt>( + // this.Unknown_108h_Pointer, // offset + // this.Count2 + //); + this.Unknown_108h_Data = reader.ReadStructsAt(this.Unknown_108h_Pointer, this.Count2); + + this.Name = reader.ReadStringAt(//BlockAt( + this.NamePointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + this.BoundPointer = (ulong)(this.Bound != null ? this.Bound.FilePosition : 0); + //this.Unknown_F8h_Pointer = (ulong)(this.Unknown_F8h_Data != null ? this.Unknown_F8h_Data.Position : 0); //TODO: fix + //this.c1qqq = (ushort)(this.pxx2data != null ? this.pxx2data.Count : 0); + //this.c2qqq = (ushort)(this.pxx3data != null ? this.pxx3data.Count : 0); + //this.Unknown_108h_Pointer = (ulong)(this.Unknown_108h_Data != null ? this.Unknown_108h_Data.Position : 0); + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); //TODO: fix + + // write structure data + writer.Write(this.Unknown_0A8h); + writer.Write(this.Unknown_0ACh); + //writer.WriteBlock(this.Unknown_0B0h); //TODO: fix! + writer.Write(this.BoundPointer); + writer.Write(this.Unknown_0F8h_Pointer); + writer.Write(this.Count1); + writer.Write(this.Count2); + writer.Write(this.Unknown_104h); + writer.Write(this.Unknown_108h_Pointer); + writer.Write(this.Count3); + writer.Write(this.Count4); + writer.Write(this.Unknown_114h); + writer.Write(this.Unknown_118h); + writer.Write(this.Unknown_11Ch); + writer.Write(this.Unknown_120h); + writer.Write(this.Unknown_124h); + writer.Write(this.Unknown_128h); + writer.Write(this.Unknown_12Ch); + writer.Write(this.NamePointer); + writer.Write(this.Unknown_138h); + writer.Write(this.Unknown_13Ch); + writer.Write(this.Unknown_140h); + writer.Write(this.Unknown_144h); + writer.Write(this.Unknown_148h); + writer.Write(this.Unknown_14Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if (Bound != null) list.Add(Bound); + //if (Unknown_F8h_Data != null) list.Add(Unknown_F8h_Data); //TODO: fix + //if (Unknown_108h_Data != null) list.Add(Unknown_108h_Data); + //if (Name != null) list.Add(Name); //TODO: fix + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragUnknown_F_004 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32 + Data.Length; } + } + + // structure data + public uint Unknown_00h { get; set; } // 0x00000000 + public uint Unknown_04h { get; set; } // 0x00000000 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public byte cnt1 { get; set; } + public byte cnt2 { get; set; } + public ushort Unknown_12h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public Matrix3_s[] Data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_00h = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.cnt1 = reader.ReadByte(); + this.cnt2 = reader.ReadByte(); + this.Unknown_12h = reader.ReadUInt16(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + //this.Data = reader.ReadBlock>( + // cnt1 + // ); + this.Data = reader.ReadStructsAt((ulong)reader.Position, cnt1); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_00h); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.cnt1); + writer.Write(this.cnt2); + writer.Write(this.Unknown_12h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + //writer.WriteBlock(this.Data); //TODO: fix + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(32, Data) //TODO: FIX + }; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragUnknown_F_006 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 112; } + } + + // structure data + public uint Unknown_00h { get; set; } + public uint Unknown_04h { get; set; } + public uint Unknown_08h { get; set; } + public uint Unknown_0Ch { get; set; } // 0x7F800001 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x7F800001 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } // 0x7F800001 + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } // 0x000000D9 + public uint Unknown_44h { get; set; } // 0x0500002C + public uint Unknown_48h { get; set; } // 0x55996996 looks like vertex types + public uint Unknown_4Ch { get; set; } // 0x76555555 + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } + public uint Unknown_58h { get; set; } + public uint Unknown_5Ch { get; set; } + public uint Unknown_60h { get; set; } + public uint Unknown_64h { get; set; } + public uint Unknown_68h { get; set; } + public uint Unknown_6Ch { get; set; } // 0x7F800001 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_00h = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_00h); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragUnknown_F_003 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 16 + Data.Length; } + } + + // structure data + public uint Unknown_0h { get; set; } // 0x56475748 + public uint Unknown_4h { get; set; } + public uint cnt1 { get; set; } + public uint Unknown_Ch { get; set; } + //public ResourceSimpleArray Data { get; set; } + public byte[] Data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.cnt1 = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + //this.Data = reader.ReadBlock>( + // cnt1 - 16 + // ); + this.Data = reader.ReadBytesAt((ulong)this.FilePosition, cnt1 - 16); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.cnt1); + writer.Write(this.Unknown_Ch); + //writer.WriteBlock(this.Data); //TODO: FIX!! + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(16, Data) + }; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysicsLODGroup : ResourceSystemBlock + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public ulong PhysicsLOD1Pointer { get; set; } + public ulong PhysicsLOD2Pointer { get; set; } + public ulong PhysicsLOD3Pointer { get; set; } + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + // reference data + public FragPhysicsLOD PhysicsLOD1 { get; set; } + public FragPhysicsLOD PhysicsLOD2 { get; set; } + public FragPhysicsLOD PhysicsLOD3 { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.PhysicsLOD1Pointer = reader.ReadUInt64(); + this.PhysicsLOD2Pointer = reader.ReadUInt64(); + this.PhysicsLOD3Pointer = reader.ReadUInt64(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + + // read reference data + this.PhysicsLOD1 = reader.ReadBlockAt( + this.PhysicsLOD1Pointer // offset + ); + this.PhysicsLOD2 = reader.ReadBlockAt( + this.PhysicsLOD2Pointer // offset + ); + this.PhysicsLOD3 = reader.ReadBlockAt( + this.PhysicsLOD3Pointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.PhysicsLOD1Pointer = (ulong)(this.PhysicsLOD1 != null ? this.PhysicsLOD1.FilePosition : 0); + this.PhysicsLOD2Pointer = (ulong)(this.PhysicsLOD2 != null ? this.PhysicsLOD2.FilePosition : 0); + this.PhysicsLOD3Pointer = (ulong)(this.PhysicsLOD3 != null ? this.PhysicsLOD3.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.PhysicsLOD1Pointer); + writer.Write(this.PhysicsLOD2Pointer); + writer.Write(this.PhysicsLOD3Pointer); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (PhysicsLOD1 != null) list.Add(PhysicsLOD1); + if (PhysicsLOD2 != null) list.Add(PhysicsLOD2); + if (PhysicsLOD3 != null) list.Add(PhysicsLOD3); + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysicsLOD : ResourceSystemBlock + { + public override long BlockLength + { + get { return 304; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + public ulong ArticulatedBodyTypePointer { get; set; } + public ulong Unknown_28h_Pointer { get; set; } + public SharpDX.Vector4 Unknown_30h { get; set; } + public SharpDX.Vector4 Unknown_40h { get; set; } + public SharpDX.Vector4 Unknown_50h { get; set; } + public SharpDX.Vector4 Unknown_60h { get; set; } + public SharpDX.Vector4 Unknown_70h { get; set; } + public SharpDX.Vector4 Unknown_80h { get; set; } + public SharpDX.Vector4 Unknown_90h { get; set; } + public SharpDX.Vector4 Unknown_A0h { get; set; } + public SharpDX.Vector4 Unknown_B0h { get; set; } + public ulong GroupNamesPointer { get; set; } + public ulong GroupsPointer { get; set; } + public ulong ChildrenPointer { get; set; } + public ulong Archetype1Pointer { get; set; } + public ulong Archetype2Pointer { get; set; } + public ulong BoundPointer { get; set; } + public ulong Unknown_F0h_Pointer { get; set; } + public ulong Unknown_F8h_Pointer { get; set; } + public ulong Unknown_100h_Pointer { get; set; } + public ulong Unknown_108h_Pointer { get; set; } + public ulong Unknown_110h_Pointer { get; set; } + public byte Count1 { get; set; } + public byte Count2 { get; set; } + public byte GroupsCount { get; set; } + public byte Unknown_11Bh { get; set; } + public byte Unknown_11Ch { get; set; } + public byte ChildrenCount { get; set; } + public byte Count3 { get; set; } + public byte Unknown_11Fh { get; set; } // 0x00 + public uint Unknown_120h { get; set; } // 0x00000000 + public uint Unknown_124h { get; set; } // 0x00000000 + public uint Unknown_128h { get; set; } // 0x00000000 + public uint Unknown_12Ch { get; set; } // 0x00000000 + + // reference data + public FragPhysArticulatedBodyType ArticulatedBodyType { get; set; } + public uint[] Unknown_28h_Data { get; set; } + public ResourcePointerArray64_s GroupNames { get; set; } + public ResourcePointerArray64_s Groups { get; set; } + public ResourcePointerArray64 Children { get; set; } + public FragPhysArchetype Archetype1 { get; set; } + public FragPhysArchetype Archetype2 { get; set; } + public Bounds Bound { get; set; } + public SharpDX.Vector4[] Unknown_F0h_Data { get; set; } + public SharpDX.Vector4[] Unknown_F8h_Data { get; set; } + public FragPhysUnknown_F_002 Unknown_100h_Data { get; set; } + public byte[] Unknown_108h_Data { get; set; } + public byte[] Unknown_110h_Data { get; set; } + + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.ArticulatedBodyTypePointer = reader.ReadUInt64(); + this.Unknown_28h_Pointer = reader.ReadUInt64(); + this.Unknown_30h = reader.ReadStruct(); + this.Unknown_40h = reader.ReadStruct(); + this.Unknown_50h = reader.ReadStruct(); + this.Unknown_60h = reader.ReadStruct(); + this.Unknown_70h = reader.ReadStruct(); + this.Unknown_80h = reader.ReadStruct(); + this.Unknown_90h = reader.ReadStruct(); + this.Unknown_A0h = reader.ReadStruct(); + this.Unknown_B0h = reader.ReadStruct(); + this.GroupNamesPointer = reader.ReadUInt64(); + this.GroupsPointer = reader.ReadUInt64(); + this.ChildrenPointer = reader.ReadUInt64(); + this.Archetype1Pointer = reader.ReadUInt64(); + this.Archetype2Pointer = reader.ReadUInt64(); + this.BoundPointer = reader.ReadUInt64(); + this.Unknown_F0h_Pointer = reader.ReadUInt64(); + this.Unknown_F8h_Pointer = reader.ReadUInt64(); + this.Unknown_100h_Pointer = reader.ReadUInt64(); + this.Unknown_108h_Pointer = reader.ReadUInt64(); + this.Unknown_110h_Pointer = reader.ReadUInt64(); + this.Count1 = reader.ReadByte(); + this.Count2 = reader.ReadByte(); + this.GroupsCount = reader.ReadByte(); + this.Unknown_11Bh = reader.ReadByte(); + this.Unknown_11Ch = reader.ReadByte(); + this.ChildrenCount = reader.ReadByte(); + this.Count3 = reader.ReadByte(); + this.Unknown_11Fh = reader.ReadByte(); + this.Unknown_120h = reader.ReadUInt32(); + this.Unknown_124h = reader.ReadUInt32(); + this.Unknown_128h = reader.ReadUInt32(); + this.Unknown_12Ch = reader.ReadUInt32(); + + // read reference data + this.ArticulatedBodyType = reader.ReadBlockAt( + this.ArticulatedBodyTypePointer // offset + ); + //this.Unknown_28h_Data = reader.ReadBlockAt>( + // this.Unknown_28h_Pointer, // offset + // this.ChildrenCount + //); + this.Unknown_28h_Data = reader.ReadUintsAt(this.Unknown_28h_Pointer, this.ChildrenCount); + + this.GroupNames = reader.ReadBlockAt>( + this.GroupNamesPointer, // offset + this.GroupsCount + ); + this.Groups = reader.ReadBlockAt>( + this.GroupsPointer, // offset + this.GroupsCount + ); + this.Children = reader.ReadBlockAt>( + this.ChildrenPointer, // offset + this.ChildrenCount + ); + this.Archetype1 = reader.ReadBlockAt( + this.Archetype1Pointer // offset + ); + this.Archetype2 = reader.ReadBlockAt( + this.Archetype2Pointer // offset + ); + this.Bound = reader.ReadBlockAt( + this.BoundPointer // offset + ); + //this.Unknown_F0h_Data = reader.ReadBlockAt>( + // this.Unknown_F0h_Pointer, // offset + // this.ChildrenCount + //); + //this.Unknown_F8h_Data = reader.ReadBlockAt>( + // this.Unknown_F8h_Pointer, // offset + // this.ChildrenCount + //); + this.Unknown_F0h_Data = reader.ReadStructsAt(this.Unknown_F0h_Pointer, this.ChildrenCount); + this.Unknown_F8h_Data = reader.ReadStructsAt(this.Unknown_F8h_Pointer, this.ChildrenCount); + + + this.Unknown_100h_Data = reader.ReadBlockAt( + this.Unknown_100h_Pointer // offset + ); + //this.Unknown_108h_Data = reader.ReadBlockAt>( + // this.Unknown_108h_Pointer, // offset + // this.Count1 + //); + //this.Unknown_110h_Data = reader.ReadBlockAt>( + // this.Unknown_110h_Pointer, // offset + // this.Count2 + //); + + this.Unknown_108h_Data = reader.ReadBytesAt(this.Unknown_108h_Pointer, this.Count1); + this.Unknown_110h_Data = reader.ReadBytesAt(this.Unknown_110h_Pointer, this.Count2); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.ArticulatedBodyTypePointer = (ulong)(this.ArticulatedBodyType != null ? this.ArticulatedBodyType.FilePosition : 0); + //this.Unknown_28h_Pointer = (ulong)(this.Unknown_28h_Data != null ? this.Unknown_28h_Data.Position : 0); //TODO: fix + this.GroupNamesPointer = (ulong)(this.GroupNames != null ? this.GroupNames.FilePosition : 0); + this.GroupsPointer = (ulong)(this.Groups != null ? this.Groups.FilePosition : 0); + this.ChildrenPointer = (ulong)(this.Children != null ? this.Children.FilePosition : 0); + this.Archetype1Pointer = (ulong)(this.Archetype1 != null ? this.Archetype1.FilePosition : 0); + this.Archetype2Pointer = (ulong)(this.Archetype2 != null ? this.Archetype2.FilePosition : 0); + this.BoundPointer = (ulong)(this.Bound != null ? this.Bound.FilePosition : 0); + //this.Unknown_F0h_Pointer = (ulong)(this.Unknown_F0h_Data != null ? this.Unknown_F0h_Data.Position : 0); + //this.Unknown_F8h_Pointer = (ulong)(this.Unknown_F8h_Data != null ? this.Unknown_F8h_Data.Position : 0); + this.Unknown_100h_Pointer = (ulong)(this.Unknown_100h_Data != null ? this.Unknown_100h_Data.FilePosition : 0); + //this.Unknown_108h_Pointer = (ulong)(this.Unknown_108h_Data != null ? this.Unknown_108h_Data.Position : 0); + //this.Unknown_110h_Pointer = (ulong)(this.Unknown_110h_Data != null ? this.Unknown_110h_Data.Position : 0); + + //this.vvv1 = (byte)(this.pxxxxx_2data != null ? this.pxxxxx_2data.Count : 0); + //this.vvv2 = (byte)(this.pxxxxx_3data != null ? this.pxxxxx_3data.Count : 0); + //this.GroupsCount = (byte)(this.Groups != null ? this.Groups.Count : 0); + //this.ChildrenCount = (byte)(this.p1data != null ? this.p1data.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.ArticulatedBodyTypePointer); + writer.Write(this.Unknown_28h_Pointer); + //writer.WriteBlock(this.Unknown_30h); //TODO: fix this! + //writer.WriteBlock(this.Unknown_40h); + //writer.WriteBlock(this.Unknown_50h); + //writer.WriteBlock(this.Unknown_60h); + //writer.WriteBlock(this.Unknown_70h); + //writer.WriteBlock(this.Unknown_80h); + //writer.WriteBlock(this.Unknown_90h); + //writer.WriteBlock(this.Unknown_A0h); + //writer.WriteBlock(this.Unknown_B0h); + writer.Write(this.GroupNamesPointer); + writer.Write(this.GroupsPointer); + writer.Write(this.ChildrenPointer); + writer.Write(this.Archetype1Pointer); + writer.Write(this.Archetype2Pointer); + writer.Write(this.BoundPointer); + writer.Write(this.Unknown_F0h_Pointer); + writer.Write(this.Unknown_F8h_Pointer); + writer.Write(this.Unknown_100h_Pointer); + writer.Write(this.Unknown_108h_Pointer); + writer.Write(this.Unknown_110h_Pointer); + writer.Write(this.Count1); + writer.Write(this.Count2); + writer.Write(this.GroupsCount); + writer.Write(this.Unknown_11Bh); + writer.Write(this.Unknown_11Ch); + writer.Write(this.ChildrenCount); + writer.Write(this.Count3); + writer.Write(this.Unknown_11Fh); + writer.Write(this.Unknown_120h); + writer.Write(this.Unknown_124h); + writer.Write(this.Unknown_128h); + writer.Write(this.Unknown_12Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (ArticulatedBodyType != null) list.Add(ArticulatedBodyType); + //if (Unknown_28h_Data != null) list.Add(Unknown_28h_Data); //TODO: fix + if (Groups != null) list.Add(Groups); + if (Children != null) list.Add(Children); + if (Archetype1 != null) list.Add(Archetype1); + if (Archetype2 != null) list.Add(Archetype2); + if (Bound != null) list.Add(Bound); + //if (Unknown_F0h_Data != null) list.Add(Unknown_F0h_Data); + //if (Unknown_F8h_Data != null) list.Add(Unknown_F8h_Data); + if (Unknown_100h_Data != null) list.Add(Unknown_100h_Data); + //if (Unknown_108h_Data != null) list.Add(Unknown_108h_Data); + //if (Unknown_110h_Data != null) list.Add(Unknown_110h_Data); + if (GroupNames != null) list.Add(GroupNames); + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysArticulatedBodyType : ResourceSystemBlock + { + public override long BlockLength + { + get { return 176; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public uint Unknown_48h { get; set; } + public uint Unknown_4Ch { get; set; } + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } + public uint Unknown_58h { get; set; } + public uint Unknown_5Ch { get; set; } + public uint Unknown_60h { get; set; } + public uint Unknown_64h { get; set; } + public uint Unknown_68h { get; set; } + public uint Unknown_6Ch { get; set; } + public uint Unknown_70h { get; set; } + public uint Unknown_74h { get; set; } + public ulong JointTypesPointer { get; set; } + public ulong p2 { get; set; } + public byte c1 { get; set; } + public byte JointTypesCount { get; set; } + public ushort Unknown_8Ah { get; set; } + public uint Unknown_8Ch { get; set; } + public uint Unknown_90h { get; set; } + public uint Unknown_94h { get; set; } + public uint Unknown_98h { get; set; } + public uint Unknown_9Ch { get; set; } + public uint Unknown_A0h { get; set; } + public uint Unknown_A4h { get; set; } + public uint Unknown_A8h { get; set; } + public uint Unknown_ACh { get; set; } + + // reference data + public ResourcePointerArray64 JointTypes { get; set; } + public SharpDX.Vector4[] p2data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.JointTypesPointer = reader.ReadUInt64(); + this.p2 = reader.ReadUInt64(); + this.c1 = reader.ReadByte(); + this.JointTypesCount = reader.ReadByte(); + this.Unknown_8Ah = reader.ReadUInt16(); + this.Unknown_8Ch = reader.ReadUInt32(); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.Unknown_A0h = reader.ReadUInt32(); + this.Unknown_A4h = reader.ReadUInt32(); + this.Unknown_A8h = reader.ReadUInt32(); + this.Unknown_ACh = reader.ReadUInt32(); + + // read reference data + this.JointTypes = reader.ReadBlockAt>( + this.JointTypesPointer, // offset + this.JointTypesCount + ); + //this.p2data = reader.ReadBlockAt>( + // this.p2, // offset + // this.c1 + //); + this.p2data = reader.ReadStructsAt(this.p2, this.c1); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.JointTypesPointer = (ulong)(this.JointTypes != null ? this.JointTypes.FilePosition : 0); + //this.p2 = (ulong)(this.p2data != null ? this.p2data.Position : 0); //TODO:fix + ////this.c1 = (byte)(this.p2data != null ? this.p2data.Count : 0); + ////this.c2 = (byte)(this.p1data != null ? this.p1data.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.JointTypesPointer); + writer.Write(this.p2); + writer.Write(this.c1); + writer.Write(this.JointTypesCount); + writer.Write(this.Unknown_8Ah); + writer.Write(this.Unknown_8Ch); + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.Unknown_A0h); + writer.Write(this.Unknown_A4h); + writer.Write(this.Unknown_A8h); + writer.Write(this.Unknown_ACh); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (JointTypes != null) list.Add(JointTypes); + //if (p2data != null) list.Add(p2data); //TODO: fix + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysJointType : ResourceSystemBlock, IResourceXXSystemBlock + { + public override long BlockLength + { + get { return 32; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public byte Unknown_14h { get; set; } // 0x3F533333 + public byte Type { get; set; } + public ushort Unknown_16h { get; set; } + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadByte(); + this.Type = reader.ReadByte(); + this.Unknown_16h = reader.ReadUInt16(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Type); + writer.Write(this.Unknown_16h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + } + + public IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters) + { + reader.Position += 21; + var type = reader.ReadByte(); + reader.Position -= 22; + + switch (type) + { + case 0: return new FragPhysJoint1DofType(); + case 1: return new FragPhysJoint3DofType(); + default: return null;// throw new Exception("Unknown type"); + } + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysJoint1DofType : FragPhysJointType + { + public override long BlockLength + { + get { return 176; } + } + + // structure data + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public uint Unknown_48h { get; set; } + public uint Unknown_4Ch { get; set; } + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } + public uint Unknown_58h { get; set; } + public uint Unknown_5Ch { get; set; } + public uint Unknown_60h { get; set; } + public uint Unknown_64h { get; set; } + public uint Unknown_68h { get; set; } + public uint Unknown_6Ch { get; set; } + public uint Unknown_70h { get; set; } + public uint Unknown_74h { get; set; } + public uint Unknown_78h { get; set; } + public uint Unknown_7Ch { get; set; } + public uint Unknown_80h { get; set; } + public uint Unknown_84h { get; set; } + public uint Unknown_88h { get; set; } + public uint Unknown_8Ch { get; set; } + public uint Unknown_90h { get; set; } + public uint Unknown_94h { get; set; } + public uint Unknown_98h { get; set; } + public uint Unknown_9Ch { get; set; } + public uint Unknown_A0h { get; set; } + public uint Unknown_A4h { get; set; } + public uint Unknown_A8h { get; set; } // 0x4CBEBC20 + public uint Unknown_ACh { get; set; } // 0xCCBEBC20 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.Unknown_A0h = reader.ReadUInt32(); + this.Unknown_A4h = reader.ReadUInt32(); + this.Unknown_A8h = reader.ReadUInt32(); + this.Unknown_ACh = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.Unknown_A0h); + writer.Write(this.Unknown_A4h); + writer.Write(this.Unknown_A8h); + writer.Write(this.Unknown_ACh); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysJoint3DofType : FragPhysJointType + { + public override long BlockLength + { + get { return 240; } + } + + // structure data + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public uint Unknown_48h { get; set; } + public uint Unknown_4Ch { get; set; } + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } + public uint Unknown_58h { get; set; } + public uint Unknown_5Ch { get; set; } + public uint Unknown_60h { get; set; } + public uint Unknown_64h { get; set; } + public uint Unknown_68h { get; set; } + public uint Unknown_6Ch { get; set; } + public uint Unknown_70h { get; set; } + public uint Unknown_74h { get; set; } + public uint Unknown_78h { get; set; } + public uint Unknown_7Ch { get; set; } + public uint Unknown_80h { get; set; } + public uint Unknown_84h { get; set; } + public uint Unknown_88h { get; set; } + public uint Unknown_8Ch { get; set; } + public uint Unknown_90h { get; set; } + public uint Unknown_94h { get; set; } + public uint Unknown_98h { get; set; } + public uint Unknown_9Ch { get; set; } + public uint Unknown_A0h { get; set; } + public uint Unknown_A4h { get; set; } + public uint Unknown_A8h { get; set; } + public uint Unknown_ACh { get; set; } // 0x00000000 + public uint Unknown_B0h { get; set; } // 0x00000000 + public uint Unknown_B4h { get; set; } // 0x00000000 + public uint Unknown_B8h { get; set; } // 0x00000000 + public uint Unknown_BCh { get; set; } // 0x00000000 + public uint Unknown_C0h { get; set; } // 0x4CBEBC20 + public uint Unknown_C4h { get; set; } // 0x4CBEBC20 + public uint Unknown_C8h { get; set; } // 0x4CBEBC20 + public uint Unknown_CCh { get; set; } // 0x4CBEBC20 + public uint Unknown_D0h { get; set; } // 0xCCBEBC20 + public uint Unknown_D4h { get; set; } // 0xCCBEBC20 + public uint Unknown_D8h { get; set; } // 0xCCBEBC20 + public uint Unknown_DCh { get; set; } // 0xCCBEBC20 + public uint Unknown_E0h { get; set; } // 0x00000000 + public uint Unknown_E4h { get; set; } // 0x00000000 + public uint Unknown_E8h { get; set; } // 0x00000000 + public uint Unknown_ECh { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.Unknown_A0h = reader.ReadUInt32(); + this.Unknown_A4h = reader.ReadUInt32(); + this.Unknown_A8h = reader.ReadUInt32(); + this.Unknown_ACh = reader.ReadUInt32(); + this.Unknown_B0h = reader.ReadUInt32(); + this.Unknown_B4h = reader.ReadUInt32(); + this.Unknown_B8h = reader.ReadUInt32(); + this.Unknown_BCh = reader.ReadUInt32(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.Unknown_C8h = reader.ReadUInt32(); + this.Unknown_CCh = reader.ReadUInt32(); + this.Unknown_D0h = reader.ReadUInt32(); + this.Unknown_D4h = reader.ReadUInt32(); + this.Unknown_D8h = reader.ReadUInt32(); + this.Unknown_DCh = reader.ReadUInt32(); + this.Unknown_E0h = reader.ReadUInt32(); + this.Unknown_E4h = reader.ReadUInt32(); + this.Unknown_E8h = reader.ReadUInt32(); + this.Unknown_ECh = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.Unknown_A0h); + writer.Write(this.Unknown_A4h); + writer.Write(this.Unknown_A8h); + writer.Write(this.Unknown_ACh); + writer.Write(this.Unknown_B0h); + writer.Write(this.Unknown_B4h); + writer.Write(this.Unknown_B8h); + writer.Write(this.Unknown_BCh); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.Unknown_C8h); + writer.Write(this.Unknown_CCh); + writer.Write(this.Unknown_D0h); + writer.Write(this.Unknown_D4h); + writer.Write(this.Unknown_D8h); + writer.Write(this.Unknown_DCh); + writer.Write(this.Unknown_E0h); + writer.Write(this.Unknown_E4h); + writer.Write(this.Unknown_E8h); + writer.Write(this.Unknown_ECh); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysUnknown_F_002 : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32 + Data.Length; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint cnt { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + //public ResourceSimpleArray Data { get; set; } + public SharpDX.Matrix[] Data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.cnt = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + //this.Data = reader.ReadBlock>( + // cnt + // ); + this.Data = reader.ReadStructsAt((ulong)reader.Position, cnt); + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.cnt); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + //writer.WriteBlock(this.Data); //TODO: fix + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(32, Data) //TODO: fix + }; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysArchetype : ResourceSystemBlock + { + public override long BlockLength + { + get { return 224; } + } + + // structure data + public float Unknown_00h { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000002 + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong NamePointer { get; set; } + public ulong BoundPointer { get; set; } + public uint Unknown_28h { get; set; } // 0x00000001 + public uint Unknown_2Ch { get; set; } // 0xFFFFFFFF + public uint Unknown_30h { get; set; } // 0x00010000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public float Unknown_40h { get; set; } + public float Unknown_44h { get; set; } + public float Unknown_48h { get; set; } // 1.0f + public float Unknown_4Ch { get; set; } // 150.0f + public float Unknown_50h { get; set; } // 6.2831855f = 2*pi + public float Unknown_54h { get; set; } // 1.0f + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + public SharpDX.Vector4 Unknown_60h { get; set; } + public SharpDX.Vector4 Unknown_70h { get; set; } + public SharpDX.Vector4 Unknown_80h { get; set; } // 0.0 0.0 0.0 NaN + public SharpDX.Vector4 Unknown_90h { get; set; } // 0.0 0.0 0.0 NaN + public SharpDX.Vector4 Unknown_A0h { get; set; } // 0.0 0.0 0.0 NaN + public SharpDX.Vector4 Unknown_B0h { get; set; } // 0.0 0.0 0.0 NaN + public SharpDX.Vector4 Unknown_C0h { get; set; } // 0.0 0.0 0.0 NaN + public SharpDX.Vector4 Unknown_D0h { get; set; } // 0.0 0.0 0.0 NaN + + // reference data + public string Name { get; set; } + public Bounds Bound { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_00h = reader.ReadSingle(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + this.BoundPointer = reader.ReadUInt64(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadSingle(); + this.Unknown_44h = reader.ReadSingle(); + this.Unknown_48h = reader.ReadSingle(); + this.Unknown_4Ch = reader.ReadSingle(); + this.Unknown_50h = reader.ReadSingle(); + this.Unknown_54h = reader.ReadSingle(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadStruct(); + this.Unknown_70h = reader.ReadStruct(); + this.Unknown_80h = reader.ReadStruct(); + this.Unknown_90h = reader.ReadStruct(); + this.Unknown_A0h = reader.ReadStruct(); + this.Unknown_B0h = reader.ReadStruct(); + this.Unknown_C0h = reader.ReadStruct(); + this.Unknown_D0h = reader.ReadStruct(); + + // read reference data + this.Name = reader.ReadStringAt(//BlockAt( + this.NamePointer // offset + ); + this.Bound = reader.ReadBlockAt( + this.BoundPointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); //TODO:fix + this.BoundPointer = (ulong)(this.Bound != null ? this.Bound.FilePosition : 0); + + // write structure data + writer.Write(this.Unknown_00h); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.NamePointer); + writer.Write(this.BoundPointer); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + //writer.WriteBlock(this.Unknown_60h); //TODO: fix! + //writer.WriteBlock(this.Unknown_70h); + //writer.WriteBlock(this.Unknown_80h); + //writer.WriteBlock(this.Unknown_90h); + //writer.WriteBlock(this.Unknown_A0h); + //writer.WriteBlock(this.Unknown_B0h); + //writer.WriteBlock(this.Unknown_C0h); + //writer.WriteBlock(this.Unknown_D0h); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Name != null) list.Add(Name); //TODO: fix! + if (Bound != null) list.Add(Bound); + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysTypeChild : ResourceSystemBlock + { + public override long BlockLength + { + get { return 256; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } + public uint Unknown_0Ch { get; set; } + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + public uint Unknown_60h { get; set; } // 0x00000000 + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + public uint Unknown_70h { get; set; } // 0x00000000 + public uint Unknown_74h { get; set; } // 0x00000000 + public uint Unknown_78h { get; set; } // 0x00000000 + public uint Unknown_7Ch { get; set; } // 0x00000000 + public uint Unknown_80h { get; set; } // 0x00000000 + public uint Unknown_84h { get; set; } // 0x00000000 + public uint Unknown_88h { get; set; } // 0x00000000 + public uint Unknown_8Ch { get; set; } // 0x00000000 + public uint Unknown_90h { get; set; } // 0x00000000 + public uint Unknown_94h { get; set; } // 0x00000000 + public uint Unknown_98h { get; set; } // 0x00000000 + public uint Unknown_9Ch { get; set; } // 0x00000000 + public ulong Drawable1Pointer { get; set; } + public ulong Drawable2Pointer { get; set; } + public ulong EvtSetPointer { get; set; } + public uint Unknown_B8h { get; set; } // 0x00000000 + public uint Unknown_BCh { get; set; } // 0x00000000 + public uint Unknown_C0h { get; set; } // 0x00000000 + public uint Unknown_C4h { get; set; } // 0x00000000 + public uint Unknown_C8h { get; set; } // 0x00000000 + public uint Unknown_CCh { get; set; } // 0x00000000 + public uint Unknown_D0h { get; set; } // 0x00000000 + public uint Unknown_D4h { get; set; } // 0x00000000 + public uint Unknown_D8h { get; set; } // 0x00000000 + public uint Unknown_DCh { get; set; } // 0x00000000 + public uint Unknown_E0h { get; set; } // 0x00000000 + public uint Unknown_E4h { get; set; } // 0x00000000 + public uint Unknown_E8h { get; set; } // 0x00000000 + public uint Unknown_ECh { get; set; } // 0x00000000 + public uint Unknown_F0h { get; set; } // 0x00000000 + public uint Unknown_F4h { get; set; } // 0x00000000 + public uint Unknown_F8h { get; set; } // 0x00000000 + public uint Unknown_FCh { get; set; } // 0x00000000 + + // reference data + public FragDrawable Drawable1 { get; set; } + public FragDrawable Drawable2 { get; set; } + public FragPhysEvtSet EvtSet { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.Drawable1Pointer = reader.ReadUInt64(); + this.Drawable2Pointer = reader.ReadUInt64(); + this.EvtSetPointer = reader.ReadUInt64(); + this.Unknown_B8h = reader.ReadUInt32(); + this.Unknown_BCh = reader.ReadUInt32(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.Unknown_C8h = reader.ReadUInt32(); + this.Unknown_CCh = reader.ReadUInt32(); + this.Unknown_D0h = reader.ReadUInt32(); + this.Unknown_D4h = reader.ReadUInt32(); + this.Unknown_D8h = reader.ReadUInt32(); + this.Unknown_DCh = reader.ReadUInt32(); + this.Unknown_E0h = reader.ReadUInt32(); + this.Unknown_E4h = reader.ReadUInt32(); + this.Unknown_E8h = reader.ReadUInt32(); + this.Unknown_ECh = reader.ReadUInt32(); + this.Unknown_F0h = reader.ReadUInt32(); + this.Unknown_F4h = reader.ReadUInt32(); + this.Unknown_F8h = reader.ReadUInt32(); + this.Unknown_FCh = reader.ReadUInt32(); + + // read reference data + this.Drawable1 = reader.ReadBlockAt( + this.Drawable1Pointer // offset + ); + this.Drawable2 = reader.ReadBlockAt( + this.Drawable2Pointer // offset + ); + this.EvtSet = reader.ReadBlockAt( + this.EvtSetPointer // offset + ); + + if (this.Drawable1 != null) + { + this.Drawable1.OwnerFragmentPhys = this; + } + if (this.Drawable2 != null) + { + this.Drawable2.OwnerFragmentPhys = this; + } + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.Drawable1Pointer = (ulong)(this.Drawable1 != null ? this.Drawable1.FilePosition : 0); + this.Drawable2Pointer = (ulong)(this.Drawable2 != null ? this.Drawable2.FilePosition : 0); + this.EvtSetPointer = (ulong)(this.EvtSet != null ? this.EvtSet.FilePosition : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.Drawable1Pointer); + writer.Write(this.Drawable2Pointer); + writer.Write(this.EvtSetPointer); + writer.Write(this.Unknown_B8h); + writer.Write(this.Unknown_BCh); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.Unknown_C8h); + writer.Write(this.Unknown_CCh); + writer.Write(this.Unknown_D0h); + writer.Write(this.Unknown_D4h); + writer.Write(this.Unknown_D8h); + writer.Write(this.Unknown_DCh); + writer.Write(this.Unknown_E0h); + writer.Write(this.Unknown_E4h); + writer.Write(this.Unknown_E8h); + writer.Write(this.Unknown_ECh); + writer.Write(this.Unknown_F0h); + writer.Write(this.Unknown_F4h); + writer.Write(this.Unknown_F8h); + writer.Write(this.Unknown_FCh); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Drawable1 != null) list.Add(Drawable1); + if (Drawable2 != null) list.Add(Drawable2); + if (EvtSet != null) list.Add(EvtSet); + return list.ToArray(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class FragPhysEvtSet : ResourceSystemBlock + { + public override long BlockLength + { + get { return 48; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint Unknown_08h { get; set; } // 0x00000000 + public uint Unknown_0Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_04h = reader.ReadUInt32(); + this.Unknown_08h = reader.ReadUInt32(); + this.Unknown_0Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_04h); + writer.Write(this.Unknown_08h); + writer.Write(this.Unknown_0Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct FragPhysTypeGroup_s + { + // structure data + public float Unknown_00h { get; set; } // 0x00000000 + public float Unknown_04h { get; set; } // 0x00000000 + public float Unknown_08h { get; set; } // 0x00000000 + public float Unknown_0Ch { get; set; } // 0x00000000 + public float Unknown_10h { get; set; } + public float Unknown_14h { get; set; } + public float Unknown_18h { get; set; } + public float Unknown_1Ch { get; set; } + public float Unknown_20h { get; set; } + public float Unknown_24h { get; set; } + public float Unknown_28h { get; set; } + public float Unknown_2Ch { get; set; } + public float Unknown_30h { get; set; } + public float Unknown_34h { get; set; } + public float Unknown_38h { get; set; } + public float Unknown_3Ch { get; set; } + public float Unknown_40h { get; set; } + public float Unknown_44h { get; set; } + public float Unknown_48h { get; set; } // 0x00000000 + public byte Unknown_4Cha { get; set; } + public byte Unknown_4Chb { get; set; } + public byte Unknown_4Chc { get; set; } + public byte Unknown_4Chd { get; set; } + //public uint Unknown_4Ch { get; set; } + public byte Unknown_50ha { get; set; } + public byte Unknown_50hb { get; set; }//0xFF + public ushort Unknown_50hc { get; set; }//0 + //public uint Unknown_50h { get; set; } + public float Unknown_54h { get; set; } + public float Unknown_58h { get; set; } + public float Unknown_5Ch { get; set; } + public float Unknown_60h { get; set; } + public float Unknown_64h { get; set; } + public float Unknown_68h { get; set; } + public float Unknown_6Ch { get; set; } + public float Unknown_70h { get; set; } + public float Unknown_74h { get; set; } + public float Unknown_78h { get; set; } + public float Unknown_7Ch { get; set; } // 0x00000000 + public FragPhysNameStruct_s Name { get; set; } + public float Unknown_A0h { get; set; } // 0x00000000 + public float Unknown_A4h { get; set; } // 0x00000000 + public float Unknown_A8h { get; set; } + public float Unknown_ACh { get; set; } // 0x00000000 + + public override string ToString() + { + return Name.ToString(); + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct FragPhysNameStruct_s + { + // structure data + public uint Unknown_00h { get; set; } + public uint Unknown_04h { get; set; } + public uint Unknown_08h { get; set; } + public uint Unknown_0Ch { get; set; } + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + + public override string ToString() + { + UintStringBuilder usb = new UintStringBuilder(); + usb.Add(Unknown_00h); + usb.Add(Unknown_04h); + usb.Add(Unknown_08h); + usb.Add(Unknown_0Ch); + usb.Add(Unknown_10h); + usb.Add(Unknown_14h); + usb.Add(Unknown_18h); + usb.Add(Unknown_1Ch); + return usb.ToString(); + } + } + + + public class UintStringBuilder + { + public StringBuilder sb = new StringBuilder(); + + public void Add(uint u) + { + sb.Append((char)((u & 0x000000FF) >> 0)); + sb.Append((char)((u & 0x0000FF00) >> 8)); + sb.Append((char)((u & 0x00FF0000) >> 16)); + sb.Append((char)((u & 0xFF000000) >> 24)); + } + + public override string ToString() + { + return sb.ToString().Replace("\0", ""); + } + } + + +} \ No newline at end of file diff --git a/GameFiles/Resources/Nav.cs b/GameFiles/Resources/Nav.cs new file mode 100644 index 0000000..2284c4c --- /dev/null +++ b/GameFiles/Resources/Nav.cs @@ -0,0 +1,803 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//now with enhanced uglification for codewalker + + +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class NavMesh : ResourceFileBase + { + public override long BlockLength + { + get { return 368; } + } + + + public NavMeshFlags ContentFlags { get; set; } + public uint VersionUnk1 { get; set; } // 0x00010011 + public uint Unused_018h { get; set; } // 0x00000000 + public uint Unused_01Ch { get; set; } // 0x00000000 + public Matrix Transform { get; set; } //(1,0,0,NaN),(0,1,0,NaN),(0,0,1,NaN),(0,0,0,NaN) + public Vector3 AABBSize { get; set; } + public float AABBUnk { get; set; } // 0x7F800001 //NaN + public ulong VerticesPointer { get; set; } + public uint Unused_078h { get; set; } // 0x00000000 + public uint Unused_07Ch { get; set; } // 0x00000000 + public ulong IndicesPointer { get; set; } + public ulong AdjPolysPointer { get; set; } + public uint AdjPolysIndicesCount { get; set; } + public NavMeshUintArray AdjAreaIDs { get; set; } + public ulong PolysPointer { get; set; } + public ulong SectorTreePointer { get; set; } + public ulong PortalsPointer { get; set; } + public ulong PortalLinksPointer { get; set; } + public uint VerticesCount { get; set; } + public uint PolysCount { get; set; } + public uint AreaID { get; set; } // X + Y*100 + public uint TotalBytes { get; set; } + public uint SectorUnkCount { get; set; } + public uint PortalsCount { get; set; } + public uint PortalLinksCount { get; set; } + public uint Unused_154h { get; set; } // 0x00000000 + public uint Unused_158h { get; set; } // 0x00000000 + public uint Unused_15Ch { get; set; } // 0x00000000 + public uint VersionUnk2 { get; set; } //2244687201 (0x85CB3561) for grid ynv's + public uint Unused_164h { get; set; } // 0x00000000 + public uint Unused_168h { get; set; } // 0x00000000 + public uint Unused_16Ch { get; set; } // 0x00000000 + + + public NavMeshList Vertices { get; set; } + public NavMeshList Indices { get; set; } + public NavMeshList AdjPolys { get; set; } + public NavMeshList Polys { get; set; } + public NavMeshSector SectorTree { get; set; } + public NavMeshPortal[] Portals { get; set; } + public ushort[] PortalLinks { get; set; } + + + + + private ResourceSystemStructBlock PortalsBlock = null; + private ResourceSystemStructBlock PortalLinksBlock = null; + + + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + ContentFlags = (NavMeshFlags)reader.ReadUInt32(); + VersionUnk1 = reader.ReadUInt32(); + Unused_018h = reader.ReadUInt32(); + Unused_01Ch = reader.ReadUInt32(); + Transform = reader.ReadMatrix(); + AABBSize = reader.ReadVector3(); + AABBUnk = reader.ReadSingle(); + VerticesPointer = reader.ReadUInt64(); + Unused_078h = reader.ReadUInt32(); + Unused_07Ch = reader.ReadUInt32(); + IndicesPointer = reader.ReadUInt64(); + AdjPolysPointer = reader.ReadUInt64(); + AdjPolysIndicesCount = reader.ReadUInt32(); + AdjAreaIDs = reader.ReadStruct(); + PolysPointer = reader.ReadUInt64(); + SectorTreePointer = reader.ReadUInt64(); + PortalsPointer = reader.ReadUInt64(); + PortalLinksPointer = reader.ReadUInt64(); + VerticesCount = reader.ReadUInt32(); + PolysCount = reader.ReadUInt32(); + AreaID = reader.ReadUInt32(); + TotalBytes = reader.ReadUInt32(); + SectorUnkCount = reader.ReadUInt32(); + PortalsCount = reader.ReadUInt32(); + PortalLinksCount = reader.ReadUInt32(); + Unused_154h = reader.ReadUInt32(); + Unused_158h = reader.ReadUInt32(); + Unused_15Ch = reader.ReadUInt32(); + VersionUnk2 = reader.ReadUInt32(); + Unused_164h = reader.ReadUInt32(); + Unused_168h = reader.ReadUInt32(); + Unused_16Ch = reader.ReadUInt32(); + + + + Vertices = reader.ReadBlockAt>(VerticesPointer); + Indices = reader.ReadBlockAt>(IndicesPointer); + AdjPolys = reader.ReadBlockAt>(AdjPolysPointer); + Polys = reader.ReadBlockAt>(PolysPointer); + SectorTree = reader.ReadBlockAt(SectorTreePointer); + Portals = reader.ReadStructsAt(PortalsPointer, PortalsCount); + PortalLinks = reader.ReadUshortsAt(PortalLinksPointer, PortalLinksCount); + + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + VerticesPointer = (ulong)(Vertices != null ? Vertices.FilePosition : 0); + IndicesPointer = (ulong)(Indices != null ? Indices.FilePosition : 0); + AdjPolysPointer = (ulong)(AdjPolys != null ? AdjPolys.FilePosition : 0); + PolysPointer = (ulong)(Polys != null ? Polys.FilePosition : 0); + SectorTreePointer = (ulong)(SectorTree != null ? SectorTree.FilePosition : 0); + PortalsPointer = (ulong)(PortalsBlock?.FilePosition ?? 0); + PortalLinksPointer = (ulong)(PortalLinksBlock?.FilePosition ?? 0); + + + + writer.Write((uint)ContentFlags); + writer.Write(VersionUnk1); + writer.Write(Unused_018h); + writer.Write(Unused_01Ch); + writer.Write(Transform); + writer.Write(AABBSize); + writer.Write(AABBUnk); + writer.Write(VerticesPointer); + writer.Write(Unused_078h); + writer.Write(Unused_07Ch); + writer.Write(IndicesPointer); + writer.Write(AdjPolysPointer); + writer.Write(AdjPolysIndicesCount); + writer.WriteStruct(AdjAreaIDs); + writer.Write(PolysPointer); + writer.Write(SectorTreePointer); + writer.Write(PortalsPointer); + writer.Write(PortalLinksPointer); + writer.Write(VerticesCount); + writer.Write(PolysCount); + writer.Write(AreaID); + writer.Write(TotalBytes); + writer.Write(SectorUnkCount); + writer.Write(PortalsCount); + writer.Write(PortalLinksCount); + writer.Write(Unused_154h); + writer.Write(Unused_158h); + writer.Write(Unused_15Ch); + writer.Write(VersionUnk2); + writer.Write(Unused_164h); + writer.Write(Unused_168h); + writer.Write(Unused_16Ch); + } + + + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if (Vertices != null) list.Add(Vertices); + if (Indices != null) list.Add(Indices); + if (AdjPolys != null) list.Add(AdjPolys); + if (Polys != null) list.Add(Polys); + if (SectorTree != null) list.Add(SectorTree); + + if ((Portals != null) && (Portals.Length > 0)) + { + PortalsBlock = new ResourceSystemStructBlock(Portals); + list.Add(PortalsBlock); + } + + if ((PortalLinks != null) && (PortalLinks.Length > 0)) + { + PortalLinksBlock = new ResourceSystemStructBlock(PortalLinks); + list.Add(PortalLinksBlock); + } + + + + + return list.ToArray(); + } + + + public override string ToString() + { + return "(Size: " + FloatUtil.GetVector3String(AABBSize) + ")"; + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshUintArray + { + public uint Count { get; set; } + public uint v00; + public uint v01; + public uint v02; + public uint v03; + public uint v04; + public uint v05; + public uint v06; // 0x00000000 + public uint v07; // 0x00000000 + public uint v08; // 0x00000000 + public uint v09; // 0x00000000 + public uint v10; // 0x00000000 + public uint v11; // 0x00000000 + public uint v12; // 0x00000000 + public uint v13; // 0x00000000 + public uint v14; // 0x00000000 + public uint v15; // 0x00000000 + public uint v16; // 0x00000000 + public uint v17; // 0x00000000 + public uint v18; // 0x00000000 + public uint v19; // 0x00000000 + public uint v20; // 0x00000000 + public uint v21; // 0x00000000 + public uint v22; // 0x00000000 + public uint v23; // 0x00000000 + public uint v24; // 0x00000000 + public uint v25; // 0x00000000 + public uint v26; // 0x00000000 + public uint v27; // 0x00000000 + public uint v28; // 0x00000000 + public uint v29; // 0x00000000 + public uint v30; // 0x00000000 + public uint v31; // 0x00000000 + + public uint[] RawValues + { + get + { + return new[]{ v00,v01,v02,v03,v04,v05,v06,v07,v08,v09, + v10,v11,v12,v13,v14,v15,v16,v17,v18,v19, + v20,v21,v22,v23,v24,v25,v26,v27,v28,v29, + v30,v31 }; + } + } + + public uint[] Values + { + get + { + uint[] vals = new uint[Count]; + uint[] rvals = RawValues; + for (int i = 0; i < Count; i++) + { + vals[i] = rvals[i]; + } + return vals; + } + } + + + public override string ToString() + { + return "(Count: " + Count.ToString() + ")"; + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class NavMeshList : ResourceSystemBlock where T : struct + { + public override long BlockLength + { + get { return 48; } + } + + public uint VFT { get; set; } + public uint Unknown_04h { get; set; } // 0x00000001 + public uint ItemCount { get; set; } + public uint Unknown_0Ch { get; set; } // 0x00000000 + public ulong ListPartsPointer { get; set; } + public ulong ListOffsetsPointer { get; set; } + public uint ListPartsCount { get; set; } + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + public ResourceSimpleArray> ListParts { get; set; } + public uint[] ListOffsets { get; set; } + + private ResourceSystemStructBlock ListOffsetsBlock = null; + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + VFT = reader.ReadUInt32(); + Unknown_04h = reader.ReadUInt32(); + ItemCount = reader.ReadUInt32(); + Unknown_0Ch = reader.ReadUInt32(); + ListPartsPointer = reader.ReadUInt64(); + ListOffsetsPointer = reader.ReadUInt64(); + ListPartsCount = reader.ReadUInt32(); + Unknown_24h = reader.ReadUInt32(); + Unknown_28h = reader.ReadUInt32(); + Unknown_2Ch = reader.ReadUInt32(); + + ListParts = reader.ReadBlockAt>>(ListPartsPointer, ListPartsCount); + ListOffsets = reader.ReadUintsAt(ListOffsetsPointer, ListPartsCount); + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + ListPartsPointer = (ulong)(ListParts != null ? ListParts.FilePosition : 0); + ListOffsetsPointer = (ulong)(ListOffsetsBlock?.FilePosition ?? 0); + ListPartsCount = (uint)(ListParts != null ? ListParts.Count : 0); + + writer.Write(VFT); + writer.Write(Unknown_04h); + writer.Write(ItemCount); + writer.Write(Unknown_0Ch); + writer.Write(ListPartsPointer); + writer.Write(ListOffsetsPointer); + writer.Write(ListPartsCount); + writer.Write(Unknown_24h); + writer.Write(Unknown_28h); + writer.Write(Unknown_2Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (ListParts != null) list.Add(ListParts); + + if ((ListOffsets != null) && (ListOffsets.Length > 0)) + { + ListOffsetsBlock = new ResourceSystemStructBlock(ListOffsets); + list.Add(ListOffsetsBlock); + } + + return list.ToArray(); + } + + + + public List GetFullList() + { + List list = new List((int)ItemCount); + + if (ListParts != null) + { + foreach (var part in ListParts) + { + if (part.Items != null) + { + list.AddRange(part.Items); + } + } + } + + return list; + } + + + + public override string ToString() + { + return "(" + ItemCount.ToString() + " total items, " + ListPartsCount.ToString() + " parts)"; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class NavMeshListPart : ResourceSystemBlock where T : struct + { + public override long BlockLength + { + get { return 16; } + } + + public ulong Pointer { get; set; } + public uint Count { get; set; } + public uint Unknown_0Ch { get; set; } // 0x00000000 + + public T[] Items { get; set; } + + private ResourceSystemStructBlock ItemsBlock = null; + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + Pointer = reader.ReadUInt64(); + Count = reader.ReadUInt32(); + Unknown_0Ch = reader.ReadUInt32(); + + Items = reader.ReadStructsAt(Pointer, Count); + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + Pointer = (ulong)(ItemsBlock?.FilePosition ?? 0); + Count = (uint)(Items?.Length ?? 0); + + writer.Write(Pointer); + writer.Write(Count); + writer.Write(Unknown_0Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + + if ((Items != null) && (Items.Length > 0)) + { + ItemsBlock = new ResourceSystemStructBlock(Items); + list.Add(ItemsBlock); + } + + return list.ToArray(); + } + + public override string ToString() + { + return "(" + Count.ToString() + " items)"; + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshVertex + { + public ushort X { get; set; } + public ushort Y { get; set; } + public ushort Z { get; set; } + + + public Vector3 ToVector3() + { + const float usmax = (float)ushort.MaxValue; + return new Vector3(X / usmax, Y / usmax, Z / usmax); + } + + public override string ToString() + { + return X.ToString() + ", " + Y.ToString() + ", " + Z.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAABB + { + public short MinX { get; set; } + public short MaxX { get; set; } + public short MinY { get; set; } + public short MaxY { get; set; } + public short MinZ { get; set; } + public short MaxZ { get; set; } + + public Vector3 Min { get { return new Vector3(MinX / 4.0f, MinY / 4.0f, MinZ / 4.0f); } } + public Vector3 Max { get { return new Vector3(MaxX / 4.0f, MaxY / 4.0f, MaxZ / 4.0f); } } + + public override string ToString() + { + Vector3 min = Min; + Vector3 max = Max; + return string.Format("({0}, {1}, {2}) | ({3}, {4}, {5})", min.X, min.Y, min.Z, max.X, max.Y, max.Z); + //return string.Format("({0}, {1}, {2}) | ({3}, {4}, {5})", MinX, MinY, MinZ, MaxX, MaxY, MaxZ); + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPoly + { + public NavMeshAdjPolyPart Unknown_0h { get; set; } + public NavMeshAdjPolyPart Unknown_4h { get; set; } + + public override string ToString() + { + return Unknown_0h.Bin + " | " + Unknown_4h.Bin + " | " + + Unknown_0h.ToString() + " | " + Unknown_4h.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPolyPart + { + public uint Value { get; set; } + + public string Bin + { + get + { + return Convert.ToString(Value, 2).PadLeft(32, '0'); + } + } + + public uint AdjAreaIDInd { get { return (Value >> 0) & 0x1F; } } + public uint PolyID { get { return (Value >> 5) & 0x3FFF; } } + public uint Unk2 { get { return (Value >> 19) & 0x3; } } + public uint Unk3 { get { return (Value >> 21); } } + + public override string ToString() + { + return AdjAreaIDInd.ToString() + ", " + PolyID.ToString() + ", " + Unk2.ToString() + ", " + Unk3.ToString(); + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPoly + { + public ushort Unknown_00h { get; set; } + public ushort IndexFlags { get; set; } + public ushort IndexID { get; set; } + public ushort AreaID { get; set; } + public uint Unused_08h { get; set; } // 0x00000000 + public uint Unused_0Ch { get; set; } // 0x00000000 + public uint Unused_10h { get; set; } // 0x00000000 + public uint Unused_14h { get; set; } // 0x00000000 + public NavMeshAABB CellAABB { get; set; } + public FlagsUint Unknown_24h { get; set; } + public FlagsUint Unknown_28h { get; set; } + public ushort PartFlags { get; set; } + public ushort PortalID { get; set; } + + + //public int IndexUnk { get { return (IndexFlags >> 0) & 31; } } //always 0 + public int IndexCount { get { return (IndexFlags >> 5); } } + + //public int PartUnk1 { get { return (PartFlags >> 0) & 0xF; } } //always 0 + public int PartID { get { return (PartFlags >> 4) & 0xFF; } } + public int PartUnk2 { get { return (PartFlags >> 12) & 0xF; } } + + + public uint Unknown_28h_16 { get { return ((Unknown_28h.Value & 65535)); } } + public uint Unknown_28h_8a { get { return ((Unknown_28h.Value >> 0) & 255); } } + public uint Unknown_28h_8b { get { return ((Unknown_28h.Value >> 8) & 255); } } + + + public override string ToString() + { + return + //Unknown_28h.Bin + ", (" + Unknown_28h_8a.ToString() + ", " + Unknown_28h_8b.ToString() + "), " + + Unknown_00h.ToString() + ", " + + //IndexFlags.ToString() + ", " + + IndexCount.ToString() + ", " + //IndexUnk.ToString() + ", " + + IndexID.ToString() + ", " + AreaID.ToString() + ", " + + CellAABB.ToString() + ", " + + Unknown_24h.Hex + ", " + + Unknown_28h.Hex + ", " + + //PartFlags.ToString() + ", " + //PartUnk1.ToString() + ", " + + PartID.ToString() + ", " + + PartUnk2.ToString() + ", " + + PortalID.ToString(); + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class NavMeshSector : ResourceSystemBlock + { + public override long BlockLength + { + get { return 96; } + } + + public Vector4 AABBMin { get; set; } //W==NaN + public Vector4 AABBMax { get; set; } //W==NaN + public NavMeshAABB CellAABB { get; set; } + public ulong DataPointer { get; set; } + public ulong SubTree1Pointer { get; set; } + public ulong SubTree2Pointer { get; set; } + public ulong SubTree3Pointer { get; set; } + public ulong SubTree4Pointer { get; set; } + public uint Unused_54h { get; set; } // 0x00000000 + public uint Unused_58h { get; set; } // 0x00000000 + public uint Unused_5Ch { get; set; } // 0x00000000 + + public NavMeshSectorData Data { get; set; } + public NavMeshSector SubTree1 { get; set; } + public NavMeshSector SubTree2 { get; set; } + public NavMeshSector SubTree3 { get; set; } + public NavMeshSector SubTree4 { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + AABBMin = reader.ReadVector4(); + AABBMax = reader.ReadVector4(); + CellAABB = reader.ReadStruct(); + DataPointer = reader.ReadUInt64(); + SubTree1Pointer = reader.ReadUInt64(); + SubTree2Pointer = reader.ReadUInt64(); + SubTree3Pointer = reader.ReadUInt64(); + SubTree4Pointer = reader.ReadUInt64(); + Unused_54h = reader.ReadUInt32(); + Unused_58h = reader.ReadUInt32(); + Unused_5Ch = reader.ReadUInt32(); + + Data = reader.ReadBlockAt(DataPointer); + SubTree1 = reader.ReadBlockAt(SubTree1Pointer); + SubTree2 = reader.ReadBlockAt(SubTree2Pointer); + SubTree3 = reader.ReadBlockAt(SubTree3Pointer); + SubTree4 = reader.ReadBlockAt(SubTree4Pointer); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + DataPointer = (ulong)(Data != null ? Data.FilePosition : 0); + SubTree1Pointer = (ulong)(SubTree1 != null ? SubTree1.FilePosition : 0); + SubTree2Pointer = (ulong)(SubTree2 != null ? SubTree2.FilePosition : 0); + SubTree3Pointer = (ulong)(SubTree3 != null ? SubTree3.FilePosition : 0); + SubTree4Pointer = (ulong)(SubTree4 != null ? SubTree4.FilePosition : 0); + + writer.Write(AABBMin); + writer.Write(AABBMax); + writer.WriteStruct(CellAABB); + writer.Write(DataPointer); + writer.Write(SubTree1Pointer); + writer.Write(SubTree2Pointer); + writer.Write(SubTree3Pointer); + writer.Write(SubTree4Pointer); + writer.Write(Unused_54h); + writer.Write(Unused_58h); + writer.Write(Unused_5Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Data != null) list.Add(Data); + if (SubTree1 != null) list.Add(SubTree1); + if (SubTree2 != null) list.Add(SubTree2); + if (SubTree3 != null) list.Add(SubTree3); + if (SubTree4 != null) list.Add(SubTree4); + return list.ToArray(); + } + + + public override string ToString() + { + return "[Min: "+AABBMin.ToString() + "], [Max:" + AABBMax.ToString() + "]"; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class NavMeshSectorData : ResourceSystemBlock + { + public override long BlockLength + { + get { return 32; } + } + + public uint UnkOffset { get; set; } + public uint Unused_04h { get; set; } // 0x00000000 + public ulong PolyIDsPointer { get; set; } + public ulong UnkDataPointer { get; set; } + public ushort PolyIDsCount { get; set; } + public ushort UnkDataCount { get; set; } + public uint Unused_1Ch { get; set; } // 0x00000000 + + public ushort[] PolyIDs { get; set; } + public NavMeshSectorDataUnk[] UnkData { get; set; } + + private ResourceSystemStructBlock PolyIDsBlock = null; + private ResourceSystemStructBlock UnkDataBlock = null; + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + UnkOffset = reader.ReadUInt32(); + Unused_04h = reader.ReadUInt32(); + PolyIDsPointer = reader.ReadUInt64(); + UnkDataPointer = reader.ReadUInt64(); + PolyIDsCount = reader.ReadUInt16(); + UnkDataCount = reader.ReadUInt16(); + Unused_1Ch = reader.ReadUInt32(); + + PolyIDs = reader.ReadUshortsAt(PolyIDsPointer, PolyIDsCount); + UnkData = reader.ReadStructsAt(UnkDataPointer, UnkDataCount); + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + PolyIDsPointer = (ulong)(PolyIDsBlock?.FilePosition ?? 0); + PolyIDsCount = (ushort)(PolyIDs?.Length ?? 0); + UnkDataPointer = (ulong)(UnkDataBlock?.FilePosition ?? 0); + UnkDataCount = (ushort)(UnkData?.Length ?? 0); + + + writer.Write(UnkOffset); + writer.Write(Unused_04h); + writer.Write(PolyIDsPointer); + writer.Write(UnkDataPointer); + writer.Write(PolyIDsCount); + writer.Write(UnkDataCount); + writer.Write(Unused_1Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + + if ((PolyIDs != null) && (PolyIDs.Length > 0)) + { + PolyIDsBlock = new ResourceSystemStructBlock(PolyIDs); + list.Add(PolyIDsBlock); + } + if ((UnkData != null) && (UnkData.Length > 0)) + { + UnkDataBlock = new ResourceSystemStructBlock(UnkData); + list.Add(UnkDataBlock); + } + + + return list.ToArray(); + } + + public override string ToString() + { + return "(Polys: " + PolyIDsCount.ToString() + ", UnkOffset: " + UnkOffset.ToString() + ", UnkCount: " + UnkDataCount.ToString() + ")"; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshSectorDataUnk + { + public ushort Unknown_0h { get; set; } + public ushort Unknown_2h { get; set; } + public ushort Unknown_4h { get; set; } + public ushort Unknown_6h { get; set; } + + public override string ToString() + { + return Unknown_0h.ToString() + ", " + Unknown_2h.ToString() + ", " + Unknown_4h.ToString() + ", " + Unknown_6h.ToString(); + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPortal + { + public uint Unknown_00h { get; set; } + public NavMeshVertex Position1 { get; set; } + public NavMeshVertex Position2 { get; set; } + public ushort Unknown_10h { get; set; } + public ushort Unknown_12h { get; set; } + public ushort Unknown_14h { get; set; } + public ushort Unknown_16h { get; set; } + public ushort Unknown_18h { get; set; } + public ushort Unknown_1Ah { get; set; } + //public NavMeshAABB AABB1 { get; set; } + //public NavMeshAABB AABB2 { get; set; } + + public override string ToString() + { + return Unknown_00h.ToString() + ", " + + Position1.ToString() + ", " + Position2.ToString() + ", " + + Unknown_10h.ToString() + ", " + Unknown_12h.ToString() + ", " + + Unknown_14h.ToString() + ", " + Unknown_16h.ToString() + ", " + + Unknown_18h.ToString() + ", " + Unknown_1Ah.ToString(); + //AABB1.ToString() + ", " + AABB2.ToString(); + } + } + + + + + [Flags] public enum NavMeshFlags : uint + { + Vertices = 1, + Portals = 2, + Vehicle = 4, + Unknown8 = 8, + } + + +} diff --git a/GameFiles/Resources/Node.cs b/GameFiles/Resources/Node.cs new file mode 100644 index 0000000..3acfccb --- /dev/null +++ b/GameFiles/Resources/Node.cs @@ -0,0 +1,280 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//mangled to fit + + +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +namespace CodeWalker.GameFiles +{ + [TypeConverter(typeof(ExpandableObjectConverter))] public class NodeDictionary : ResourceFileBase + { + public override long BlockLength + { + get { return 112; } + } + + public ulong NodesPointer { get; set; } + public uint NodesCount { get; set; } + public uint NodesCountVehicle { get; set; } + public uint NodesCountPed { get; set; } + public uint Unk24 { get; set; } // 0x00000000 + public ulong LinksPtr { get; set; } + public uint LinksCount { get; set; } + public uint Unk34 { get; set; } // 0x00000000 + public ulong JunctionsPtr { get; set; } + public ulong JunctionHeightmapBytesPtr { get; set; } + public uint Unk48 { get; set; } = 1; // 0x00000001 + public uint Unk4C { get; set; } // 0x00000000 + public ulong JunctionRefsPtr { get; set; } + public ushort JunctionRefsCount0 { get; set; } + public ushort JunctionRefsCount1 { get; set; } // same as JunctionRefsCount0 + public uint Unk5C { get; set; } // 0x00000000 + public uint JunctionsCount { get; set; } // same as JunctionRefsCount0 + public uint JunctionHeightmapBytesCount { get; set; } + public uint Unk68 { get; set; } // 0x00000000 + public uint Unk6C { get; set; } // 0x00000000 + + public Node[] Nodes { get; set; } + public NodeLink[] Links { get; set; } + public NodeJunction[] Junctions { get; set; } + public byte[] JunctionHeightmapBytes { get; set; } + public NodeJunctionRef[] JunctionRefs { get; set; } + + + private ResourceSystemStructBlock NodesBlock = null; + private ResourceSystemStructBlock LinksBlock = null; + private ResourceSystemStructBlock JunctionsBlock = null; + private ResourceSystemStructBlock JunctionHeightmapBytesBlock = null; + private ResourceSystemStructBlock JunctionRefsBlock = null; + + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + this.NodesPointer = reader.ReadUInt64(); + this.NodesCount = reader.ReadUInt32(); + this.NodesCountVehicle = reader.ReadUInt32(); + this.NodesCountPed = reader.ReadUInt32(); + this.Unk24 = reader.ReadUInt32(); + this.LinksPtr = reader.ReadUInt64(); + this.LinksCount = reader.ReadUInt32(); + this.Unk34 = reader.ReadUInt32(); + this.JunctionsPtr = reader.ReadUInt64(); + this.JunctionHeightmapBytesPtr = reader.ReadUInt64(); + this.Unk48 = reader.ReadUInt32(); + this.Unk4C = reader.ReadUInt32(); + this.JunctionRefsPtr = reader.ReadUInt64(); + this.JunctionRefsCount0 = reader.ReadUInt16(); + this.JunctionRefsCount1 = reader.ReadUInt16(); + this.Unk5C = reader.ReadUInt32(); + this.JunctionsCount = reader.ReadUInt32(); + this.JunctionHeightmapBytesCount = reader.ReadUInt32(); + this.Unk68 = reader.ReadUInt32(); + this.Unk6C = reader.ReadUInt32(); + + this.Nodes = reader.ReadStructsAt(this.NodesPointer, this.NodesCount); + this.Links = reader.ReadStructsAt(this.LinksPtr, this.LinksCount); + this.Junctions = reader.ReadStructsAt(this.JunctionsPtr, this.JunctionsCount); + this.JunctionHeightmapBytes = reader.ReadBytesAt(this.JunctionHeightmapBytesPtr, this.JunctionHeightmapBytesCount); + this.JunctionRefs = reader.ReadStructsAt(this.JunctionRefsPtr, this.JunctionRefsCount1); + + + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + NodesPointer = (ulong)(NodesBlock?.FilePosition ?? 0); + NodesCount = (uint)(Nodes?.Length ?? 0); //assume NodesCountVehicle and Ped already updated.. + LinksPtr = (ulong)(LinksBlock?.FilePosition ?? 0); + LinksCount = (uint)(Links?.Length ?? 0); + JunctionsPtr = (ulong)(JunctionsBlock?.FilePosition ?? 0); + JunctionHeightmapBytesPtr = (ulong)(JunctionHeightmapBytesBlock?.FilePosition ?? 0); + JunctionRefsPtr = (ulong)(JunctionRefsBlock?.FilePosition ?? 0); + JunctionRefsCount0 = (ushort)(JunctionRefs?.Length ?? 0); + JunctionRefsCount1 = JunctionRefsCount1; + JunctionsCount = (uint)(Junctions?.Length ?? 0); + JunctionHeightmapBytesCount = (uint)(JunctionHeightmapBytes?.Length ?? 0); + + + // write structure data + writer.Write(this.NodesPointer); + writer.Write(this.NodesCount); + writer.Write(this.NodesCountVehicle); + writer.Write(this.NodesCountPed); + writer.Write(this.Unk24); + writer.Write(this.LinksPtr); + writer.Write(this.LinksCount); + writer.Write(this.Unk34); + writer.Write(this.JunctionsPtr); + writer.Write(this.JunctionHeightmapBytesPtr); + writer.Write(this.Unk48); + writer.Write(this.Unk4C); + writer.Write(this.JunctionRefsPtr); + writer.Write(this.JunctionRefsCount0); + writer.Write(this.JunctionRefsCount1); + writer.Write(this.Unk5C); + writer.Write(this.JunctionsCount); + writer.Write(this.JunctionHeightmapBytesCount); + writer.Write(this.Unk68); + writer.Write(this.Unk6C); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + + if ((JunctionRefs != null) && (JunctionRefs.Length > 0)) + { + JunctionRefsBlock = new ResourceSystemStructBlock(JunctionRefs); + list.Add(JunctionRefsBlock); + } + if ((JunctionHeightmapBytes != null) && (JunctionHeightmapBytes.Length > 0)) + { + JunctionHeightmapBytesBlock = new ResourceSystemStructBlock(JunctionHeightmapBytes); + list.Add(JunctionHeightmapBytesBlock); + } + if ((Junctions != null) && (Junctions.Length > 0)) + { + JunctionsBlock = new ResourceSystemStructBlock(Junctions); + list.Add(JunctionsBlock); + } + if ((Links != null) && (Links.Length > 0)) + { + LinksBlock = new ResourceSystemStructBlock(Links); + list.Add(LinksBlock); + } + if ((Nodes != null) && (Nodes.Length > 0)) + { + NodesBlock = new ResourceSystemStructBlock(Nodes); + list.Add(NodesBlock); + } + + + return list.ToArray(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct Node + { + public uint Unused0 { get; set; } // 0x00000000 + public uint Unused1 { get; set; } // 0x00000000 + public uint Unused2 { get; set; } // 0x00000000 + public uint Unused3 { get; set; } // 0x00000000 + public ushort AreaID { get; set; } + public ushort NodeID { get; set; } + public TextHash StreetName { get; set; } + public ushort Unused4 { get; set; } + public ushort LinkID { get; set; } + public short PositionX { get; set; } + public short PositionY { get; set; } + public FlagsByte Flags0 { get; set; } + public FlagsByte Flags1 { get; set; } + public short PositionZ { get; set; } + public FlagsByte Flags2 { get; set; } + public FlagsByte LinkCountFlags { get; set; } + public FlagsByte Flags3 { get; set; } + public FlagsByte Flags4 { get; set; } + + public override string ToString() + { + //return Unused0.ToString() + ", " + Unused1.ToString() + ", " + Unused2.ToString() + ", " + + // Unused3.ToString() + ", " + AreaID.ToString() + ", " + NodeID.ToString() + ", " + + // UnknownInterp.ToString() + ", " + HeuristicCost.ToString() + ", " + LinkID.ToString() + ", " + + // PositionX.ToString() + ", " + PositionY.ToString() + ", " + Unk20.ToString() + ", " + Unk21.ToString() + ", " + + // Unk22.ToString() + ", " + Unk24.ToString() + ", " + Unk26.ToString(); + + return AreaID.ToString() + ", " + NodeID.ToString() + ", " + StreetName.ToString();// + ", X:" + + //PositionX.ToString() + ", Y:" + PositionY.ToString() + ", " + PositionZ.ToString();// + ", " + + //Flags0.ToString() + ", " + Flags1.ToString() + ", Z:" + + //Flags2.ToString() + ", " + LinkCountFlags.ToString() + ", " + + //Flags3.ToString() + ", " + Flags4.ToString(); + + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NodeLink + { + public ushort AreaID { get; set; } + public ushort NodeID { get; set; } + public FlagsByte Flags0 { get; set; } + public FlagsByte Flags1 { get; set; } + public FlagsByte Flags2 { get; set; } + public FlagsByte LinkLength { get; set; } + + public override string ToString() + { + return AreaID.ToString() + ", " + NodeID.ToString() + ", " + Flags0.Value.ToString() + ", " + Flags1.Value.ToString() + ", " + Flags2.Value.ToString() + ", " + LinkLength.Value.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NodeJunction + { + public short MaxZ { get; set; } + public short PositionX { get; set; } + public short PositionY { get; set; } + public short MinZ { get; set; } + public ushort HeightmapPtr { get; set; } + public byte HeightmapDimX { get; set; } + public byte HeightmapDimY { get; set; } + + public override string ToString() + { + return PositionX.ToString() + ", " + PositionY.ToString() + ": " + MinZ.ToString() + ", " + MaxZ.ToString() + ": " + HeightmapDimX.ToString() + " x " + HeightmapDimY.ToString(); + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NodeJunctionRef + { + public ushort AreaID { get; set; } + public ushort NodeID { get; set; } + public ushort JunctionID { get; set; } + public ushort Unk0 { get; set; } + + public override string ToString() + { + return AreaID.ToString() + ", " + NodeID.ToString() + ", " + JunctionID.ToString(); + } + } + + + + + + + + +} \ No newline at end of file diff --git a/GameFiles/Resources/Particle.cs b/GameFiles/Resources/Particle.cs new file mode 100644 index 0000000..37a0bef --- /dev/null +++ b/GameFiles/Resources/Particle.cs @@ -0,0 +1,4303 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TC = System.ComponentModel.TypeConverterAttribute; +using EXP = System.ComponentModel.ExpandableObjectConverter; + + +/* + Copyright(c) 2017 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + + + //proudly mangled by dex + +*/ + + + +namespace CodeWalker.GameFiles +{ + + // pgBase + // ptxFxList + [TC(typeof(EXP))] public class ParticleEffectsList : ResourceFileBase + { + public override long BlockLength => 0x60; + + // structure data + public ulong NamePointer { get; set; } + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong TextureDictionaryPointer { get; set; } + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ulong DrawableDictionaryPointer { get; set; } + public ulong ParticleRuleDictionaryPointer { get; set; } + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public ulong EmitterRuleDictionaryPointer { get; set; } + public ulong EffectRuleDictionaryPointer { get; set; } + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + + // reference data + public string_r Name { get; set; } + public TextureDictionary TextureDictionary { get; set; } + public DrawableDictionary DrawableDictionary { get; set; } + public ParticleRuleDictionary ParticleRuleDictionary { get; set; } + public ParticleEffectRuleDictionary EffectRuleDictionary { get; set; } + public ParticleEmitterRuleDictionary EmitterRuleDictionary { get; set; } + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.NamePointer = reader.ReadUInt64(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.TextureDictionaryPointer = reader.ReadUInt64(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.DrawableDictionaryPointer = reader.ReadUInt64(); + this.ParticleRuleDictionaryPointer = reader.ReadUInt64(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.EmitterRuleDictionaryPointer = reader.ReadUInt64(); + this.EffectRuleDictionaryPointer = reader.ReadUInt64(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + + // read reference data + this.Name = reader.ReadBlockAt( + this.NamePointer // offset + ); + this.TextureDictionary = reader.ReadBlockAt( + this.TextureDictionaryPointer // offset + ); + this.DrawableDictionary = reader.ReadBlockAt( + this.DrawableDictionaryPointer // offset + ); + this.ParticleRuleDictionary = reader.ReadBlockAt( + this.ParticleRuleDictionaryPointer // offset + ); + this.EffectRuleDictionary = reader.ReadBlockAt( + this.EmitterRuleDictionaryPointer // offset + ); + this.EmitterRuleDictionary = reader.ReadBlockAt( + this.EffectRuleDictionaryPointer // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0);//TODO: fix?! + //this.TextureDictionaryPointer = (ulong)(this.TextureDictionary != null ? this.TextureDictionary.Position : 0); + //this.DrawableDictionaryPointer = (ulong)(this.DrawableDictionary != null ? this.DrawableDictionary.Position : 0); + //this.ParticleRuleDictionaryPointer = (ulong)(this.ParticleRuleDictionary != null ? this.ParticleRuleDictionary.Position : 0); + //this.EmitterRuleDictionaryPointer = (ulong)(this.EffectRuleDictionary != null ? this.EffectRuleDictionary.Position : 0); + //this.EffectRuleDictionaryPointer = (ulong)(this.EmitterRuleDictionary != null ? this.EmitterRuleDictionary.Position : 0); + + // write structure data + writer.Write(this.NamePointer); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.TextureDictionaryPointer); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.DrawableDictionaryPointer); + writer.Write(this.ParticleRuleDictionaryPointer); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.EmitterRuleDictionaryPointer); + writer.Write(this.EffectRuleDictionaryPointer); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); //TODO: fix!! + //if (Name != null) list.Add(Name); + //if (TextureDictionary != null) list.Add(TextureDictionary); + //if (DrawableDictionary != null) list.Add(DrawableDictionary); + //if (ParticleRuleDictionary != null) list.Add(ParticleRuleDictionary); + //if (EffectRuleDictionary != null) list.Add(EffectRuleDictionary); + //if (EmitterRuleDictionary != null) list.Add(EmitterRuleDictionary); + return list.ToArray(); + } + } + + + + + + // pgBase + // pgDictionaryBase + // pgDictionary + [TC(typeof(EXP))] public class ParticleRuleDictionary : ResourceSystemBlock + { + public override long BlockLength => 0x40; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000001 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ResourceSimpleList64 ParticleRuleNameHashes { get; set; } + public ResourcePointerList64 ParticleRules { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.ParticleRuleNameHashes = reader.ReadBlock>(); + this.ParticleRules = reader.ReadBlock>(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.WriteBlock(this.ParticleRuleNameHashes); + writer.WriteBlock(this.ParticleRules); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0x20, ParticleRuleNameHashes), + new Tuple(0x30, ParticleRules) + }; + } + } + + + + + + // pgBase + // pgDictionaryBase + // pgDictionary + [TC(typeof(EXP))] public class ParticleEffectRuleDictionary : ResourceSystemBlock + { + public override long BlockLength => 0x40; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000001 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ResourceSimpleList64 EffectRuleNameHashes { get; set; } + public ResourcePointerList64 EffectRules { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.EffectRuleNameHashes = reader.ReadBlock>(); + this.EffectRules = reader.ReadBlock>(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.WriteBlock(this.EffectRuleNameHashes); + writer.WriteBlock(this.EffectRules); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0x20, EffectRuleNameHashes), + new Tuple(0x30, EffectRules) + }; + } + } + + + + + + // pgBase + // pgDictionaryBase + // pgDictionary + [TC(typeof(EXP))] public class ParticleEmitterRuleDictionary : ResourceSystemBlock + { + public override long BlockLength => 0x40; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000001 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong HashesPointer { get; set; } + public ushort HashesCount1 { get; set; } + public ushort HashesCount2 { get; set; } + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ulong EffectRulesPointer { get; set; } + public ushort EffectRulesCount1 { get; set; } + public ushort EffectRulesCount2 { get; set; } + public uint Unknown_3Ch { get; set; } // 0x00000000 + + // reference data + public ResourceSimpleArray Hashes { get; set; } + public ResourcePointerArray64 EmitterRules { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.HashesPointer = reader.ReadUInt64(); + this.HashesCount1 = reader.ReadUInt16(); + this.HashesCount2 = reader.ReadUInt16(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.EffectRulesPointer = reader.ReadUInt64(); + this.EffectRulesCount1 = reader.ReadUInt16(); + this.EffectRulesCount2 = reader.ReadUInt16(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + this.Hashes = reader.ReadBlockAt>( + this.HashesPointer, // offset + this.HashesCount1 + ); + this.EmitterRules = reader.ReadBlockAt>( + this.EffectRulesPointer, // offset + this.EffectRulesCount1 + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.HashesPointer = (ulong)(this.Hashes != null ? this.Hashes.Position : 0); + ////this.HashesCount1 = (ushort)(this.Hashes != null ? this.Hashes.Count : 0); + //this.EffectRulesPointer = (ulong)(this.EmitterRules != null ? this.EmitterRules.Position : 0); + ////this.EffectRulesCount1 = (ushort)(this.EffectRules != null ? this.EffectRules.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.HashesPointer); + writer.Write(this.HashesCount1); + writer.Write(this.HashesCount2); + writer.Write(this.Unknown_2Ch); + writer.Write(this.EffectRulesPointer); + writer.Write(this.EffectRulesCount1); + writer.Write(this.EffectRulesCount2); + writer.Write(this.Unknown_3Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Hashes != null) list.Add(Hashes); + if (EmitterRules != null) list.Add(EmitterRules); + return list.ToArray(); + } + } + + + + + + + + + // pgBase + // pgBaseRefCounted + // ptxParticleRule + [TC(typeof(EXP))] public class ParticleRule : ResourceSystemBlock + { + public override long BlockLength => 0x240; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ParticleEffectSpawner emb1 { get; set; } + public ParticleEffectSpawner emb2 { get; set; } + public uint Unknown_100h { get; set; } + public uint Unknown_104h { get; set; } + public uint Unknown_108h { get; set; } + public uint Unknown_10Ch { get; set; } + public uint Unknown_110h { get; set; } // 0x00000000 + public uint Unknown_114h { get; set; } + public uint Unknown_118h { get; set; } + public uint Unknown_11Ch { get; set; } + public ulong NamePointer { get; set; } + public ResourcePointerList64 Unknown_128h { get; set; } + public ResourcePointerList64 Unknown_138h { get; set; } + public ResourcePointerList64 Unknown_148h { get; set; } + public ResourcePointerList64 Unknown_158h { get; set; } + public ResourcePointerList64 Unknown_168h { get; set; } + public uint Unknown_178h { get; set; } // 0x00000000 + public uint Unknown_17Ch { get; set; } // 0x00000000 + public uint Unknown_180h { get; set; } // 0x00000000 + public uint Unknown_184h { get; set; } // 0x00000000 + public ResourceSimpleList64 Unknown_188h { get; set; } + public uint Unknown_198h { get; set; } // 0x00000000 + public uint Unknown_19Ch { get; set; } // 0x00000000 + public uint Unknown_1A0h { get; set; } // 0x00000000 + public uint Unknown_1A4h { get; set; } // 0x00000000 + public uint Unknown_1A8h { get; set; } // 0x00000000 + public uint Unknown_1ACh { get; set; } // 0x00000000 + public uint VFTx3 { get; set; } + public uint Unknown_1B4h { get; set; } // 0x00000001 + public ulong p9 { get; set; } + public ulong p10 { get; set; } + public uint Unknown_1C8h { get; set; } // 0x00000000 + public uint Unknown_1CCh { get; set; } // 0x00000000 + public uint Unknown_1D0h { get; set; } + public uint Unknown_1D4h { get; set; } // 0x00000000 + public uint VFTx4 { get; set; } + public uint Unknown_1DCh { get; set; } // 0x00000001 + public uint Unknown_1E0h { get; set; } + public uint Unknown_1E4h { get; set; } + public uint Unknown_1E8h { get; set; } + public uint Unknown_1ECh { get; set; } + public ResourcePointerList64 ShaderVars { get; set; } + public uint Unknown_200h { get; set; } // 0x00000001 + public uint Unknown_204h { get; set; } // 0x00000000 + public uint Unknown_208h { get; set; } + public uint Unknown_20Ch { get; set; } // 0x00000000 + public ResourceSimpleList64 Unknown_210h { get; set; } + public uint Unknown_220h { get; set; } + public uint Unknown_224h { get; set; } // 0x00000000 + public uint Unknown_228h { get; set; } // 0x00000000 + public uint Unknown_22Ch { get; set; } // 0x00000000 + public uint Unknown_230h { get; set; } // 0x00000000 + public uint Unknown_234h { get; set; } // 0x00000000 + public uint Unknown_238h { get; set; } // 0x00000000 + public uint Unknown_23Ch { get; set; } // 0x00000000 + + // reference data + public string_r Name { get; set; } + public string_r p9data { get; set; } + public string_r p10data { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.emb1 = reader.ReadBlock(); + this.emb2 = reader.ReadBlock(); + this.Unknown_100h = reader.ReadUInt32(); + this.Unknown_104h = reader.ReadUInt32(); + this.Unknown_108h = reader.ReadUInt32(); + this.Unknown_10Ch = reader.ReadUInt32(); + this.Unknown_110h = reader.ReadUInt32(); + this.Unknown_114h = reader.ReadUInt32(); + this.Unknown_118h = reader.ReadUInt32(); + this.Unknown_11Ch = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + this.Unknown_128h = reader.ReadBlock>(); + this.Unknown_138h = reader.ReadBlock>(); + this.Unknown_148h = reader.ReadBlock>(); + this.Unknown_158h = reader.ReadBlock>(); + this.Unknown_168h = reader.ReadBlock>(); + this.Unknown_178h = reader.ReadUInt32(); + this.Unknown_17Ch = reader.ReadUInt32(); + this.Unknown_180h = reader.ReadUInt32(); + this.Unknown_184h = reader.ReadUInt32(); + this.Unknown_188h = reader.ReadBlock>(); + this.Unknown_198h = reader.ReadUInt32(); + this.Unknown_19Ch = reader.ReadUInt32(); + this.Unknown_1A0h = reader.ReadUInt32(); + this.Unknown_1A4h = reader.ReadUInt32(); + this.Unknown_1A8h = reader.ReadUInt32(); + this.Unknown_1ACh = reader.ReadUInt32(); + this.VFTx3 = reader.ReadUInt32(); + this.Unknown_1B4h = reader.ReadUInt32(); + this.p9 = reader.ReadUInt64(); + this.p10 = reader.ReadUInt64(); + this.Unknown_1C8h = reader.ReadUInt32(); + this.Unknown_1CCh = reader.ReadUInt32(); + this.Unknown_1D0h = reader.ReadUInt32(); + this.Unknown_1D4h = reader.ReadUInt32(); + this.VFTx4 = reader.ReadUInt32(); + this.Unknown_1DCh = reader.ReadUInt32(); + this.Unknown_1E0h = reader.ReadUInt32(); + this.Unknown_1E4h = reader.ReadUInt32(); + this.Unknown_1E8h = reader.ReadUInt32(); + this.Unknown_1ECh = reader.ReadUInt32(); + this.ShaderVars = reader.ReadBlock>(); + this.Unknown_200h = reader.ReadUInt32(); + this.Unknown_204h = reader.ReadUInt32(); + this.Unknown_208h = reader.ReadUInt32(); + this.Unknown_20Ch = reader.ReadUInt32(); + this.Unknown_210h = reader.ReadBlock>(); + this.Unknown_220h = reader.ReadUInt32(); + this.Unknown_224h = reader.ReadUInt32(); + this.Unknown_228h = reader.ReadUInt32(); + this.Unknown_22Ch = reader.ReadUInt32(); + this.Unknown_230h = reader.ReadUInt32(); + this.Unknown_234h = reader.ReadUInt32(); + this.Unknown_238h = reader.ReadUInt32(); + this.Unknown_23Ch = reader.ReadUInt32(); + + // read reference data + this.Name = reader.ReadBlockAt( + this.NamePointer // offset + ); + this.p9data = reader.ReadBlockAt( + this.p9 // offset + ); + this.p10data = reader.ReadBlockAt( + this.p10 // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + //// update structure data //TODO: fix! + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); + //this.p9 = (ulong)(this.p9data != null ? this.p9data.Position : 0); + //this.p10 = (ulong)(this.p10data != null ? this.p10data.Position : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.WriteBlock(this.emb1); + writer.WriteBlock(this.emb2); + writer.Write(this.Unknown_100h); + writer.Write(this.Unknown_104h); + writer.Write(this.Unknown_108h); + writer.Write(this.Unknown_10Ch); + writer.Write(this.Unknown_110h); + writer.Write(this.Unknown_114h); + writer.Write(this.Unknown_118h); + writer.Write(this.Unknown_11Ch); + writer.Write(this.NamePointer); + writer.WriteBlock(this.Unknown_128h); + writer.WriteBlock(this.Unknown_138h); + writer.WriteBlock(this.Unknown_148h); + writer.WriteBlock(this.Unknown_158h); + writer.WriteBlock(this.Unknown_168h); + writer.Write(this.Unknown_178h); + writer.Write(this.Unknown_17Ch); + writer.Write(this.Unknown_180h); + writer.Write(this.Unknown_184h); + writer.WriteBlock(this.Unknown_188h); + writer.Write(this.Unknown_198h); + writer.Write(this.Unknown_19Ch); + writer.Write(this.Unknown_1A0h); + writer.Write(this.Unknown_1A4h); + writer.Write(this.Unknown_1A8h); + writer.Write(this.Unknown_1ACh); + writer.Write(this.VFTx3); + writer.Write(this.Unknown_1B4h); + writer.Write(this.p9); + writer.Write(this.p10); + writer.Write(this.Unknown_1C8h); + writer.Write(this.Unknown_1CCh); + writer.Write(this.Unknown_1D0h); + writer.Write(this.Unknown_1D4h); + writer.Write(this.VFTx4); + writer.Write(this.Unknown_1DCh); + writer.Write(this.Unknown_1E0h); + writer.Write(this.Unknown_1E4h); + writer.Write(this.Unknown_1E8h); + writer.Write(this.Unknown_1ECh); + writer.WriteBlock(this.ShaderVars); + writer.Write(this.Unknown_200h); + writer.Write(this.Unknown_204h); + writer.Write(this.Unknown_208h); + writer.Write(this.Unknown_20Ch); + writer.WriteBlock(this.Unknown_210h); + writer.Write(this.Unknown_220h); + writer.Write(this.Unknown_224h); + writer.Write(this.Unknown_228h); + writer.Write(this.Unknown_22Ch); + writer.Write(this.Unknown_230h); + writer.Write(this.Unknown_234h); + writer.Write(this.Unknown_238h); + writer.Write(this.Unknown_23Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Name != null) list.Add(Name); + //if (p9data != null) list.Add(p9data); + //if (p10data != null) list.Add(p10data); + return list.ToArray(); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(88, emb1), + new Tuple(96, emb2), + new Tuple(0x128, Unknown_128h), + new Tuple(0x138, Unknown_138h), + new Tuple(0x148, Unknown_148h), + new Tuple(0x158, Unknown_158h), + new Tuple(0x168, Unknown_168h), + new Tuple(0x188, Unknown_188h), + new Tuple(0x1F0, ShaderVars), + new Tuple(0x210, Unknown_210h) + }; + } + } + + + + // pgBase + // ptxEffectSpawner + [TC(typeof(EXP))] public class ParticleEffectSpawner : ResourceSystemBlock + { + public override long BlockLength => 0x70; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public uint Unknown_48h { get; set; } + public uint Unknown_4Ch { get; set; } // 0x00000000 + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public ulong EmitterRulePointer { get; set; } + public ulong p1 { get; set; } + public uint Unknown_68h { get; set; } + public uint Unknown_6Ch { get; set; } + + // reference data + public ParticleEffectRule EmitterRule { get; set; } + public string_r p1data { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.EmitterRulePointer = reader.ReadUInt64(); + this.p1 = reader.ReadUInt64(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + + // read reference data + this.EmitterRule = reader.ReadBlockAt( + this.EmitterRulePointer // offset + ); + this.p1data = reader.ReadBlockAt( + this.p1 // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data //TODO: fix!! + //this.EmitterRulePointer = (ulong)(this.EmitterRule != null ? this.EmitterRule.Position : 0); + //this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.EmitterRulePointer); + writer.Write(this.p1); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (EmitterRule != null) list.Add(EmitterRule); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + + + // pgBase + // pgBaseRefCounted + // ptxEffectRule + [TC(typeof(EXP))] public class ParticleEffectRule : ResourceSystemBlock + { + public override long BlockLength => 0x3C0; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000001 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x40866666 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong NamePointer { get; set; } + public uint Unknown_28h { get; set; } // 0x50000000 -> ".?AVptxFxList@rage@@" pointer to itself + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } // 0x00000001 + public ulong EventEmittersPointer { get; set; } + public ushort EventEmittersCount1 { get; set; } + public ushort EventEmittersCount2 { get; set; } + public uint Unknown_44h { get; set; } + public ulong p4 { get; set; } + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + public uint Unknown_60h { get; set; } // 0x00000000 + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } + public uint Unknown_70h { get; set; } + public uint Unknown_74h { get; set; } + public uint Unknown_78h { get; set; } + public uint Unknown_7Ch { get; set; } + public uint Unknown_80h { get; set; } + public uint Unknown_84h { get; set; } + public uint Unknown_88h { get; set; } + public uint Unknown_8Ch { get; set; } + public uint Unknown_90h { get; set; } + public uint Unknown_94h { get; set; } + public uint Unknown_98h { get; set; } + public uint Unknown_9Ch { get; set; } + public uint Unknown_A0h { get; set; } + public uint Unknown_A4h { get; set; } + public uint Unknown_A8h { get; set; } + public uint Unknown_ACh { get; set; } + public uint Unknown_B0h { get; set; } + public uint Unknown_B4h { get; set; } + public uint Unknown_B8h { get; set; } + public uint Unknown_BCh { get; set; } + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public ParticleKeyframeProp KeyframeProp3 { get; set; } + public ParticleKeyframeProp KeyframeProp4 { get; set; } + public ulong KeyframePropsPointer { get; set; } + public ushort KeyframePropsCount1 { get; set; } + public ushort KeyframePropsCount2 { get; set; } + public uint Unknown_39Ch { get; set; } // 0x00000000 + public uint Unknown_3A0h { get; set; } + public uint Unknown_3A4h { get; set; } // 0x00000000 + public uint Unknown_3A8h { get; set; } // 0x42C80000 + public uint Unknown_3ACh { get; set; } // 0x00000000 + public uint Unknown_3B0h { get; set; } // 0x00000000 + public uint Unknown_3B4h { get; set; } // 0x00000000 + public uint Unknown_3B8h { get; set; } // 0x00000000 + public uint Unknown_3BCh { get; set; } // 0x00000000 + + // reference data + public string_r Name { get; set; } + public ResourcePointerArray64 EventEmitters { get; set; } + public ParticleUnknown_P_004 p4data { get; set; } + public ResourcePointerArray64 KeyframeProps { get; set; } + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.EventEmittersPointer = reader.ReadUInt64(); + this.EventEmittersCount1 = reader.ReadUInt16(); + this.EventEmittersCount2 = reader.ReadUInt16(); + this.Unknown_44h = reader.ReadUInt32(); + this.p4 = reader.ReadUInt64(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + this.Unknown_90h = reader.ReadUInt32(); + this.Unknown_94h = reader.ReadUInt32(); + this.Unknown_98h = reader.ReadUInt32(); + this.Unknown_9Ch = reader.ReadUInt32(); + this.Unknown_A0h = reader.ReadUInt32(); + this.Unknown_A4h = reader.ReadUInt32(); + this.Unknown_A8h = reader.ReadUInt32(); + this.Unknown_ACh = reader.ReadUInt32(); + this.Unknown_B0h = reader.ReadUInt32(); + this.Unknown_B4h = reader.ReadUInt32(); + this.Unknown_B8h = reader.ReadUInt32(); + this.Unknown_BCh = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.KeyframeProp3 = reader.ReadBlock(); + this.KeyframeProp4 = reader.ReadBlock(); + this.KeyframePropsPointer = reader.ReadUInt64(); + this.KeyframePropsCount1 = reader.ReadUInt16(); + this.KeyframePropsCount2 = reader.ReadUInt16(); + this.Unknown_39Ch = reader.ReadUInt32(); + this.Unknown_3A0h = reader.ReadUInt32(); + this.Unknown_3A4h = reader.ReadUInt32(); + this.Unknown_3A8h = reader.ReadUInt32(); + this.Unknown_3ACh = reader.ReadUInt32(); + this.Unknown_3B0h = reader.ReadUInt32(); + this.Unknown_3B4h = reader.ReadUInt32(); + this.Unknown_3B8h = reader.ReadUInt32(); + this.Unknown_3BCh = reader.ReadUInt32(); + + // read reference data + this.Name = reader.ReadBlockAt( + this.NamePointer // offset + ); + this.EventEmitters = reader.ReadBlockAt>( + this.EventEmittersPointer, // offset + this.EventEmittersCount1 + ); + this.p4data = reader.ReadBlockAt( + this.p4 // offset + ); + this.KeyframeProps = reader.ReadBlockAt>( + this.KeyframePropsPointer, // offset + this.KeyframePropsCount2 + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + //// update structure data + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); + //this.EventEmittersPointer = (ulong)(this.EventEmitters != null ? this.EventEmitters.Position : 0); + ////this.c3b = (ushort)(this.p3data != null ? this.p3data.Count : 0); + //this.p4 = (ulong)(this.p4data != null ? this.p4data.Position : 0); + //this.KeyframePropsPointer = (ulong)(this.KeyframeProps != null ? this.KeyframeProps.Position : 0); + ////this.refcnt2 = (ushort)(this.refs != null ? this.refs.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.NamePointer); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.EventEmittersPointer); + writer.Write(this.EventEmittersCount1); + writer.Write(this.EventEmittersCount2); + writer.Write(this.Unknown_44h); + writer.Write(this.p4); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + writer.Write(this.Unknown_90h); + writer.Write(this.Unknown_94h); + writer.Write(this.Unknown_98h); + writer.Write(this.Unknown_9Ch); + writer.Write(this.Unknown_A0h); + writer.Write(this.Unknown_A4h); + writer.Write(this.Unknown_A8h); + writer.Write(this.Unknown_ACh); + writer.Write(this.Unknown_B0h); + writer.Write(this.Unknown_B4h); + writer.Write(this.Unknown_B8h); + writer.Write(this.Unknown_BCh); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.WriteBlock(this.KeyframeProp3); + writer.WriteBlock(this.KeyframeProp4); + writer.Write(this.KeyframePropsPointer); + writer.Write(this.KeyframePropsCount1); + writer.Write(this.KeyframePropsCount2); + writer.Write(this.Unknown_39Ch); + writer.Write(this.Unknown_3A0h); + writer.Write(this.Unknown_3A4h); + writer.Write(this.Unknown_3A8h); + writer.Write(this.Unknown_3ACh); + writer.Write(this.Unknown_3B0h); + writer.Write(this.Unknown_3B4h); + writer.Write(this.Unknown_3B8h); + writer.Write(this.Unknown_3BCh); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Name != null) list.Add(Name); + //if (EventEmitters != null) list.Add(EventEmitters); + //if (p4data != null) list.Add(p4data); + //if (KeyframeProps != null) list.Add(KeyframeProps); + return list.ToArray(); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(192, KeyframeProp0), + new Tuple(336, KeyframeProp1), + new Tuple(480, KeyframeProp2), + new Tuple(624, KeyframeProp3), + new Tuple(768, KeyframeProp4) + }; + } + } + + + // datBase + // ptxKeyframeProp + [TC(typeof(EXP))] public class ParticleKeyframeProp : ResourceSystemBlock + { + public override long BlockLength => 0x90; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public uint Unknown_58h { get; set; } // 0x00000000 + public uint Unknown_5Ch { get; set; } // 0x00000000 + public uint Unknown_60h { get; set; } // 0x00000000 + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } + public uint Unknown_6Ch { get; set; } + public ResourceSimpleList64 Unknown_70h { get; set; } + public uint Unknown_80h { get; set; } // 0x00000000 + public uint Unknown_84h { get; set; } // 0x00000000 + public uint Unknown_88h { get; set; } // 0x00000000 + public uint Unknown_8Ch { get; set; } // 0x00000000 + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadBlock>(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.WriteBlock(this.Unknown_70h); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0x70, Unknown_70h) + }; + } + } + + + + [TC(typeof(EXP))] public class ParticleUnknown_P_011 : ResourceSystemBlock + { + public override long BlockLength => 0x20; + + // structure data + public float Unknown_0h { get; set; } + public float Unknown_4h { get; set; } + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public float Unknown_10h { get; set; } + public float Unknown_14h { get; set; } + public float Unknown_18h { get; set; } + public float Unknown_1Ch { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadSingle(); + this.Unknown_4h = reader.ReadSingle(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadSingle(); + this.Unknown_14h = reader.ReadSingle(); + this.Unknown_18h = reader.ReadSingle(); + this.Unknown_1Ch = reader.ReadSingle(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + } + } + + + // ptxEvent + // ptxEventEmitter + [TC(typeof(EXP))] public class ParticleEventEmitter : ResourceSystemBlock + { + public override long BlockLength => 0x70; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public ulong p1 { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ulong p2 { get; set; } + public ulong p3 { get; set; } + public ulong p4 { get; set; } + public ulong p5 { get; set; } + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } + public uint Unknown_58h { get; set; } + public uint Unknown_5Ch { get; set; } + public uint Unknown_60h { get; set; } + public uint Unknown_64h { get; set; } + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + + // reference data + public ParticleUnknown_P_005 p1data { get; set; } + public string_r p2data { get; set; } + public string_r p3data { get; set; } + public ParticleEmitterRule EmitterRule { get; set; } + public ParticleRule ParticleRule { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.p1 = reader.ReadUInt64(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.p2 = reader.ReadUInt64(); + this.p3 = reader.ReadUInt64(); + this.p4 = reader.ReadUInt64(); + this.p5 = reader.ReadUInt64(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + + // read reference data + this.p1data = reader.ReadBlockAt( + this.p1 // offset + ); + this.p2data = reader.ReadBlockAt( + this.p2 // offset + ); + this.p3data = reader.ReadBlockAt( + this.p3 // offset + ); + this.EmitterRule = reader.ReadBlockAt( + this.p4 // offset + ); + this.ParticleRule = reader.ReadBlockAt( + this.p5 // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0); + //this.p2 = (ulong)(this.p2data != null ? this.p2data.Position : 0); + //this.p3 = (ulong)(this.p3data != null ? this.p3data.Position : 0); + //this.p4 = (ulong)(this.EmitterRule != null ? this.EmitterRule.Position : 0); + //this.p5 = (ulong)(this.ParticleRule != null ? this.ParticleRule.Position : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.p1); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.p2); + writer.Write(this.p3); + writer.Write(this.p4); + writer.Write(this.p5); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (p1data != null) list.Add(p1data); + //if (p2data != null) list.Add(p2data); + //if (p3data != null) list.Add(p3data); + //if (EmitterRule != null) list.Add(EmitterRule); + //if (ParticleRule != null) list.Add(ParticleRule); + return list.ToArray(); + } + } + + + [TC(typeof(EXP))] public class ParticleUnknown_P_005 : ResourceSystemBlock + { + public override long BlockLength => 0x40; + + // structure data + public ResourceSimpleList64 Unknown_0h { get; set; } + public ResourceSimpleList64 Unknown_10h { get; set; } + public uint Unknown_20h { get; set; } // 0x00000001 + public uint Unknown_24h { get; set; } // 0x00000000 + public ResourceSimpleList64 Unknown_28h { get; set; } + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadBlock>(); + this.Unknown_10h = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadBlock>(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.WriteBlock(this.Unknown_0h); + writer.WriteBlock(this.Unknown_10h); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.WriteBlock(this.Unknown_28h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0, Unknown_0h), + new Tuple(0x10, Unknown_10h), + new Tuple(0x28, Unknown_28h) + }; + } + } + + [TC(typeof(EXP))] public class ParticleUnknown_P_008 : ResourceSystemBlock + { + public override long BlockLength => 24; + + // structure data + public ulong p1 { get; set; } + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + + // reference data + public string_r p1data { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.p1 = reader.ReadUInt64(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + + // read reference data + this.p1data = reader.ReadBlockAt( + this.p1 // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0); + + // write structure data + writer.Write(this.p1); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + + [TC(typeof(EXP))] public class ParticleUnknown_P_003 : ResourceSystemBlock + { + public override long BlockLength => 24; + + // structure data + public ResourceSimpleList64 Unknown_0h { get; set; } + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadBlock>(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.WriteBlock(this.Unknown_0h); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0, Unknown_0h) + }; + } + } + + [TC(typeof(EXP))] public class ParticleUnknown_P_006 : ResourceSystemBlock + { + public override long BlockLength => 0x30; + + // structure data + public ResourceSimpleList64 Unknown_0h { get; set; } + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadBlock>(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.WriteBlock(this.Unknown_0h); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0, Unknown_0h) + }; + } + } + + [TC(typeof(EXP))] public class ParticleUnknown_P_009 : ResourceSystemBlock + { + public override long BlockLength => 0x20; + + // structure data + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + } + } + + [TC(typeof(EXP))] public class ParticleUnknown_P_010 : ResourceSystemBlock + { + public override long BlockLength => 0x10; + + // structure data + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } // 0x00000000 + public ulong Unknown_8h_Pointer { get; set; } + + // reference data + public ParticleUnknown_P_003 Unknown_8h_Data { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h_Pointer = reader.ReadUInt64(); + + // read reference data + this.Unknown_8h_Data = reader.ReadBlockAt( + this.Unknown_8h_Pointer // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.Unknown_8h_Pointer = (ulong)(this.Unknown_8h_Data != null ? this.Unknown_8h_Data.Position : 0); + + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h_Pointer); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Unknown_8h_Data != null) list.Add(Unknown_8h_Data); + return list.ToArray(); + } + } + + + + // pgBase + // pgBaseRefCounted + // ptxEmitterRule + [TC(typeof(EXP))] public class ParticleEmitterRule : ResourceSystemBlock + { + public override long BlockLength => 0x630; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x40833333 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ulong NamePointer { get; set; } + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public ulong p2 { get; set; } + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public ulong p3 { get; set; } + public uint Unknown_50h { get; set; } // 0x00000000 + public uint Unknown_54h { get; set; } // 0x00000000 + public ulong p4 { get; set; } + public uint Unknown_60h { get; set; } // 0x00000000 + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + public uint Unknown_70h { get; set; } // 0x00000000 + public uint Unknown_74h { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public ParticleKeyframeProp KeyframeProp3 { get; set; } + public ParticleKeyframeProp KeyframeProp4 { get; set; } + public ParticleKeyframeProp KeyframeProp5 { get; set; } + public ParticleKeyframeProp KeyframeProp6 { get; set; } + public ParticleKeyframeProp KeyframeProp7 { get; set; } + public ParticleKeyframeProp KeyframeProp8 { get; set; } + public ParticleKeyframeProp KeyframeProp9 { get; set; } + public ulong KeyframePropsPointer { get; set; } + public ushort KeyframePropsCount1 { get; set; } // 10 + public ushort KeyframePropsCount2 { get; set; } // 10 + public uint Unknown_624h { get; set; } // 0x00000000 + public uint Unknown_628h { get; set; } + public uint Unknown_62Ch { get; set; } // 0x00000000 + + // reference data + public string_r Name { get; set; } + public ParticleDomain p2data { get; set; } + public ParticleDomain p3data { get; set; } + public ParticleDomain p4data { get; set; } + public ResourcePointerArray64 KeyframeProps { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.p2 = reader.ReadUInt64(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.p3 = reader.ReadUInt64(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.p4 = reader.ReadUInt64(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.Unknown_70h = reader.ReadUInt32(); + this.Unknown_74h = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.KeyframeProp3 = reader.ReadBlock(); + this.KeyframeProp4 = reader.ReadBlock(); + this.KeyframeProp5 = reader.ReadBlock(); + this.KeyframeProp6 = reader.ReadBlock(); + this.KeyframeProp7 = reader.ReadBlock(); + this.KeyframeProp8 = reader.ReadBlock(); + this.KeyframeProp9 = reader.ReadBlock(); + this.KeyframePropsPointer = reader.ReadUInt64(); + this.KeyframePropsCount1 = reader.ReadUInt16(); + this.KeyframePropsCount2 = reader.ReadUInt16(); + this.Unknown_624h = reader.ReadUInt32(); + this.Unknown_628h = reader.ReadUInt32(); + this.Unknown_62Ch = reader.ReadUInt32(); + + // read reference data + this.Name = reader.ReadBlockAt( + this.NamePointer // offset + ); + this.p2data = reader.ReadBlockAt( + this.p2 // offset + ); + this.p3data = reader.ReadBlockAt( + this.p3 // offset + ); + this.p4data = reader.ReadBlockAt( + this.p4 // offset + ); + this.KeyframeProps = reader.ReadBlockAt>( + this.KeyframePropsPointer, // offset + this.KeyframePropsCount2 + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); + //this.p2 = (ulong)(this.p2data != null ? this.p2data.Position : 0); + //this.p3 = (ulong)(this.p3data != null ? this.p3data.Position : 0); + //this.p4 = (ulong)(this.p4data != null ? this.p4data.Position : 0); + //this.KeyframePropsPointer = (ulong)(this.KeyframeProps != null ? this.KeyframeProps.Position : 0); + ////this.refcnt2 = (ushort)(this.refs != null ? this.refs.Count : 0); + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.NamePointer); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.p2); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.p3); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.p4); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.Unknown_70h); + writer.Write(this.Unknown_74h); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.WriteBlock(this.KeyframeProp3); + writer.WriteBlock(this.KeyframeProp4); + writer.WriteBlock(this.KeyframeProp5); + writer.WriteBlock(this.KeyframeProp6); + writer.WriteBlock(this.KeyframeProp7); + writer.WriteBlock(this.KeyframeProp8); + writer.WriteBlock(this.KeyframeProp9); + writer.Write(this.KeyframePropsPointer); + writer.Write(this.KeyframePropsCount1); + writer.Write(this.KeyframePropsCount2); + writer.Write(this.Unknown_624h); + writer.Write(this.Unknown_628h); + writer.Write(this.Unknown_62Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Name != null) list.Add(Name); + //if (p2data != null) list.Add(p2data); + //if (p3data != null) list.Add(p3data); + //if (p4data != null) list.Add(p4data); + //if (KeyframeProps != null) list.Add(KeyframeProps); + return list.ToArray(); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(120, KeyframeProp0), + new Tuple(264, KeyframeProp1), + new Tuple(408, KeyframeProp2), + new Tuple(552, KeyframeProp3), + new Tuple(696, KeyframeProp4), + new Tuple(840, KeyframeProp5), + new Tuple(984, KeyframeProp6), + new Tuple(1128, KeyframeProp7), + new Tuple(1272, KeyframeProp8), + new Tuple(1416, KeyframeProp9), + }; + } + } + + + + // datBase + // ptxDomain + [TC(typeof(EXP))] public class ParticleDomain : ResourceSystemBlock, IResourceXXSystemBlock + { + public override long BlockLength => 0x280; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } + public byte Unknown_Ch { get; set; } + public byte Unknown_Dh { get; set; } + public ushort Unknown_Eh { get; set; } + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public ParticleKeyframeProp KeyframeProp3 { get; set; } + public uint Unknown_258h { get; set; } + public uint Unknown_25Ch { get; set; } // 0x00000000 + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_270h { get; set; } // 0x00000000 + public uint Unknown_274h { get; set; } // 0x00000000 + public uint Unknown_278h { get; set; } // 0x00000000 + public uint Unknown_27Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadByte(); + this.Unknown_Dh = reader.ReadByte(); + this.Unknown_Eh = reader.ReadUInt16(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.KeyframeProp3 = reader.ReadBlock(); + this.Unknown_258h = reader.ReadUInt32(); + this.Unknown_25Ch = reader.ReadUInt32(); + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_270h = reader.ReadUInt32(); + this.Unknown_274h = reader.ReadUInt32(); + this.Unknown_278h = reader.ReadUInt32(); + this.Unknown_27Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_Dh); + writer.Write(this.Unknown_Eh); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.WriteBlock(this.KeyframeProp3); + writer.Write(this.Unknown_258h); + writer.Write(this.Unknown_25Ch); + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_270h); + writer.Write(this.Unknown_274h); + writer.Write(this.Unknown_278h); + writer.Write(this.Unknown_27Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(24, KeyframeProp0), + new Tuple(168, KeyframeProp1), + new Tuple(312, KeyframeProp2), + new Tuple(456, KeyframeProp3), + new Tuple(0x260, KeyframeProps) + }; + } + + public IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters) + { + reader.Position += 12; + byte type = reader.ReadByte(); + reader.Position -= 13; + + switch (type) + { + case 0: return new ParticleDomainBox(); + case 1: return new ParticleDomainSphere(); + case 2: return new ParticleDomainCylinder(); + case 3: return new ParticleDomainAttractor(); + default: return null;// throw new Exception("Unknown domain type"); + } + } + + } + + // ptxDomainBox + [TC(typeof(EXP))] public class ParticleDomainBox : ParticleDomain + { } + + // ptxDomainSphere + [TC(typeof(EXP))] public class ParticleDomainSphere : ParticleDomain + { } + + // ptxDomainCylinder + [TC(typeof(EXP))] public class ParticleDomainCylinder : ParticleDomain + { } + + // ptxDomainAttractor + [TC(typeof(EXP))] public class ParticleDomainAttractor : ParticleDomain + { } + + + + + + + [TC(typeof(EXP))] public class ParticleUnknown_P_004 : ResourceSystemBlock + { + public override long BlockLength => 0x40; + + // structure data + public ResourceSimpleList64 Unknown_0h { get; set; } + public ResourceSimpleList64 Unknown_10h { get; set; } + public uint Unknown_20h { get; set; } // 0x00000001 + public uint Unknown_24h { get; set; } // 0x00000000 + public ResourceSimpleList64 Unknown_28h { get; set; } + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadBlock>(); + this.Unknown_10h = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadBlock>(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.WriteBlock(this.Unknown_0h); + writer.WriteBlock(this.Unknown_10h); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.WriteBlock(this.Unknown_28h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0, Unknown_0h), + new Tuple(0x10, Unknown_10h), + new Tuple(0x28, Unknown_28h) + }; + } + } + + [TC(typeof(EXP))] public class ParticleUnknown_P_002 : ResourceSystemBlock + { + public override long BlockLength => 24; + + // structure data + public ulong p1 { get; set; } + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + + // reference data + public string_r p1data { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.p1 = reader.ReadUInt64(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + + // read reference data + this.p1data = reader.ReadBlockAt( + this.p1 // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + ////this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0); + + // write structure data + writer.Write(this.p1); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + + [TC(typeof(EXP))] public class ParticleUnknown_P_007 : ResourceSystemBlock + { + public override long BlockLength => 0x10; + + // structure data + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } // 0x00000000 + public ulong p1 { get; set; } + + // reference data + public ParticleUnknown_P_003 p1data { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.p1 = reader.ReadUInt64(); + + // read reference data + this.p1data = reader.ReadBlockAt( + this.p1 // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + ////this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0); + + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.p1); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (p1data != null) list.Add(p1data); + return list.ToArray(); + } + } + + + + + + + + + + + public enum ParticleBehaviourType : uint + { + Age = 0xF5B33BAA, + Acceleration = 0xD63D9F1B, + Velocity = 0x6C0719BC, + Rotation = 0x1EE64552, + Size = 0x38B60240, + Dampening = 0x052B1293, + MatrixWeight = 0x64E5D702, + Collision = 0x928A1C45, + AnimateTexture = 0xECA84C1E, + Colour = 0x164AEA72, + Sprite = 0x68FA73F5, + Wind = 0x38B63978, + Light = 0x0544C710, + Model = 0x6232E25A, + Decal = 0x8F3B6036, + ZCull = 0xA35C721F, + Noise = 0xB77FED19, + Attractor = 0x25AC9437, + Trail = 0xC57377F8, + FogVolume = 0xA05DA63E, + River = 0xD4594BEF, + DecalPool = 0xA2D6DC3F, + Liquid = 0xDF229542 + } + + // ptxBehaviour + [TC(typeof(EXP))] public class ParticleBehaviour : ResourceSystemBlock, IResourceXXSystemBlock + { + public override long BlockLength => 0x10; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Type { get; set; } + public uint Unknown_Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Type = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Type); + writer.Write(this.Unknown_Ch); + } + + public IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters) + { + + reader.Position += 8; + ParticleBehaviourType type = (ParticleBehaviourType)reader.ReadUInt32(); + reader.Position -= 12; + + switch (type) + { + case ParticleBehaviourType.Age: return new ParticleBehaviourAge(); + case ParticleBehaviourType.Acceleration: return new ParticleBehaviourAcceleration(); + case ParticleBehaviourType.Velocity: return new ParticleBehaviourVelocity(); + case ParticleBehaviourType.Rotation: return new ParticleBehaviourRotation(); + case ParticleBehaviourType.Size: return new ParticleBehaviourSize(); + case ParticleBehaviourType.Dampening: return new ParticleBehaviourDampening(); + case ParticleBehaviourType.MatrixWeight: return new ParticleBehaviourMatrixWeight(); + case ParticleBehaviourType.Collision: return new ParticleBehaviourCollision(); + case ParticleBehaviourType.AnimateTexture: return new ParticleBehaviourAnimateTexture(); + case ParticleBehaviourType.Colour: return new ParticleBehaviourColour(); + case ParticleBehaviourType.Sprite: return new ParticleBehaviourSprite(); + case ParticleBehaviourType.Wind: return new ParticleBehaviourWind(); + case ParticleBehaviourType.Light: return new ParticleBehaviourLight(); + case ParticleBehaviourType.Model: return new ParticleBehaviourModel(); + case ParticleBehaviourType.Decal: return new ParticleBehaviourDecal(); + case ParticleBehaviourType.ZCull: return new ParticleBehaviourZCull(); + case ParticleBehaviourType.Noise: return new ParticleBehaviourNoise(); + case ParticleBehaviourType.Attractor: return new ParticleBehaviourAttractor(); + case ParticleBehaviourType.Trail: return new ParticleBehaviourTrail(); + case ParticleBehaviourType.FogVolume: return new ParticleBehaviourFogVolume(); + case ParticleBehaviourType.River: return new ParticleBehaviourRiver(); + case ParticleBehaviourType.DecalPool: return new ParticleBehaviourDecalPool(); + case ParticleBehaviourType.Liquid: return new ParticleBehaviourLiquid(); + default: return null;// throw new Exception("Unknown behaviour type"); + } + } + } + + // ptxu_Age + [TC(typeof(EXP))] public class ParticleBehaviourAge : ParticleBehaviour + { + public override long BlockLength => 0x30; + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + + // ptxu_Acceleration + [TC(typeof(EXP))] public class ParticleBehaviourAcceleration : ParticleBehaviour + { + public override long BlockLength => 0x170; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public uint Unknown_150h { get; set; } // 0x00000000 + public uint Unknown_154h { get; set; } // 0x00000000 + public uint Unknown_158h { get; set; } + public uint Unknown_15Ch { get; set; } + public uint Unknown_160h { get; set; } // 0x00000000 + public uint Unknown_164h { get; set; } // 0x00000000 + public uint Unknown_168h { get; set; } // 0x00000000 + public uint Unknown_16Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.Unknown_150h = reader.ReadUInt32(); + this.Unknown_154h = reader.ReadUInt32(); + this.Unknown_158h = reader.ReadUInt32(); + this.Unknown_15Ch = reader.ReadUInt32(); + this.Unknown_160h = reader.ReadUInt32(); + this.Unknown_164h = reader.ReadUInt32(); + this.Unknown_168h = reader.ReadUInt32(); + this.Unknown_16Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.Write(this.Unknown_150h); + writer.Write(this.Unknown_154h); + writer.Write(this.Unknown_158h); + writer.Write(this.Unknown_15Ch); + writer.Write(this.Unknown_160h); + writer.Write(this.Unknown_164h); + writer.Write(this.Unknown_168h); + writer.Write(this.Unknown_16Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0x10, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1) + }; + } + } + + // ptxu_Velocity + [TC(typeof(EXP))] public class ParticleBehaviourVelocity : ParticleBehaviour + { + public override long BlockLength => 0x30; + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + } + + // ptxu_Rotation + [TC(typeof(EXP))] public class ParticleBehaviourRotation : ParticleBehaviour + { + public override long BlockLength => 0x280; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public ParticleKeyframeProp KeyframeProp3 { get; set; } + public uint Unknown_270h { get; set; } + public uint Unknown_274h { get; set; } + public uint Unknown_278h { get; set; } + public uint Unknown_27Ch { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.KeyframeProp3 = reader.ReadBlock(); + this.Unknown_270h = reader.ReadUInt32(); + this.Unknown_274h = reader.ReadUInt32(); + this.Unknown_278h = reader.ReadUInt32(); + this.Unknown_27Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.WriteBlock(this.KeyframeProp3); + writer.Write(this.Unknown_270h); + writer.Write(this.Unknown_274h); + writer.Write(this.Unknown_278h); + writer.Write(this.Unknown_27Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1), + new Tuple(336, KeyframeProp2), + new Tuple(480, KeyframeProp3) + }; + } + } + + // ptxu_Size + [TC(typeof(EXP))] public class ParticleBehaviourSize : ParticleBehaviour + { + public override long BlockLength => 0x280; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public ParticleKeyframeProp KeyframeProp3 { get; set; } + public uint Unknown_270h { get; set; } + public uint Unknown_274h { get; set; } + public uint Unknown_278h { get; set; } // 0x00000000 + public uint Unknown_27Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.KeyframeProp3 = reader.ReadBlock(); + this.Unknown_270h = reader.ReadUInt32(); + this.Unknown_274h = reader.ReadUInt32(); + this.Unknown_278h = reader.ReadUInt32(); + this.Unknown_27Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.WriteBlock(this.KeyframeProp3); + writer.Write(this.Unknown_270h); + writer.Write(this.Unknown_274h); + writer.Write(this.Unknown_278h); + writer.Write(this.Unknown_27Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1), + new Tuple(336, KeyframeProp2), + new Tuple(480, KeyframeProp3) + }; + } + } + + // ptxu_Dampening + [TC(typeof(EXP))] public class ParticleBehaviourDampening : ParticleBehaviour + { + public override long BlockLength => 0x170; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public uint Unknown_150h { get; set; } // 0x00000000 + public uint Unknown_154h { get; set; } // 0x00000000 + public uint Unknown_158h { get; set; } + public uint Unknown_15Ch { get; set; } // 0x00000000 + public uint Unknown_160h { get; set; } // 0x00000000 + public uint Unknown_164h { get; set; } // 0x00000000 + public uint Unknown_168h { get; set; } // 0x00000000 + public uint Unknown_16Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.Unknown_150h = reader.ReadUInt32(); + this.Unknown_154h = reader.ReadUInt32(); + this.Unknown_158h = reader.ReadUInt32(); + this.Unknown_15Ch = reader.ReadUInt32(); + this.Unknown_160h = reader.ReadUInt32(); + this.Unknown_164h = reader.ReadUInt32(); + this.Unknown_168h = reader.ReadUInt32(); + this.Unknown_16Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.Write(this.Unknown_150h); + writer.Write(this.Unknown_154h); + writer.Write(this.Unknown_158h); + writer.Write(this.Unknown_15Ch); + writer.Write(this.Unknown_160h); + writer.Write(this.Unknown_164h); + writer.Write(this.Unknown_168h); + writer.Write(this.Unknown_16Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1) + }; + } + } + + // ptxu_MatrixWeight + [TC(typeof(EXP))] public class ParticleBehaviourMatrixWeight : ParticleBehaviour + { + public override long BlockLength => 0xD0; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public uint Unknown_C0h { get; set; } + public uint Unknown_C4h { get; set; } // 0x00000000 + public uint Unknown_C8h { get; set; } // 0x00000000 + public uint Unknown_CCh { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.Unknown_C8h = reader.ReadUInt32(); + this.Unknown_CCh = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.Unknown_C8h); + writer.Write(this.Unknown_CCh); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0) + }; + } + } + + // ptxu_Collision + [TC(typeof(EXP))] public class ParticleBehaviourCollision : ParticleBehaviour + { + public override long BlockLength => 0x170; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public uint Unknown_150h { get; set; } + public uint Unknown_154h { get; set; } + public uint Unknown_158h { get; set; } + public uint Unknown_15Ch { get; set; } + public uint Unknown_160h { get; set; } // 0x00000000 + public uint Unknown_164h { get; set; } // 0x00000000 + public uint Unknown_168h { get; set; } // 0x00000000 + public uint Unknown_16Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.Unknown_150h = reader.ReadUInt32(); + this.Unknown_154h = reader.ReadUInt32(); + this.Unknown_158h = reader.ReadUInt32(); + this.Unknown_15Ch = reader.ReadUInt32(); + this.Unknown_160h = reader.ReadUInt32(); + this.Unknown_164h = reader.ReadUInt32(); + this.Unknown_168h = reader.ReadUInt32(); + this.Unknown_16Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.Write(this.Unknown_150h); + writer.Write(this.Unknown_154h); + writer.Write(this.Unknown_158h); + writer.Write(this.Unknown_15Ch); + writer.Write(this.Unknown_160h); + writer.Write(this.Unknown_164h); + writer.Write(this.Unknown_168h); + writer.Write(this.Unknown_16Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1) + }; + } + } + + // ptxu_AnimateTexture + [TC(typeof(EXP))] public class ParticleBehaviourAnimateTexture : ParticleBehaviour + { + public override long BlockLength => 0xD0; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public uint Unknown_C0h { get; set; } + public uint Unknown_C4h { get; set; } + public uint Unknown_C8h { get; set; } + public uint Unknown_CCh { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.Unknown_C8h = reader.ReadUInt32(); + this.Unknown_CCh = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.Unknown_C8h); + writer.Write(this.Unknown_CCh); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0) + }; + } + } + + // ptxu_Colour + [TC(typeof(EXP))] public class ParticleBehaviourColour : ParticleBehaviour + { + public override long BlockLength => 0x1F0; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public uint Unknown_1E0h { get; set; } + public uint Unknown_1E4h { get; set; } + public uint Unknown_1E8h { get; set; } // 0x00000000 + public uint Unknown_1ECh { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.Unknown_1E0h = reader.ReadUInt32(); + this.Unknown_1E4h = reader.ReadUInt32(); + this.Unknown_1E8h = reader.ReadUInt32(); + this.Unknown_1ECh = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.Write(this.Unknown_1E0h); + writer.Write(this.Unknown_1E4h); + writer.Write(this.Unknown_1E8h); + writer.Write(this.Unknown_1ECh); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1), + new Tuple(336, KeyframeProp2) + }; + } + } + + // ptxd_Sprite + [TC(typeof(EXP))] public class ParticleBehaviourSprite : ParticleBehaviour + { + public override long BlockLength => 0x70; + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public uint Unknown_48h { get; set; } + public uint Unknown_4Ch { get; set; } + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } + public uint Unknown_58h { get; set; } + public uint Unknown_5Ch { get; set; } + public uint Unknown_60h { get; set; } + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + this.Unknown_58h = reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadUInt32(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + writer.Write(this.Unknown_58h); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + } + } + + // ptxu_Wind + [TC(typeof(EXP))] public class ParticleBehaviourWind : ParticleBehaviour + { + public override long BlockLength => 0xF0; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public uint Unknown_C0h { get; set; } // 0x00000000 + public uint Unknown_C4h { get; set; } // 0x00000000 + public uint Unknown_C8h { get; set; } // 0x00000000 + public uint Unknown_CCh { get; set; } // 0x00000000 + public uint Unknown_D0h { get; set; } + public uint Unknown_D4h { get; set; } + public uint Unknown_D8h { get; set; } + public uint Unknown_DCh { get; set; } + public uint Unknown_E0h { get; set; } + public uint Unknown_E4h { get; set; } // 0x00000000 + public uint Unknown_E8h { get; set; } // 0x00000000 + public uint Unknown_ECh { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.Unknown_C8h = reader.ReadUInt32(); + this.Unknown_CCh = reader.ReadUInt32(); + this.Unknown_D0h = reader.ReadUInt32(); + this.Unknown_D4h = reader.ReadUInt32(); + this.Unknown_D8h = reader.ReadUInt32(); + this.Unknown_DCh = reader.ReadUInt32(); + this.Unknown_E0h = reader.ReadUInt32(); + this.Unknown_E4h = reader.ReadUInt32(); + this.Unknown_E8h = reader.ReadUInt32(); + this.Unknown_ECh = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.Unknown_C8h); + writer.Write(this.Unknown_CCh); + writer.Write(this.Unknown_D0h); + writer.Write(this.Unknown_D4h); + writer.Write(this.Unknown_D8h); + writer.Write(this.Unknown_DCh); + writer.Write(this.Unknown_E0h); + writer.Write(this.Unknown_E4h); + writer.Write(this.Unknown_E8h); + writer.Write(this.Unknown_ECh); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0) + }; + } + } + + // ptxu_Light + [TC(typeof(EXP))] public class ParticleBehaviourLight : ParticleBehaviour + { + public override long BlockLength => 0x550; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public ParticleKeyframeProp KeyframeProp3 { get; set; } + public ParticleKeyframeProp KeyframeProp4 { get; set; } + public ParticleKeyframeProp KeyframeProp5 { get; set; } + public ParticleKeyframeProp KeyframeProp6 { get; set; } + public ParticleKeyframeProp KeyframeProp7 { get; set; } + public ParticleKeyframeProp KeyframeProp8 { get; set; } + public uint Unknown_540h { get; set; } + public uint Unknown_544h { get; set; } + public uint Unknown_548h { get; set; } + public uint Unknown_54Ch { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.KeyframeProp3 = reader.ReadBlock(); + this.KeyframeProp4 = reader.ReadBlock(); + this.KeyframeProp5 = reader.ReadBlock(); + this.KeyframeProp6 = reader.ReadBlock(); + this.KeyframeProp7 = reader.ReadBlock(); + this.KeyframeProp8 = reader.ReadBlock(); + this.Unknown_540h = reader.ReadUInt32(); + this.Unknown_544h = reader.ReadUInt32(); + this.Unknown_548h = reader.ReadUInt32(); + this.Unknown_54Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.WriteBlock(this.KeyframeProp3); + writer.WriteBlock(this.KeyframeProp4); + writer.WriteBlock(this.KeyframeProp5); + writer.WriteBlock(this.KeyframeProp6); + writer.WriteBlock(this.KeyframeProp7); + writer.WriteBlock(this.KeyframeProp8); + writer.Write(this.Unknown_540h); + writer.Write(this.Unknown_544h); + writer.Write(this.Unknown_548h); + writer.Write(this.Unknown_54Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1), + new Tuple(336, KeyframeProp2), + new Tuple(480, KeyframeProp3), + new Tuple(624, KeyframeProp4), + new Tuple(768, KeyframeProp5), + new Tuple(912, KeyframeProp6), + new Tuple(1056, KeyframeProp7), + new Tuple(1200, KeyframeProp8) + }; + } + } + + // ptxd_Model + [TC(typeof(EXP))] public class ParticleBehaviourModel : ParticleBehaviour + { + public override long BlockLength => 0x40; + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + } + + // ptxu_Decal + [TC(typeof(EXP))] public class ParticleBehaviourDecal : ParticleBehaviour + { + public override long BlockLength => 0x180; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public uint Unknown_150h { get; set; } + public uint Unknown_154h { get; set; } + public uint Unknown_158h { get; set; } + public uint Unknown_15Ch { get; set; } + public uint Unknown_160h { get; set; } + public uint Unknown_164h { get; set; } + public uint Unknown_168h { get; set; } + public uint Unknown_16Ch { get; set; } + public uint Unknown_170h { get; set; } + public uint Unknown_174h { get; set; } // 0x3E99999A + public uint Unknown_178h { get; set; } // 0x3F800000 + public uint Unknown_17Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.Unknown_150h = reader.ReadUInt32(); + this.Unknown_154h = reader.ReadUInt32(); + this.Unknown_158h = reader.ReadUInt32(); + this.Unknown_15Ch = reader.ReadUInt32(); + this.Unknown_160h = reader.ReadUInt32(); + this.Unknown_164h = reader.ReadUInt32(); + this.Unknown_168h = reader.ReadUInt32(); + this.Unknown_16Ch = reader.ReadUInt32(); + this.Unknown_170h = reader.ReadUInt32(); + this.Unknown_174h = reader.ReadUInt32(); + this.Unknown_178h = reader.ReadUInt32(); + this.Unknown_17Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.Write(this.Unknown_150h); + writer.Write(this.Unknown_154h); + writer.Write(this.Unknown_158h); + writer.Write(this.Unknown_15Ch); + writer.Write(this.Unknown_160h); + writer.Write(this.Unknown_164h); + writer.Write(this.Unknown_168h); + writer.Write(this.Unknown_16Ch); + writer.Write(this.Unknown_170h); + writer.Write(this.Unknown_174h); + writer.Write(this.Unknown_178h); + writer.Write(this.Unknown_17Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1) + }; + } + } + + // ptxu_ZCull + [TC(typeof(EXP))] public class ParticleBehaviourZCull : ParticleBehaviour + { + public override long BlockLength => 0x170; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public uint Unknown_150h { get; set; } // 0x00000000 + public uint Unknown_154h { get; set; } // 0x00000000 + public uint Unknown_158h { get; set; } + public uint Unknown_15Ch { get; set; } + public uint Unknown_160h { get; set; } // 0x00000000 + public uint Unknown_164h { get; set; } // 0x00000000 + public uint Unknown_168h { get; set; } // 0x00000000 + public uint Unknown_16Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.Unknown_150h = reader.ReadUInt32(); + this.Unknown_154h = reader.ReadUInt32(); + this.Unknown_158h = reader.ReadUInt32(); + this.Unknown_15Ch = reader.ReadUInt32(); + this.Unknown_160h = reader.ReadUInt32(); + this.Unknown_164h = reader.ReadUInt32(); + this.Unknown_168h = reader.ReadUInt32(); + this.Unknown_16Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.Write(this.Unknown_150h); + writer.Write(this.Unknown_154h); + writer.Write(this.Unknown_158h); + writer.Write(this.Unknown_15Ch); + writer.Write(this.Unknown_160h); + writer.Write(this.Unknown_164h); + writer.Write(this.Unknown_168h); + writer.Write(this.Unknown_16Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1) + }; + } + } + + // ptxu_Noise + [TC(typeof(EXP))] public class ParticleBehaviourNoise : ParticleBehaviour + { + public override long BlockLength => 0x280; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public ParticleKeyframeProp KeyframeProp3 { get; set; } + public uint Unknown_270h { get; set; } // 0x00000000 + public uint Unknown_274h { get; set; } + public uint Unknown_278h { get; set; } // 0x00000000 + public uint Unknown_27Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.KeyframeProp3 = reader.ReadBlock(); + this.Unknown_270h = reader.ReadUInt32(); + this.Unknown_274h = reader.ReadUInt32(); + this.Unknown_278h = reader.ReadUInt32(); + this.Unknown_27Ch = reader.ReadUInt32(); + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.WriteBlock(this.KeyframeProp3); + writer.Write(this.Unknown_270h); + writer.Write(this.Unknown_274h); + writer.Write(this.Unknown_278h); + writer.Write(this.Unknown_27Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1), + new Tuple(336, KeyframeProp2), + new Tuple(480, KeyframeProp3) + }; + } + } + + // ptxu_Attractor + [TC(typeof(EXP))] public class ParticleBehaviourAttractor : ParticleBehaviour + { + public override long BlockLength => 0xC0; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0) + }; + } + } + + // ptxd_Trail + [TC(typeof(EXP))] public class ParticleBehaviourTrail : ParticleBehaviour + { + public override long BlockLength => 0xF0; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public uint Unknown_C0h { get; set; } // 0x00000000 + public uint Unknown_C4h { get; set; } + public uint Unknown_C8h { get; set; } + public uint Unknown_CCh { get; set; } + public uint Unknown_D0h { get; set; } // 0x00000000 + public uint Unknown_D4h { get; set; } + public uint Unknown_D8h { get; set; } + public uint Unknown_DCh { get; set; } + public uint Unknown_E0h { get; set; } + public uint Unknown_E4h { get; set; } + public uint Unknown_E8h { get; set; } // 0x00000000 + public uint Unknown_ECh { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.Unknown_C0h = reader.ReadUInt32(); + this.Unknown_C4h = reader.ReadUInt32(); + this.Unknown_C8h = reader.ReadUInt32(); + this.Unknown_CCh = reader.ReadUInt32(); + this.Unknown_D0h = reader.ReadUInt32(); + this.Unknown_D4h = reader.ReadUInt32(); + this.Unknown_D8h = reader.ReadUInt32(); + this.Unknown_DCh = reader.ReadUInt32(); + this.Unknown_E0h = reader.ReadUInt32(); + this.Unknown_E4h = reader.ReadUInt32(); + this.Unknown_E8h = reader.ReadUInt32(); + this.Unknown_ECh = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.Write(this.Unknown_C0h); + writer.Write(this.Unknown_C4h); + writer.Write(this.Unknown_C8h); + writer.Write(this.Unknown_CCh); + writer.Write(this.Unknown_D0h); + writer.Write(this.Unknown_D4h); + writer.Write(this.Unknown_D8h); + writer.Write(this.Unknown_DCh); + writer.Write(this.Unknown_E0h); + writer.Write(this.Unknown_E4h); + writer.Write(this.Unknown_E8h); + writer.Write(this.Unknown_ECh); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0) + }; + } + } + + // ptxu_FogVolume + [TC(typeof(EXP))] public class ParticleBehaviourFogVolume : ParticleBehaviour + { + public override long BlockLength => 0x430; + + // structure data + public ResourcePointerList64 KeyframeProps { get; set; } + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public ParticleKeyframeProp KeyframeProp0 { get; set; } + public ParticleKeyframeProp KeyframeProp1 { get; set; } + public ParticleKeyframeProp KeyframeProp2 { get; set; } + public ParticleKeyframeProp KeyframeProp3 { get; set; } + public ParticleKeyframeProp KeyframeProp4 { get; set; } + public ParticleKeyframeProp KeyframeProp5 { get; set; } + public ParticleKeyframeProp KeyframeProp6 { get; set; } + public uint Unknown_420h { get; set; } + public uint Unknown_424h { get; set; } + public uint Unknown_428h { get; set; } + public uint Unknown_42Ch { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.KeyframeProps = reader.ReadBlock>(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.KeyframeProp0 = reader.ReadBlock(); + this.KeyframeProp1 = reader.ReadBlock(); + this.KeyframeProp2 = reader.ReadBlock(); + this.KeyframeProp3 = reader.ReadBlock(); + this.KeyframeProp4 = reader.ReadBlock(); + this.KeyframeProp5 = reader.ReadBlock(); + this.KeyframeProp6 = reader.ReadBlock(); + this.Unknown_420h = reader.ReadUInt32(); + this.Unknown_424h = reader.ReadUInt32(); + this.Unknown_428h = reader.ReadUInt32(); + this.Unknown_42Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.WriteBlock(this.KeyframeProps); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.WriteBlock(this.KeyframeProp0); + writer.WriteBlock(this.KeyframeProp1); + writer.WriteBlock(this.KeyframeProp2); + writer.WriteBlock(this.KeyframeProp3); + writer.WriteBlock(this.KeyframeProp4); + writer.WriteBlock(this.KeyframeProp5); + writer.WriteBlock(this.KeyframeProp6); + writer.Write(this.Unknown_420h); + writer.Write(this.Unknown_424h); + writer.Write(this.Unknown_428h); + writer.Write(this.Unknown_42Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, KeyframeProps), + new Tuple(48, KeyframeProp0), + new Tuple(192, KeyframeProp1), + new Tuple(336, KeyframeProp2), + new Tuple(480, KeyframeProp3), + new Tuple(624, KeyframeProp4), + new Tuple(768, KeyframeProp5), + new Tuple(912, KeyframeProp6) + }; + } + } + + // ptxu_River + [TC(typeof(EXP))] public class ParticleBehaviourRiver : ParticleBehaviour + { + public override long BlockLength => 0x40; + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x42C80000 + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + } + + // ptxu_DecalPool + [TC(typeof(EXP))] public class ParticleBehaviourDecalPool : ParticleBehaviour + { + public override long BlockLength => 0x50; + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + } + } + + // ptxu_Liquid + [TC(typeof(EXP))] public class ParticleBehaviourLiquid : ParticleBehaviour + { + public override long BlockLength => 0x50; + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } + public uint Unknown_48h { get; set; } + public uint Unknown_4Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + } + } + + + + + + + + + [TC(typeof(EXP))] public class ParticleUnknown_P_013 : ResourceSystemBlock + { + public override long BlockLength => 0x58; + + // structure data + public uint Unknown_0h { get; set; } // 0x73616942 + public uint Unknown_4h { get; set; } // 0x6E694C20 + public uint Unknown_8h { get; set; } // 0x6553206B + public uint Unknown_Ch { get; set; } // 0x30305F74 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + public uint Unknown_30h { get; set; } // 0x00000000 + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public ResourceSimpleList64 Unknown_40h { get; set; } + public uint Unknown_50h { get; set; } + public uint Unknown_54h { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadBlock>(); + this.Unknown_50h = reader.ReadUInt32(); + this.Unknown_54h = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.WriteBlock(this.Unknown_40h); + writer.Write(this.Unknown_50h); + writer.Write(this.Unknown_54h); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0x40, Unknown_40h) + }; + } + } + + + + + + + + // datBase + // ptxShaderVar + [TC(typeof(EXP))] public class ParticleShaderVar : ResourceSystemBlock, IResourceXXSystemBlock + { + public override long BlockLength => 24; + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public byte Type { get; set; } + public byte Unknown_15h { get; set; } + public ushort Unknown_16h { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Type = reader.ReadByte(); + this.Unknown_15h = reader.ReadByte(); + this.Unknown_16h = reader.ReadUInt16(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Type); + writer.Write(this.Unknown_15h); + writer.Write(this.Unknown_16h); + } + + public IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters) + { + reader.Position += 20; + var type = reader.ReadByte(); + reader.Position -= 21; + + switch (type) + { + case 2: + case 4: return new ParticleShaderVarVector(); + case 6: return new ParticleShaderVarTexture(); + case 7: return new ParticleShaderVarKeyframe(); + default: return null;// throw new Exception("Unknown shader var type"); + } + } + } + + // ptxShaderVarVector + [TC(typeof(EXP))] public class ParticleShaderVarVector : ParticleShaderVar + { + public override long BlockLength => 0x40; + + // structure data + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public uint Unknown_28h { get; set; } + public uint Unknown_2Ch { get; set; } + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } + public uint Unknown_38h { get; set; } + public uint Unknown_3Ch { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + } + + // ptxShaderVarTexture + [TC(typeof(EXP))] public class ParticleShaderVarTexture : ParticleShaderVar + { + public override long BlockLength => 0x40; + + // structure data + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } + public ulong TexturePointer { get; set; } + public ulong NamePointer { get; set; } + public uint NameHash { get; set; } + public uint Unknown_3Ch { get; set; } + + // reference data + public Texture Texture { get; set; } + public string_r Name { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.TexturePointer = reader.ReadUInt64(); + this.NamePointer = reader.ReadUInt64(); + this.NameHash = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + this.Texture = reader.ReadBlockAt( + this.TexturePointer // offset + ); + this.Name = reader.ReadBlockAt( + this.NamePointer // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // update structure data + //this.TexturePointer = (ulong)(this.Texture != null ? this.Texture.Position : 0); + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); + + // write structure data + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.TexturePointer); + writer.Write(this.NamePointer); + writer.Write(this.NameHash); + writer.Write(this.Unknown_3Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + //if (Texture != null) list.Add(Texture); + //if (Name != null) list.Add(Name); + return list.ToArray(); + } + } + + // ptxShaderVarKeyframe + [TC(typeof(EXP))] public class ParticleShaderVarKeyframe : ParticleShaderVar + { + public override long BlockLength => 0x50; + + // structure data + public uint Unknown_18h { get; set; } + public uint Unknown_1Ch { get; set; } // 0x00000001 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public ResourceSimpleList64 Unknown_28h { get; set; } + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + public uint Unknown_40h { get; set; } // 0x00000000 + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } // 0x00000000 + public uint Unknown_4Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadBlock>(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.WriteBlock(this.Unknown_28h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(0x28, Unknown_28h) + }; + } + } + + + [TC(typeof(EXP))] public class ParticleUnknown_P_001 : ResourceSystemBlock + { + public override long BlockLength => 0x20; + + // structure data + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + } + } + + + + [TC(typeof(EXP))] public class ParticleUnknown_P_012 : ResourceSystemBlock + { + public override long BlockLength => 0x30; + + // structure data + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } + public uint Unknown_8h { get; set; } + public uint Unknown_Ch { get; set; } + public ulong Unknown_10h_Pointer { get; set; } + public ulong DrawablePointer { get; set; } + public uint Unknown_20h { get; set; } + public uint Unknown_24h { get; set; } // 0x00000000 + public uint Unknown_28h { get; set; } // 0x00000000 + public uint Unknown_2Ch { get; set; } // 0x00000000 + + // reference data + public string_r Unknown_10h_Data { get; set; } + public Drawable Drawable { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h_Pointer = reader.ReadUInt64(); + this.DrawablePointer = reader.ReadUInt64(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + + // read reference data + this.Unknown_10h_Data = reader.ReadBlockAt( + this.Unknown_10h_Pointer // offset + ); + this.Drawable = reader.ReadBlockAt( + this.DrawablePointer // offset + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + //// update structure data + //this.Unknown_10h_Pointer = (ulong)(this.Unknown_10h_Data != null ? this.Unknown_10h_Data.Position : 0); + //this.DrawablePointer = (ulong)(this.Drawable != null ? this.Drawable.Position : 0); + + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h_Pointer); + writer.Write(this.DrawablePointer); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (Unknown_10h_Data != null) list.Add(Unknown_10h_Data); + if (Drawable != null) list.Add(Drawable); + return list.ToArray(); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + +} diff --git a/GameFiles/Resources/ResourceBaseTypes.cs b/GameFiles/Resources/ResourceBaseTypes.cs new file mode 100644 index 0000000..735ea87 --- /dev/null +++ b/GameFiles/Resources/ResourceBaseTypes.cs @@ -0,0 +1,1414 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen and mangled + + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class uint_r : ResourceSystemBlock + { + // Represents a uint that can be referenced in a resource structure. + + /// + /// Gets the length of the uint. + /// + public override long BlockLength + { + get { return 4; } + } + + /// + /// Gets or sets the uint value. + /// + public uint Value { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + Value = reader.ReadUInt32(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + writer.Write(Value); + } + + public static explicit operator uint(uint_r value) + { + return value.Value; + } + + public static explicit operator uint_r(uint value) + { + var x = new uint_r(); + x.Value = value; + return x; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class string_r : ResourceSystemBlock + { + // Represents a string that can be referenced in a resource structure. + + /// + /// Gets the length of the string. + /// + public override long BlockLength + { + get { return Value.Length + 1; } + } + + /// + /// Gets or sets the string value. + /// + public string Value { get; set; } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + Value = reader.ReadString(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + writer.Write(Value); + } + + public static explicit operator string(string_r value) + { + return value.Value; + } + + public static explicit operator string_r(string value) + { + var x = new string_r(); + x.Value = value; + return x; + } + public override string ToString() + { + return Value; + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct Matrix3_s + { + public SharpDX.Vector4 Row1 { get; set; } + public SharpDX.Vector4 Row2 { get; set; } + public SharpDX.Vector4 Row3 { get; set; } + + // structure data + //public float Unknown_01 { get; set; } + //public float Unknown_02 { get; set; } + //public float Unknown_03 { get; set; } + //public float Unknown_04 { get; set; } + //public float Unknown_11 { get; set; } + //public float Unknown_12 { get; set; } + //public float Unknown_13 { get; set; } + //public float Unknown_14 { get; set; } + //public float Unknown_21 { get; set; } + //public float Unknown_22 { get; set; } + //public float Unknown_23 { get; set; } + //public float Unknown_24 { get; set; } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct AABB_s + { + public SharpDX.Vector4 Min { get; set; } + public SharpDX.Vector4 Max { get; set; } + } + + + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct FlagsByte + { + public byte Value { get; set; } + + public string Hex + { + get + { + return Convert.ToString(Value, 16).ToUpper().PadLeft(2, '0'); + } + } + + public string Bin + { + get + { + return Convert.ToString(Value, 2).PadLeft(8, '0'); + } + } + + + public FlagsByte(byte v) + { + Value = v; + } + + public override string ToString() + { + return Bin + " | 0x" + Hex + " | " + Value.ToString(); + } + public string ToShortString() + { + return Bin + " | 0x" + Hex; + } + public string ToHexString() + { + return "0x" + Hex; + } + + public static implicit operator FlagsByte(byte v) + { + return new FlagsByte(v); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public struct FlagsUint + { + public uint Value { get; set; } + + public string Hex + { + get + { + return Convert.ToString(Value, 16).ToUpper().PadLeft(8, '0'); + } + } + + public string Bin + { + get + { + return Convert.ToString(Value, 2).PadLeft(32, '0'); + } + } + + public FlagsUint(uint v) + { + Value = v; + } + + public override string ToString() + { + return Bin + " | 0x" + Hex + " | " + Value.ToString(); + } + public string ToShortString() + { + return Bin + " | 0x" + Hex; + } + + public static implicit operator FlagsUint(uint v) + { + return new FlagsUint(v); + } + } + + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public abstract class ListBase : ResourceSystemBlock, ICustomTypeDescriptor, IList where T : IResourceSystemBlock, new() + { + + // this is the data... + public List Data { get; set; } + + + + + + public T this[int index] + { + get + { + return Data[index]; + } + set + { + Data[index] = value; + } + } + + public int Count + { + get + { + return Data?.Count ?? 0; + } + } + + public bool IsReadOnly + { + get + { + return false; + } + } + + + + + + + public ListBase() + { + //Data = new List(); + } + + + + + + public void Add(T item) + { + if (Data == null) + { + Data = new List(); + } + Data.Add(item); + } + + public void Clear() + { + Data.Clear(); + } + + public bool Contains(T item) + { + return Data.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + Data.CopyTo(array, arrayIndex); + } + + public IEnumerator GetEnumerator() + { + return Data.GetEnumerator(); + } + + public int IndexOf(T item) + { + return Data.IndexOf(item); + } + + public void Insert(int index, T item) + { + Data.Insert(index, item); + } + + public bool Remove(T item) + { + return Data.Remove(item); + } + + public void RemoveAt(int index) + { + Data.RemoveAt(index); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return Data.GetEnumerator(); + } + + + + + public String GetClassName() + { + return TypeDescriptor.GetClassName(this, true); + } + + public AttributeCollection GetAttributes() + { + return TypeDescriptor.GetAttributes(this, true); + } + + public String GetComponentName() + { + return TypeDescriptor.GetComponentName(this, true); + } + + public TypeConverter GetConverter() + { + return TypeDescriptor.GetConverter(this, true); + } + + public EventDescriptor GetDefaultEvent() + { + return TypeDescriptor.GetDefaultEvent(this, true); + } + + public PropertyDescriptor GetDefaultProperty() + { + return TypeDescriptor.GetDefaultProperty(this, true); + } + + public object GetEditor(Type editorBaseType) + { + return TypeDescriptor.GetEditor(this, editorBaseType, true); + } + + public EventDescriptorCollection GetEvents(Attribute[] attributes) + { + return TypeDescriptor.GetEvents(this, attributes, true); + } + + public EventDescriptorCollection GetEvents() + { + return TypeDescriptor.GetEvents(this, true); + } + + public object GetPropertyOwner(PropertyDescriptor pd) + { + return this; + } + + + public PropertyDescriptorCollection GetProperties() + { + var pds = new PropertyDescriptorCollection(null); + for (int i = 0; i < Data.Count; i++) + { + var pd = new ListBasePropertyDescriptor(this, i); + pds.Add(pd); + } + return pds; + } + + public PropertyDescriptorCollection GetProperties(Attribute[] attributes) + { + return GetProperties(); + } + + + public class ListBasePropertyDescriptor : PropertyDescriptor + { + private ListBase collection = null; + private int index = -1; + + public ListBasePropertyDescriptor(ListBase coll, int i) : base("#" + i.ToString(), null) + { + collection = coll; + index = i; + } + + public override AttributeCollection Attributes + { + get + { + return new AttributeCollection(null); + } + } + + public override bool CanResetValue(object component) + { + return true; + } + + public override Type ComponentType + { + get + { + return this.collection.GetType(); + } + } + + public override string DisplayName + { + get + { + return "[" + index.ToString() + "]"; + } + } + + public override string Description + { + get + { + return collection[index].ToString(); + } + } + + public override object GetValue(object component) + { + return this.collection[index]; + } + + public override bool IsReadOnly + { + get { return true; } + } + + public override string Name + { + get { return "#" + index.ToString(); } + } + + public override Type PropertyType + { + get { return this.collection[index].GetType(); } + } + + public override void ResetValue(object component) { } + + public override bool ShouldSerializeValue(object component) + { + return true; + } + + public override void SetValue(object component, object value) + { + // this.collection[index] = value; + } + } + + } + + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleArray : ListBase where T : IResourceSystemBlock, new() + { + /// + /// Gets the length of the data block. + /// + public override long BlockLength + { + get + { + long length = 0; + if (Data != null) + { + foreach (var x in Data) + length += x.BlockLength; + } + return length; + } + } + + + public ResourceSimpleArray() + { + //Data = new List(); + } + + + + + + + + /// + /// Reads the data block. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + int numElements = Convert.ToInt32(parameters[0]); + + Data = new List(numElements); + for (int i = 0; i < numElements; i++) + { + T item = reader.ReadBlock(); + Data.Add(item); + } + } + + /// + /// Writes the data block. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + foreach (var f in Data) + f.Write(writer); + } + + + + + public override Tuple[] GetParts() + { + var list = new List>(); + + long length = 0; + + if (Data != null) + { + foreach (var x in Data) + { + list.Add(new Tuple(length, x)); + length += x.BlockLength; + } + } + + + return list.ToArray(); + } + + + + + public override string ToString() + { + return "(Count: " + Count.ToString() + ")"; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleList64 : ResourceSystemBlock where T : IResourceSystemBlock, new() + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public ulong EntriesPointer { get; private set; } + public ushort EntriesCount { get; private set; } + public ushort EntriesCapacity { get; private set; } + + // reference data + //public ResourceSimpleArray Entries; + public T[] data_items { get; private set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.EntriesPointer = reader.ReadUInt64(); + this.EntriesCount = reader.ReadUInt16(); + this.EntriesCapacity = reader.ReadUInt16(); + reader.Position += 4; + + // read reference data + //this.Entries = reader.ReadBlockAt>( + // this.EntriesPointer, // offset + // this.EntriesCount + //); + + //TODO: NEEDS TO BE TESTED!!! + data_items = new T[EntriesCount]; + var posbckp = reader.Position; + reader.Position = (long)EntriesPointer; + for (int i = 0; i < EntriesCount; i++) + { + data_items[i] = reader.ReadBlock(); + } + reader.Position = posbckp; + + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data //TODO: fix + //this.EntriesPointer = (ulong)(this.Entries != null ? this.Entries.Position : 0); + //this.EntriesCount = (ushort)(this.Entries != null ? this.Entries.Count : 0); + //this.EntriesCapacity = (ushort)(this.Entries != null ? this.Entries.Count : 0); + + // write structure data + writer.Write(this.EntriesPointer); + writer.Write(this.EntriesCount); + writer.Write(this.EntriesCapacity); + writer.Write((uint)0x00000000); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Entries != null) list.Add(Entries); + return list.ToArray(); + } + + public override string ToString() + { + return "(Count: " + EntriesCount.ToString() + ")"; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public struct ResourceSimpleList64Ptr + { + // structure data + public ulong EntriesPointer { get; private set; } + public ushort EntriesCount { get; private set; } + public ushort EntriesCapacity { get; private set; } + public uint Unused1 { get; private set; } + + public override string ToString() + { + return "(Count: " + EntriesCount.ToString() + ")"; + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourcePointerArray64 : ResourceSystemBlock, IList where T : IResourceSystemBlock, new() + { + + public int GetNonEmptyNumber() + { + int i = 0; + foreach (var q in data_items) + if (q != null) + i++; + return i; + } + + public override long BlockLength + { + get { return (data_items!=null)?8 * data_items.Length:0; } + } + + + //// structure data + //public List data_pointers; + + //// reference data + //public List data_items; + + public ulong[] data_pointers { get; private set; } + public T[] data_items { get; private set; } + + + + public ResourcePointerArray64() + { + //data_items = new List(); + } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + int numElements = Convert.ToInt32(parameters[0]); + + // read structure data + //data_pointers = new List(); + //for (int i = 0; i < numElements; i++) + //{ + // data_pointers.Add(reader.ReadUInt64()); + //} + + data_pointers = reader.ReadUlongsAt((ulong)reader.Position, (uint)numElements); + + + //foreach (var dp in data_pointers) + //{ + // if (dp == 0) + // { + + // } + //} + + // read reference data + //data_items = new List(); + //for (int i = 0; i < numElements; i++) + //{ + // data_items.Add( + // reader.ReadBlockAt(data_pointers[i]) + // ); + //} + + data_items = new T[numElements]; + for (int i = 0; i < numElements; i++) + { + data_items[i] = reader.ReadBlockAt(data_pointers[i]); + } + + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update... + //data_pointers = new List(); + //foreach (var x in data_items) + // if (x != null) + // data_pointers.Add((uint)x.Position); + // else + // data_pointers.Add((uint)0); + //TODO: fix! + + // write... + foreach (var x in data_pointers) + writer.Write(x); + } + + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + + foreach (var x in data_items) + list.Add(x); + + return list.ToArray(); + } + + + + + + public int IndexOf(T item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, T item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + //data_items.RemoveAt(index); + throw new NotImplementedException(); + } + + public T this[int index] + { + get + { + return data_items[index]; + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(T item) + { + //data_items.Add(item); + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(T item) + { + throw new NotImplementedException(); + } + + public void CopyTo(T[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + //get { return data_items.Count; } + get { return (data_items != null) ? data_items.Length : 0; } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(T item) + { + //return data_items.Remove(item); + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + //return data_items.GetEnumerator(); + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + + + + public override string ToString() + { + return "(Count: " + ((data_items != null) ? data_items.Length : 0).ToString() + ")"; + } + + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourcePointerArray64_s : ResourceSystemBlock, IList where T : struct + { + + //public int GetNonEmptyNumber() + //{ + // int i = 0; + // foreach (var q in data_items) + // if (q != null) + // i++; + // return i; + //} + + public override long BlockLength + { + get { return (data_items != null) ? 8 * data_items.Length : 0; } + } + + + //// structure data + //public List data_pointers; + + //// reference data + //public List data_items; + + public ulong[] data_pointers { get; private set; } + public T[] data_items { get; private set; } + + + + public ResourcePointerArray64_s() + { + //data_items = new List(); + } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + int numElements = Convert.ToInt32(parameters[0]); + + // read structure data + //data_pointers = new List(); + //for (int i = 0; i < numElements; i++) + //{ + // data_pointers.Add(reader.ReadUInt64()); + //} + + data_pointers = reader.ReadUlongsAt((ulong)reader.Position, (uint)numElements); + + + //foreach (var dp in data_pointers) + //{ + // if (dp == 0) + // { + + // } + //} + + // read reference data + //data_items = new List(); + //for (int i = 0; i < numElements; i++) + //{ + // data_items.Add( + // reader.ReadBlockAt(data_pointers[i]) + // ); + //} + + data_items = new T[numElements]; + for (int i = 0; i < numElements; i++) + { + data_items[i] = reader.ReadStructAt((long)data_pointers[i]); + } + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update... + //data_pointers = new List(); + //foreach (var x in data_items) + // if (x != null) + // data_pointers.Add((uint)x.Position); + // else + // data_pointers.Add((uint)0); + //TODO: fix! + + // write... + foreach (var x in data_pointers) + writer.Write(x); + } + + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + + //foreach (var x in data_items) //TODO: fix + // list.Add(x); + + return list.ToArray(); + } + + + + + + public int IndexOf(T item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, T item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + //data_items.RemoveAt(index); + throw new NotImplementedException(); + } + + public T this[int index] + { + get + { + return data_items[index]; + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(T item) + { + //data_items.Add(item); + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(T item) + { + throw new NotImplementedException(); + } + + public void CopyTo(T[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + //get { return data_items.Count; } + get { return (data_items != null) ? data_items.Length : 0; } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(T item) + { + //return data_items.Remove(item); + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + //return data_items.GetEnumerator(); + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + + + public override string ToString() + { + return "(Count: " + ((data_items != null) ? data_items.Length : 0).ToString() + ")"; + } + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourcePointerList64 : ResourceSystemBlock, IList where T : IResourceSystemBlock, new() + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public ulong EntriesPointer { get; private set; } + public ushort EntriesCount { get; private set; } + public ushort EntriesCapacity { get; private set; } + + // reference data + //public ResourcePointerArray64 Entries; + + public ulong[] data_pointers { get; private set; } + public T[] data_items { get; private set; } + + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + this.EntriesPointer = reader.ReadUInt64(); + this.EntriesCount = reader.ReadUInt16(); + this.EntriesCapacity = reader.ReadUInt16(); + reader.Position += 4; + + //this.Entries = reader.ReadBlockAt>( + // this.EntriesPointer, // offset + // this.EntriesCount + //); + + data_pointers = reader.ReadUlongsAt(EntriesPointer, EntriesCount); + data_items = new T[EntriesCount]; + for (int i = 0; i < EntriesCount; i++) + { + data_items[i] = reader.ReadBlockAt(data_pointers[i]); + } + + + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update... //TODO: fix... + //this.EntriesPointer = (ulong)(this.Entries != null ? this.Entries.Position : 0); + //this.EntriesCount = (ushort)(this.Entries != null ? this.Entries.Count : 0); + //this.EntriesCapacity = (ushort)(this.Entries != null ? this.Entries.Count : 0); + + // write... + writer.Write(EntriesPointer); + writer.Write(EntriesCount); + writer.Write(EntriesCapacity); + writer.Write((uint)0x0000000); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Entries != null) list.Add(Entries); //TODO: fix.. + return list.ToArray(); + } + + + + + public int IndexOf(T item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, T item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public T this[int index] + { + get + { + return data_items[index]; + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(T item) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(T item) + { + throw new NotImplementedException(); + } + + public void CopyTo(T[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + get { return EntriesCount; } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(T item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + + public IResourceBlock CheckForCast(ResourceDataReader reader, params object[] parameters) + { + throw new NotImplementedException(); + } + + + public override string ToString() + { + return "(Count: " + EntriesCount.ToString() + ")"; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleArrayArray64 : ListBase> where T : IResourceSystemBlock, new() + { + /// + /// Gets the length of the data block. + /// + public override long BlockLength + { + get + { + long len = 8 * Data.Count; + foreach (var f in Data) + len += f.BlockLength; + return len; + } + } + + + public ResourceSimpleArrayArray64() + { + Data = new List>(); + } + + + + + public List ptr_list { get; private set; } + + + + /// + /// Reads the data block. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + if (parameters[1] is uint[]) + { + //version for raw arrays from dexy + + var numEl2 = (uint[])parameters[1]; + + ptr_list = new List(); + for (int i = 0; i < numEl2.Length; i++) + ptr_list.Add(reader.ReadUInt64()); + + for (int i = 0; i < numEl2.Length; i++) + { + var xarr = reader.ReadBlockAt>(ptr_list[i], numEl2[i]); + Data.Add(xarr); + } + + return; + } + + + + var numEl = (ResourceSimpleArray)parameters[1]; + + ptr_list = new List(); + for (int i = 0; i < numEl.Count; i++) + ptr_list.Add(reader.ReadUInt64()); + + for (int i = 0; i < numEl.Count; i++) + { + var xarr = reader.ReadBlockAt>(ptr_list[i], (uint)numEl[i]); + Data.Add(xarr); + } + + //int numElements = Convert.ToInt32(parameters[0]); + + //Data = new List(); + //for (int i = 0; i < numElements; i++) + //{ + // T item = reader.ReadBlock(); + // Data.Add(item); + //} + } + + /// + /// Writes the data block. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + //foreach (var f in Data) + // f.Write(writer); + + + ptr_list = new List(); + foreach (var x in Data) + ptr_list.Add((ulong)x.FilePosition); + + foreach (var x in ptr_list) + writer.Write(x); + foreach (var x in Data) + x.Write(writer); + + } + + + + public override IResourceBlock[] GetReferences() + { + var children = new List(); + + //if (Data != null) children.AddRange(Data); + + return children.ToArray(); + } + + public override Tuple[] GetParts() + { + var children = new List>(); + + if (Data != null) + { + long len = 8 * Data.Count; + foreach (var f in Data) + { + children.Add(new Tuple(len, f)); + len += f.BlockLength; + } + } + + return children.ToArray(); + } + + public override string ToString() + { + return "(Count: " + ((ptr_list != null) ? ptr_list.Count : 0).ToString() + ")"; + } + + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleArray2 : ResourceSystemBlock where T : IResourceSystemBlock, new() where U : IResourceSystemBlock, new() + { + public ResourceSimpleArray Array1 { get; private set; } + public ResourceSimpleArray Array2 { get; private set; } + + /// + /// Gets the length of the data block. + /// + public override long BlockLength + { + get + { + return Array1.BlockLength + Array2.BlockLength; + } + } + + /// + /// Reads the data block. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + int numElements1 = Convert.ToInt32(parameters[0]); + int numElements2 = Convert.ToInt32(parameters[1]); + Array1 = reader.ReadBlock>(numElements1); + Array2 = reader.ReadBlock>(numElements2); + } + + /// + /// Writes the data block. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + writer.WriteBlock(Array1); + writer.WriteBlock(Array2); + } + + + + + public override Tuple[] GetParts() + { + var list = new List>(); + list.Add(new Tuple(0, Array1)); + list.Add(new Tuple(Array1.BlockLength, Array2)); + return list.ToArray(); + } + + + + + public override string ToString() + { + return "(Count1: " + ((Array1 != null) ? Array1.Count : 0).ToString() + ", Count2: " + ((Array2 != null) ? Array2.Count : 0).ToString() + ")"; + } + + } + + + + + + + + + + + +} diff --git a/GameFiles/Resources/ResourceBuilder.cs b/GameFiles/Resources/ResourceBuilder.cs new file mode 100644 index 0000000..60fca47 --- /dev/null +++ b/GameFiles/Resources/ResourceBuilder.cs @@ -0,0 +1,340 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class ResourceBuilder + { + protected const int RESOURCE_IDENT = 0x37435352; + protected const int BASE_SIZE = 0x2000; + private const int SKIP_SIZE = 512;//256;//64; + private const int ALIGN_SIZE = 512;//64; + + + public static void GetBlocks(IResourceBlock rootBlock, out IList sys, out IList gfx) + { + var systemBlocks = new HashSet(); + var graphicBlocks = new HashSet(); + var protectedBlocks = new List(); + + var stack = new Stack(); + stack.Push(rootBlock); + + var processed = new HashSet(); + processed.Add(rootBlock); + + while (stack.Count > 0) + { + var block = stack.Pop(); + if (block == null) + continue; + + if (block is IResourceSystemBlock) + { + if (!systemBlocks.Contains(block)) + systemBlocks.Add(block); + + // for system blocks, also process references... + + var references = ((IResourceSystemBlock)block).GetReferences(); + //Array.Reverse(references); + foreach (var reference in references) + if (!processed.Contains(reference)) + { + stack.Push(reference); + processed.Add(reference); + } + var subs = new Stack(); + foreach (var part in ((IResourceSystemBlock)block).GetParts()) + subs.Push((IResourceSystemBlock)part.Item2); + while (subs.Count > 0) + { + var sub = subs.Pop(); + + foreach (var x in sub.GetReferences()) + if (!processed.Contains(x)) + { + stack.Push(x); + processed.Add(x); + } + foreach (var x in sub.GetParts()) + subs.Push((IResourceSystemBlock)x.Item2); + + protectedBlocks.Add(sub); + } + + } + else + { + if (!graphicBlocks.Contains(block)) + graphicBlocks.Add(block); + } + } + + //var result = new List(); + //result.AddRange(systemBlocks); + //result.AddRange(graphicBlocks); + //return result; + + // there are now sys-blocks in the list that actually + // only substructures and therefore must not get + // a new position! + // -> remove them from the list + foreach (var q in protectedBlocks) + if (systemBlocks.Contains(q)) + systemBlocks.Remove(q); + + + sys = new List(); + foreach (var s in systemBlocks) + sys.Add(s); + gfx = new List(); + foreach (var s in graphicBlocks) + gfx.Add(s); + } + + public static void AssignPositions(IList blocks, uint basePosition, ref int pageSize, out int pageCount) + { + // find largest structure + long largestBlockSize = 0; + foreach (var block in blocks) + { + if (largestBlockSize < block.BlockLength) + largestBlockSize = block.BlockLength; + } + + // find minimum page size + long currentPageSize = pageSize;// 0x2000; + while (currentPageSize < largestBlockSize) + currentPageSize *= 2; + + long currentPageCount; + long currentPosition; + while (true) + { + currentPageCount = 0; + currentPosition = 0; + + // reset all positions + foreach (var block in blocks) + block.FilePosition = -1; + + foreach (var block in blocks) + { + if (block.FilePosition != -1) + throw new Exception("A position of -1 is not possible!"); + //if (block.Length == 0) + // throw new Exception("A length of 0 is not allowed!"); + + // check if new page is necessary... + // if yes, add a new page and align to it + long maxSpace = currentPageCount * currentPageSize - currentPosition; + if (maxSpace < (block.BlockLength + SKIP_SIZE)) + { + currentPageCount++; + currentPosition = currentPageSize * (currentPageCount - 1); + } + + // set position + block.FilePosition = basePosition + currentPosition; + currentPosition += block.BlockLength + SKIP_SIZE; + + // align... + if ((currentPosition % ALIGN_SIZE) != 0) + currentPosition += (ALIGN_SIZE - (currentPosition % ALIGN_SIZE)); + } + + // break if everything fits... + if (currentPageCount < 128) + break; + + currentPageSize *= 2; + } + + pageSize = (int)currentPageSize; + pageCount = (int)currentPageCount; + } + + + + public static byte[] Build(ResourceFileBase fileBase, int version) + { + + fileBase.FilePagesInfo = new ResourcePagesInfo(); + + IList systemBlocks; + IList graphicBlocks; + GetBlocks(fileBase, out systemBlocks, out graphicBlocks); + + int systemPageSize = BASE_SIZE;// *4; + int systemPageCount; + AssignPositions(systemBlocks, 0x50000000, ref systemPageSize, out systemPageCount); + + int graphicsPageSize = BASE_SIZE; + int graphicsPageCount; + AssignPositions(graphicBlocks, 0x60000000, ref graphicsPageSize, out graphicsPageCount); + + + + + fileBase.FilePagesInfo.SystemPagesCount = 0; + if (systemPageCount > 0) + fileBase.FilePagesInfo.SystemPagesCount = 1; // (byte)systemPageCount; //1 + fileBase.FilePagesInfo.GraphicsPagesCount = (byte)graphicsPageCount; + + + + var systemStream = new MemoryStream(); + var graphicsStream = new MemoryStream(); + var resourceWriter = new ResourceDataWriter(systemStream, graphicsStream); + + resourceWriter.Position = 0x50000000; + foreach (var block in systemBlocks) + { + resourceWriter.Position = block.FilePosition; + + var pos_before = resourceWriter.Position; + block.Write(resourceWriter); + var pos_after = resourceWriter.Position; + + if ((pos_after - pos_before) != block.BlockLength) + { + throw new Exception("error in system length"); + } + } + + resourceWriter.Position = 0x60000000; + foreach (var block in graphicBlocks) + { + resourceWriter.Position = block.FilePosition; + + var pos_before = resourceWriter.Position; + block.Write(resourceWriter); + var pos_after = resourceWriter.Position; + + if ((pos_after - pos_before) != block.BlockLength) + { + throw new Exception("error in graphics length"); + } + } + + + + + var sysDataSize = 0x2000; + while (sysDataSize < systemStream.Length) + { + sysDataSize *= 2; + } + var sysData = new byte[sysDataSize]; + systemStream.Flush(); + systemStream.Position = 0; + systemStream.Read(sysData, 0, (int)systemStream.Length); + + + var gfxPageSize = 0x2000; + while (gfxPageSize != graphicsPageSize) + { + gfxPageSize *= 2; + } + var gfxDataSize = graphicsPageCount * gfxPageSize; + var gfxData = new byte[gfxDataSize]; + graphicsStream.Flush(); + graphicsStream.Position = 0; + graphicsStream.Read(gfxData, 0, (int)graphicsStream.Length); + + + + uint uv = (uint)version; + uint sv = (uv >> 4) & 0xF; + uint gv = (uv >> 0) & 0xF; + + //uint sf = RpfResourceFileEntry.GetFlagsFromSize(sysDataSize, sv); + //uint gf = RpfResourceFileEntry.GetFlagsFromSize(gfxDataSize, gv); //TODO: might be broken... + + uint sf = RpfResourceFileEntry.GetFlagsFromBlocks((uint)systemPageCount, (uint)systemPageSize, sv); + uint gf = RpfResourceFileEntry.GetFlagsFromBlocks((uint)graphicsPageCount, (uint)graphicsPageSize, gv); + + var tdatasize = sysDataSize + gfxDataSize; + var tdata = new byte[tdatasize]; + Buffer.BlockCopy(sysData, 0, tdata, 0, sysDataSize); + Buffer.BlockCopy(gfxData, 0, tdata, sysDataSize, gfxDataSize); + + + var cdata = Compress(tdata); + + + var dataSize = 16 + cdata.Length;// sysDataSize + gfxDataSize; + var data = new byte[dataSize]; + + byte[] h1 = BitConverter.GetBytes((uint)0x37435352); + byte[] h2 = BitConverter.GetBytes((int)version); + byte[] h3 = BitConverter.GetBytes(sf); + byte[] h4 = BitConverter.GetBytes(gf); + Buffer.BlockCopy(h1, 0, data, 0, 4); + Buffer.BlockCopy(h2, 0, data, 4, 4); + Buffer.BlockCopy(h3, 0, data, 8, 4); + Buffer.BlockCopy(h4, 0, data, 12, 4); + Buffer.BlockCopy(cdata, 0, data, 16, cdata.Length); + //Buffer.BlockCopy(sysData, 0, data, 16, sysDataSize); + //Buffer.BlockCopy(gfxData, 0, data, 16 + sysDataSize, gfxDataSize); + + return data; + } + + + + + + + public static byte[] AddResourceHeader(RpfResourceFileEntry entry, byte[] data) + { + if (data == null) return null; + byte[] newdata = new byte[data.Length + 16]; + byte[] h1 = BitConverter.GetBytes((uint)0x37435352); + byte[] h2 = BitConverter.GetBytes(entry.Version); + byte[] h3 = BitConverter.GetBytes(entry.SystemFlags); + byte[] h4 = BitConverter.GetBytes(entry.GraphicsFlags); + Buffer.BlockCopy(h1, 0, newdata, 0, 4); + Buffer.BlockCopy(h2, 0, newdata, 4, 4); + Buffer.BlockCopy(h3, 0, newdata, 8, 4); + Buffer.BlockCopy(h4, 0, newdata, 12, 4); + Buffer.BlockCopy(data, 0, newdata, 16, data.Length); + return newdata; + } + + + public static byte[] Compress(byte[] data) + { + using (MemoryStream ms = new MemoryStream()) + { + DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress, true); + ds.Write(data, 0, data.Length); + ds.Close(); + byte[] deflated = ms.GetBuffer(); + byte[] outbuf = new byte[ms.Length]; //need to copy to the right size buffer... + Array.Copy(deflated, outbuf, outbuf.Length); + return outbuf; + } + } + public static byte[] Decompress(byte[] data) + { + using (MemoryStream ms = new MemoryStream(data)) + { + DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress); + MemoryStream outstr = new MemoryStream(); + ds.CopyTo(outstr); + byte[] deflated = outstr.GetBuffer(); + byte[] outbuf = new byte[outstr.Length]; //need to copy to the right size buffer... + Array.Copy(deflated, outbuf, outbuf.Length); + return outbuf; + } + } + + } +} diff --git a/GameFiles/Resources/ResourceData.cs b/GameFiles/Resources/ResourceData.cs new file mode 100644 index 0000000..f9ee6ae --- /dev/null +++ b/GameFiles/Resources/ResourceData.cs @@ -0,0 +1,750 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen and mangled + + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + /// + /// Represents a resource data reader. + /// + public class ResourceDataReader : DataReader + { + private const long SYSTEM_BASE = 0x50000000; + private const long GRAPHICS_BASE = 0x60000000; + + private Stream systemStream; + private Stream graphicsStream; + + // this is a dictionary that contains all the resource blocks + // which were read from this resource reader + private Dictionary> blockPool; + + /// + /// Gets the length of the underlying stream. + /// + public override long Length + { + get + { + return -1; + } + } + + /// + /// Gets or sets the position within the underlying stream. + /// + public override long Position + { + get; + set; + } + + /// + /// Initializes a new resource data reader for the specified system- and graphics-stream. + /// + public ResourceDataReader(Stream systemStream, Stream graphicsStream, Endianess endianess = Endianess.LittleEndian) + : base((Stream)null, endianess) + { + this.systemStream = systemStream; + this.graphicsStream = graphicsStream; + this.blockPool = new Dictionary>(); + } + + public ResourceDataReader(RpfResourceFileEntry resentry, byte[] data, Endianess endianess = Endianess.LittleEndian) + : base((Stream)null, endianess) + { + var systemSize = resentry.SystemSize; + var graphicsSize = resentry.GraphicsSize; + + this.systemStream = new MemoryStream(data, 0, systemSize); + this.graphicsStream = new MemoryStream(data, systemSize, graphicsSize); + this.blockPool = new Dictionary>(); + Position = 0x50000000; + } + + public ResourceDataReader(int systemSize, int graphicsSize, byte[] data, Endianess endianess = Endianess.LittleEndian) + : base((Stream)null, endianess) + { + this.systemStream = new MemoryStream(data, 0, systemSize); + this.graphicsStream = new MemoryStream(data, systemSize, graphicsSize); + this.blockPool = new Dictionary>(); + Position = 0x50000000; + } + + + + /// + /// Reads data from the underlying stream. This is the only method that directly accesses + /// the data in the underlying stream. + /// + protected override byte[] ReadFromStream(int count, bool ignoreEndianess = false) + { + if ((Position & SYSTEM_BASE) == SYSTEM_BASE) + { + // read from system stream... + + systemStream.Position = Position & ~0x50000000; + + var buffer = new byte[count]; + systemStream.Read(buffer, 0, count); + + // handle endianess + if (!ignoreEndianess && (Endianess == Endianess.BigEndian)) + { + Array.Reverse(buffer); + } + + Position = systemStream.Position | 0x50000000; + return buffer; + + } + if ((Position & GRAPHICS_BASE) == GRAPHICS_BASE) + { + // read from graphic stream... + + graphicsStream.Position = Position & ~0x60000000; + + var buffer = new byte[count]; + graphicsStream.Read(buffer, 0, count); + + // handle endianess + if (!ignoreEndianess && (Endianess == Endianess.BigEndian)) + { + Array.Reverse(buffer); + } + + Position = graphicsStream.Position | 0x60000000; + return buffer; + } + throw new Exception("illegal position!"); + } + + /// + /// Reads a block. + /// + public T ReadBlock(params object[] parameters) where T : IResourceBlock, new() + { + // make sure to return the same object if the same + // block is read again... + if (blockPool.ContainsKey(Position)) + { + var blocks = blockPool[Position]; + foreach (var block in blocks) + if (block is T) + { + Position += block.BlockLength; + + // since a resource block of the same type + // has been found at the same address, return it + return (T)block; + } + } + + var result = new T(); + + + // replace with correct type... + if (result is IResourceXXSystemBlock) + result = (T)((IResourceXXSystemBlock)result).GetType(this, parameters); + + if (result == null) + { + return default(T); + } + + + // add block to the block pool... + if (blockPool.ContainsKey(Position)) + { + blockPool[Position].Add(result); + } + else + { + var blocks = new List(); + blocks.Add(result); + blockPool.Add(Position, blocks); + } + + var classPosition = Position; + result.Read(this, parameters); + //result.Position = classPosition; //TODO: need this if writing stuff! + return (T)result; + } + + /// + /// Reads a block at a specified position. + /// + public T ReadBlockAt(ulong position, params object[] parameters) where T : IResourceBlock, new() + { + if (position != 0) + { + var positionBackup = Position; + + Position = (long)position; + var result = ReadBlock(parameters); + Position = positionBackup; + + return result; + } + else + { + return default(T); + } + } + + + public byte[] ReadBytesAt(ulong position, uint count) + { + long pos = (long)position; + if ((pos <= 0) || (count == 0)) return null; + var posbackup = Position; + Position = pos; + var result = ReadBytes((int)count); + Position = posbackup; + return result; + } + public ushort[] ReadUshortsAt(ulong position, uint count) + { + if ((position <= 0) || (count == 0)) return null; + + var result = new ushort[count]; + var length = count * 2; + byte[] data = ReadBytesAt(position, length); + Buffer.BlockCopy(data, 0, result, 0, (int)length); + + //var posbackup = Position; + //Position = position; + //var result2 = new ushort[count]; + //for (uint i = 0; i < count; i++) + //{ + // result2[i] = ReadUInt16(); + //} + //Position = posbackup; + return result; + } + public uint[] ReadUintsAt(ulong position, uint count) + { + if ((position <= 0) || (count == 0)) return null; + + var result = new uint[count]; + var length = count * 4; + byte[] data = ReadBytesAt(position, length); + Buffer.BlockCopy(data, 0, result, 0, (int)length); + + //var posbackup = Position; + //Position = position; + //var result = new uint[count]; + //for (uint i = 0; i < count; i++) + //{ + // result[i] = ReadUInt32(); + //} + //Position = posbackup; + return result; + } + public ulong[] ReadUlongsAt(ulong position, uint count) + { + if ((position <= 0) || (count == 0)) return null; + + var result = new ulong[count]; + var length = count * 8; + byte[] data = ReadBytesAt(position, length); + Buffer.BlockCopy(data, 0, result, 0, (int)length); + + //var posbackup = Position; + //Position = position; + //var result = new ulong[count]; + //for (uint i = 0; i < count; i++) + //{ + // result[i] = ReadUInt64(); + //} + //Position = posbackup; + return result; + } + public float[] ReadFloatsAt(ulong position, uint count) + { + if ((position <= 0) || (count == 0)) return null; + + var result = new float[count]; + var length = count * 4; + byte[] data = ReadBytesAt(position, length); + Buffer.BlockCopy(data, 0, result, 0, (int)length); + + //var posbackup = Position; + //Position = position; + //var result = new float[count]; + //for (uint i = 0; i < count; i++) + //{ + // result[i] = ReadSingle(); + //} + //Position = posbackup; + return result; + } + public T[] ReadStructsAt(ulong position, uint count)//, uint structsize) + { + if ((position <= 0) || (count == 0)) return null; + + uint structsize = (uint)Marshal.SizeOf(typeof(T)); + var length = count * structsize; + byte[] data = ReadBytesAt(position, length); + + //var result2 = new T[count]; + //Buffer.BlockCopy(data, 0, result2, 0, (int)length); //error: "object must be an array of primitives" :( + + var result = new T[count]; + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var h = handle.AddrOfPinnedObject(); + for (uint i = 0; i < count; i++) + { + result[i] = Marshal.PtrToStructure(h + (int)(i * structsize)); + } + handle.Free(); + + return result; + } + public T[] ReadStructs(uint count) + { + uint structsize = (uint)Marshal.SizeOf(typeof(T)); + var result = new T[count]; + var length = count * structsize; + byte[] data = ReadBytes((int)length); + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var h = handle.AddrOfPinnedObject(); + for (uint i = 0; i < count; i++) + { + result[i] = Marshal.PtrToStructure(h + (int)(i * structsize)); + } + handle.Free(); + return result; + } + + public T ReadStruct() where T : struct + { + uint structsize = (uint)Marshal.SizeOf(typeof(T)); + var length = structsize; + byte[] data = ReadBytes((int)length); + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var h = handle.AddrOfPinnedObject(); + var result = Marshal.PtrToStructure(h); + handle.Free(); + return result; + } + + public T ReadStructAt(long position) where T : struct + { + if ((position <= 0)) return default(T); + var posbackup = Position; + Position = (long)position; + var result = ReadStruct(); + Position = posbackup; + return result; + } + + public string ReadStringAt(ulong position) + { + long newpos = (long)position; + if ((newpos <= 0)) return null; + var lastpos = Position; + Position = newpos; + var result = ReadString(); + Position = lastpos; + return result; + } + + } + + + + /// + /// Represents a resource data writer. + /// + public class ResourceDataWriter : DataWriter + { + private const long SYSTEM_BASE = 0x50000000; + private const long GRAPHICS_BASE = 0x60000000; + + private Stream systemStream; + private Stream graphicsStream; + + /// + /// Gets the length of the underlying stream. + /// + public override long Length + { + get + { + return -1; + } + } + + /// + /// Gets or sets the position within the underlying stream. + /// + public override long Position + { + get; + set; + } + + /// + /// Initializes a new resource data reader for the specified system- and graphics-stream. + /// + public ResourceDataWriter(Stream systemStream, Stream graphicsStream, Endianess endianess = Endianess.LittleEndian) + : base((Stream)null, endianess) + { + this.systemStream = systemStream; + this.graphicsStream = graphicsStream; + } + + /// + /// Writes data to the underlying stream. This is the only method that directly accesses + /// the data in the underlying stream. + /// + protected override void WriteToStream(byte[] value, bool ignoreEndianess = true) + { + if ((Position & SYSTEM_BASE) == SYSTEM_BASE) + { + // write to system stream... + + systemStream.Position = Position & ~SYSTEM_BASE; + + // handle endianess + if (!ignoreEndianess && (Endianess == Endianess.BigEndian)) + { + var buf = (byte[])value.Clone(); + Array.Reverse(buf); + systemStream.Write(buf, 0, buf.Length); + } + else + { + systemStream.Write(value, 0, value.Length); + } + + Position = systemStream.Position | 0x50000000; + return; + + } + if ((Position & GRAPHICS_BASE) == GRAPHICS_BASE) + { + // write to graphic stream... + + graphicsStream.Position = Position & ~GRAPHICS_BASE; + + // handle endianess + if (!ignoreEndianess && (Endianess == Endianess.BigEndian)) + { + var buf = (byte[])value.Clone(); + Array.Reverse(buf); + graphicsStream.Write(buf, 0, buf.Length); + } + else + { + graphicsStream.Write(value, 0, value.Length); + } + + Position = graphicsStream.Position | 0x60000000; + return; + } + + throw new Exception("illegal position!"); + } + + /// + /// Writes a block. + /// + public void WriteBlock(IResourceBlock value) + { + value.Write(this); + } + + + + + public void WriteStruct(T val) where T : struct + { + int size = Marshal.SizeOf(typeof(T)); + byte[] arr = new byte[size]; + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(val, ptr, true); + Marshal.Copy(ptr, arr, 0, size); + Marshal.FreeHGlobal(ptr); + Write(arr); + } + + + + } + + + + + + /// + /// Represents a data block in a resource file. + /// + public interface IResourceBlock + { + /// + /// Gets or sets the position of the data block. + /// + long FilePosition { get; set; } + + /// + /// Gets the length of the data block. + /// + long BlockLength { get; } + + /// + /// Reads the data block. + /// + void Read(ResourceDataReader reader, params object[] parameters); + + /// + /// Writes the data block. + /// + void Write(ResourceDataWriter writer, params object[] parameters); + } + + /// + /// Represents a data block of the system segement in a resource file. + /// + public interface IResourceSystemBlock : IResourceBlock + { + /// + /// Returns a list of data blocks that are part of this block. + /// + Tuple[] GetParts(); + + /// + /// Returns a list of data blocks that are referenced by this block. + /// + IResourceBlock[] GetReferences(); + } + + public interface IResourceXXSystemBlock : IResourceSystemBlock + { + IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters); + } + + /// + /// Represents a data block of the graphics segmenet in a resource file. + /// + public interface IResourceGraphicsBlock : IResourceBlock + { } + + + + + + /// + /// Represents a data block of the system segement in a resource file. + /// + [TypeConverter(typeof(ExpandableObjectConverter))] public abstract class ResourceSystemBlock : IResourceSystemBlock + { + private long position; + + /// + /// Gets or sets the position of the data block. + /// + public virtual long FilePosition + { + get + { + return position; + } + set + { + position = value; + foreach (var part in GetParts()) + { + part.Item2.FilePosition = value + part.Item1; + } + } + } + + /// + /// Gets the length of the data block. + /// + public abstract long BlockLength + { + get; + } + + /// + /// Reads the data block. + /// + public abstract void Read(ResourceDataReader reader, params object[] parameters); + + /// + /// Writes the data block. + /// + public abstract void Write(ResourceDataWriter writer, params object[] parameters); + + /// + /// Returns a list of data blocks that are part of this block. + /// + public virtual Tuple[] GetParts() + { + return new Tuple[0]; + } + + /// + /// Returns a list of data blocks that are referenced by this block. + /// + public virtual IResourceBlock[] GetReferences() + { + return new IResourceBlock[0]; + } + } + + public abstract class ResourecTypedSystemBlock : ResourceSystemBlock, IResourceXXSystemBlock + { + public abstract IResourceSystemBlock GetType(ResourceDataReader reader, params object[] parameters); + } + + /// + /// Represents a data block of the graphics segmenet in a resource file. + /// + public abstract class ResourceGraphicsBlock : IResourceGraphicsBlock + { + /// + /// Gets or sets the position of the data block. + /// + public virtual long FilePosition + { + get; + set; + } + + /// + /// Gets the length of the data block. + /// + public abstract long BlockLength + { + get; + } + + /// + /// Reads the data block. + /// + public abstract void Read(ResourceDataReader reader, params object[] parameters); + + /// + /// Writes the data block. + /// + public abstract void Write(ResourceDataWriter writer, params object[] parameters); + } + + + + + + + + + + public class ResourceSystemDataBlock : ResourceSystemBlock //used for writing resources. + { + public byte[] Data { get; set; } + public int DataLength { get; set; } + + public override long BlockLength + { + get + { + return (Data != null) ? Data.Length : DataLength; + } + } + + + public ResourceSystemDataBlock(byte[] data) + { + Data = data; + DataLength = (Data != null) ? Data.Length : 0; + } + + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + Data = reader.ReadBytes(DataLength); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + writer.Write(Data); + } + } + + public class ResourceSystemStructBlock : ResourceSystemBlock where T : struct //used for writing resources. + { + public T[] Items { get; set; } + public int ItemCount { get; set; } + public int StructureSize { get; set; } + + public override long BlockLength + { + get + { + return ((Items != null) ? Items.Length : ItemCount) * StructureSize; + } + } + + public ResourceSystemStructBlock(T[] items) + { + Items = items; + ItemCount = (Items != null) ? Items.Length : 0; + StructureSize = Marshal.SizeOf(typeof(T)); + } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + int datalength = ItemCount * StructureSize; + byte[] data = reader.ReadBytes(datalength); + Items = MetaTypes.ConvertDataArray(data, 0, ItemCount); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + byte[] data = MetaTypes.ConvertArrayToBytes(Items); + writer.Write(data); + } + } + + + //public interface ResourceDataStruct + //{ + // void Read(ResourceDataReader reader); + // void Write(ResourceDataWriter writer); + //} + +} diff --git a/GameFiles/Resources/ResourceFile.cs b/GameFiles/Resources/ResourceFile.cs new file mode 100644 index 0000000..68ae8e2 --- /dev/null +++ b/GameFiles/Resources/ResourceFile.cs @@ -0,0 +1,149 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen and mangled + + +using SharpDX; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceFileBase : ResourceSystemBlock + { + public override long BlockLength + { + get { return 16; } + } + + // structure data + public uint FileVFT { get; set; } + public uint FileUnknown { get; set; } + public ulong FilePagesInfoPointer { get; set; } + + // reference data + public ResourcePagesInfo FilePagesInfo { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.FileVFT = reader.ReadUInt32(); + this.FileUnknown = reader.ReadUInt32(); + this.FilePagesInfoPointer = reader.ReadUInt64(); + + // read reference data + this.FilePagesInfo = reader.ReadBlockAt( + this.FilePagesInfoPointer // offset + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + this.FilePagesInfoPointer = (ulong)(this.FilePagesInfo != null ? this.FilePagesInfo.FilePosition : 0); + + // write structure data + writer.Write(this.FileVFT); + writer.Write(this.FileUnknown); + writer.Write(this.FilePagesInfoPointer); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + if (FilePagesInfo != null) list.Add(FilePagesInfo); + return list.ToArray(); + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ResourcePagesInfo : ResourceSystemBlock + { + public override long BlockLength + { + get { return 20; } + } + + // structure data + public uint Unknown_0h { get; set; } + public uint Unknown_4h { get; set; } + public byte SystemPagesCount { get; set; } + public byte GraphicsPagesCount { get; set; } + public ushort Unknown_Ah { get; set; } + public uint Unknown_Ch { get; set; } + public uint Unknown_10h { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Unknown_0h = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.SystemPagesCount = reader.ReadByte(); + this.GraphicsPagesCount = reader.ReadByte(); + this.Unknown_Ah = reader.ReadUInt16(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Unknown_0h); + writer.Write(this.Unknown_4h); + writer.Write(this.SystemPagesCount); + writer.Write(this.GraphicsPagesCount); + writer.Write(this.Unknown_Ah); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + } + + public override string ToString() + { + return SystemPagesCount.ToString() + ", " + GraphicsPagesCount.ToString(); + } + } + + +} diff --git a/GameFiles/Resources/RpfFile.cs b/GameFiles/Resources/RpfFile.cs new file mode 100644 index 0000000..dd77830 --- /dev/null +++ b/GameFiles/Resources/RpfFile.cs @@ -0,0 +1,1444 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + public class RpfFile + { + public string Name { get; set; } //name of this RPF file/package + public string NameLower { get; set; } + public string Path { get; set; } //path within the RPF structure + public string FilePath { get; set; } //full file path of the RPF + public long FileSize { get; set; } + public string LastError { get; set; } + public Exception LastException { get; set; } + + public RpfDirectoryEntry Root { get; set; } + + public bool IsCompressed { get; set; } + public bool IsAESEncrypted { get; set; } + public bool IsNGEncrypted { get; set; } + public long UncompressedSize { get; set; } + + public string RootFileName { get; set; } + public long RootFileSize { get; set; } + + + //offset in the current file + public long StartPos { get; set; } + + //header data + public uint Version { get; set; } + public uint EntryCount { get; set; } + public uint NamesLength { get; set; } + public RpfEncryption Encryption { get; set; } + + //object linkage + public List AllEntries { get; set; } + public List Children { get; set; } + public RpfFile Parent { get; set; } + + public BinaryReader CurrentFileReader { get; set; } //for temporary use while reading header + + + + public uint TotalFileCount { get; set; } + public uint TotalFolderCount { get; set; } + public uint TotalResourceCount { get; set; } + public uint TotalBinaryFileCount { get; set; } + public uint GrandTotalRpfCount { get; set; } + public uint GrandTotalFileCount { get; set; } + public uint GrandTotalFolderCount { get; set; } + public uint GrandTotalResourceCount { get; set; } + public uint GrandTotalBinaryFileCount { get; set; } + public long ExtractedByteCount { get; set; } + + + public RpfFile(string fpath, string relpath) + { + FileInfo fi = new FileInfo(fpath); + Name = fi.Name; + NameLower = Name.ToLower(); + Path = relpath.ToLower(); + FilePath = fpath; + FileSize = fi.Length; + IsCompressed = false; + IsAESEncrypted = false; + RootFileName = Name; + RootFileSize = FileSize; + } + public RpfFile(string name, string path, string filepath, long filesize, bool compressed, bool encrypted, string rootfn, long rootfs) + { + Name = name; + NameLower = Name.ToLower(); + Path = path.ToLower(); + FilePath = filepath; + FileSize = filesize; + IsCompressed = compressed; + IsAESEncrypted = encrypted; + RootFileName = rootfn; + RootFileSize = rootfs; + } + + + public string GetPhysicalFilePath() + { + RpfFile pfile = this; + while (pfile.Parent != null) + { + pfile = pfile.Parent; + } + return pfile.FilePath; + } + + + + + private void ReadHeader(BinaryReader br) + { + CurrentFileReader = br; + + StartPos = br.BaseStream.Position; + + Version = br.ReadUInt32(); //RPF Version - GTAV should be 0x52504637 (1380992567) + EntryCount = br.ReadUInt32(); //Number of Entries + NamesLength = br.ReadUInt32(); + Encryption = (RpfEncryption)br.ReadUInt32(); //0x04E45504F (1313165391): none; 0x0ffffff9 (268435449): AES + + if (Version == 0xF00) + { + throw new Exception("Invalid Resource."); + } + if (Version != 0x52504637) + { + throw new Exception("Invalid Resource - not GTAV!"); + } + + + uint entriestotalbytes = EntryCount * 16; //4x uints each + uint entriesptr = (uint)br.BaseStream.Position; + uint namesptr = entriesptr + entriestotalbytes; + + byte[] entriesdata = new byte[entriestotalbytes]; + int entread = br.Read(entriesdata, 0, (int)entriestotalbytes); + + byte[] namesdata = new byte[NamesLength]; + int namread = br.Read(namesdata, 0, (int)NamesLength); + + switch (Encryption) + { + case RpfEncryption.OPEN: //nothing to do.. OpenIV modified RPF with unencrypted TOC + break; + case RpfEncryption.AES: + entriesdata = GTACrypto.DecryptAES(entriesdata); + namesdata = GTACrypto.DecryptAES(namesdata); + IsAESEncrypted = true; + break; + case RpfEncryption.NG: + entriesdata = GTACrypto.DecryptNG(entriesdata, Name, (uint)FileSize); + namesdata = GTACrypto.DecryptNG(namesdata, Name, (uint)FileSize); + IsNGEncrypted = true; + break; + default: //unknown encryption type? assume NG.. never seems to get here + entriesdata = GTACrypto.DecryptNG(entriesdata, Name, (uint)FileSize); + namesdata = GTACrypto.DecryptNG(namesdata, Name, (uint)FileSize); + break; + } + + + + var entriesrdr = new DataReader(new MemoryStream(entriesdata)); + var namesrdr = new DataReader(new MemoryStream(namesdata)); + AllEntries = new List(); + TotalFileCount = 0; + TotalFolderCount = 0; + TotalResourceCount = 0; + TotalBinaryFileCount = 0; + + for (uint i = 0; i < EntryCount; i++) + { + //entriesrdr.Position += 4; + uint y = entriesrdr.ReadUInt32(); + uint x = entriesrdr.ReadUInt32(); + entriesrdr.Position -= 8; + + RpfEntry e; + + if (x == 0x7fffff00) //directory entry + { + e = new RpfDirectoryEntry(); + TotalFolderCount++; + } + else if ((x & 0x80000000) == 0) //binary file entry + { + e = new RpfBinaryFileEntry(); + TotalBinaryFileCount++; + TotalFileCount++; + } + else //assume resource file entry + { + e = new RpfResourceFileEntry(); + TotalResourceCount++; + TotalFileCount++; + } + + e.File = this; + e.H1 = y; + e.H2 = x; + + e.Read(entriesrdr); + + namesrdr.Position = e.NameOffset; + e.Name = namesrdr.ReadString(); + e.NameLower = e.Name.ToLower(); + + if ((e is RpfFileEntry) && string.IsNullOrEmpty(e.Name)) + { + } + if ((e is RpfResourceFileEntry))// && string.IsNullOrEmpty(e.Name)) + { + var rfe = e as RpfResourceFileEntry; + rfe.IsEncrypted = rfe.NameLower.EndsWith(".ysc");//any other way to know..? + } + + AllEntries.Add(e); + } + + + + Root = (RpfDirectoryEntry)AllEntries[0]; + Root.Path = Path.ToLower();// + "\\" + Root.Name; + var stack = new Stack(); + stack.Push(Root); + while (stack.Count > 0) + { + var item = stack.Pop(); + + for (int i = (int)item.EntriesIndex; i < (item.EntriesIndex + item.EntriesCount); i++) + { + RpfEntry e = AllEntries[i]; + if (e is RpfDirectoryEntry) + { + RpfDirectoryEntry rde = e as RpfDirectoryEntry; + rde.Path = item.Path + "\\" + rde.NameLower; + item.Directories.Add(rde); + stack.Push(rde); + } + else if (e is RpfFileEntry) + { + RpfFileEntry rfe = e as RpfFileEntry; + rfe.Path = item.Path + "\\" + rfe.NameLower; + item.Files.Add(rfe); + } + } + } + + br.BaseStream.Position = StartPos; + + CurrentFileReader = null; + + } + + + + + public void ScanStructure(Action updateStatus, Action errorLog) + { + using (BinaryReader br = new BinaryReader(File.OpenRead(FilePath))) + { + try + { + ScanStructure(br, updateStatus, errorLog); + } + catch (Exception ex) + { + LastError = ex.ToString(); + LastException = ex; + errorLog(FilePath + ": " + LastError); + } + } + } + private void ScanStructure(BinaryReader br, Action updateStatus, Action errorLog) + { + ReadHeader(br); + + Children = new List(); + + GrandTotalRpfCount = 1; //count this file.. + GrandTotalFileCount = 1; //start with this one. + GrandTotalFolderCount = 0; + GrandTotalResourceCount = 0; + GrandTotalBinaryFileCount = 0; + + + updateStatus?.Invoke("Scanning " + Path + "..."); + + foreach (RpfEntry entry in AllEntries) + { + try + { + if (entry is RpfBinaryFileEntry) + { + RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; + long l = binentry.FileSize; + if (l == 0) l = binentry.FileUncompressedSize; + + //search all the sub resources for YSC files. (recurse!) + string lname = binentry.NameLower; + if (lname.EndsWith(".rpf")) + { + br.BaseStream.Position = StartPos + (binentry.FileOffset * 512); + + RpfFile subfile = new RpfFile(binentry.Name, binentry.Path, binentry.Path, l, binentry.FileSize != 0, binentry.IsEncrypted, RootFileName, RootFileSize); + subfile.UncompressedSize = binentry.FileUncompressedSize; + subfile.Parent = this; + + subfile.ScanStructure(br, updateStatus, errorLog); + + GrandTotalRpfCount += subfile.GrandTotalRpfCount; + GrandTotalFileCount += subfile.GrandTotalFileCount; + GrandTotalFolderCount += subfile.GrandTotalFolderCount; + GrandTotalResourceCount += subfile.GrandTotalResourceCount; + GrandTotalBinaryFileCount += subfile.GrandTotalBinaryFileCount; + + + Children.Add(subfile); + } + else + { + //binary file that's not an rpf... + GrandTotalBinaryFileCount++; + GrandTotalFileCount++; + } + } + else if (entry is RpfResourceFileEntry) + { + GrandTotalResourceCount++; + GrandTotalFileCount++; + } + else if (entry is RpfDirectoryEntry) + { + GrandTotalFolderCount++; + } + } + catch (Exception ex) + { + errorLog(entry.Path + ": " + ex.ToString()); + } + } + + } + + + public void ExtractScripts(string outputfolder, Action updateStatus) + { + FileStream fs = File.OpenRead(FilePath); + BinaryReader br = new BinaryReader(fs); + + try + { + ExtractScripts(br, outputfolder, updateStatus); + } + catch (Exception ex) + { + LastError = ex.ToString(); + LastException = ex; + } + + br.Close(); + br.Dispose(); + fs.Dispose(); + } + private void ExtractScripts(BinaryReader br, string outputfolder, Action updateStatus) + { + updateStatus?.Invoke("Searching " + Name + "..."); + + ReadHeader(br); + + //List blocks = new List(); + foreach (RpfEntry entry in AllEntries) + { + if (entry is RpfBinaryFileEntry) + { + RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; + long l = binentry.FileSize; + if (l == 0) l = binentry.FileUncompressedSize; + + //search all the sub resources for YSC files. (recurse!) + string lname = binentry.NameLower; + if (lname.EndsWith(".rpf")) + { + br.BaseStream.Position = StartPos + (binentry.FileOffset * 512); + + RpfFile subfile = new RpfFile(binentry.Name, binentry.Path, binentry.Path, l, binentry.FileSize != 0, binentry.IsEncrypted, RootFileName, RootFileSize); + subfile.UncompressedSize = binentry.FileUncompressedSize; + subfile.Parent = this; + + subfile.ExtractScripts(br, outputfolder, updateStatus); + } + + } + else if (entry is RpfResourceFileEntry) + { + + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + + string lname = resentry.NameLower; + + if (lname.EndsWith(".ysc")) + { + updateStatus?.Invoke("Extracting " + resentry.Name + "..."); + + //found a YSC file. extract it! + string ofpath = outputfolder + "\\" + resentry.Name; + + br.BaseStream.Position = StartPos + (resentry.FileOffset * 512); + + if (resentry.FileSize > 0) + { + uint offset = 0x10; + uint totlen = resentry.FileSize - offset; + + byte[] tbytes = new byte[totlen]; + + br.BaseStream.Position += offset; + + br.Read(tbytes, 0, (int)totlen); + + byte[] decr; + if (IsAESEncrypted) + { + decr = GTACrypto.DecryptAES(tbytes); + + //special case! probable duplicate pilot_school.ysc + ofpath = outputfolder + "\\" + Name + "___" + resentry.Name; + } + else + { + decr = GTACrypto.DecryptNG(tbytes, resentry.Name, resentry.FileSize); + } + + + try + { + MemoryStream ms = new MemoryStream(decr); + DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress); + + MemoryStream outstr = new MemoryStream(); + ds.CopyTo(outstr); + byte[] deflated = outstr.GetBuffer(); + byte[] outbuf = new byte[outstr.Length]; //need to copy to the right size buffer for File.WriteAllBytes(). + Array.Copy(deflated, outbuf, outbuf.Length); + + bool pathok = true; + if (File.Exists(ofpath)) + { + ofpath = outputfolder + "\\" + Name + "_" + resentry.Name; + if (File.Exists(ofpath)) + { + LastError = "Output file " + ofpath + " already exists!"; + pathok = false; + } + } + if (pathok) + { + File.WriteAllBytes(ofpath, outbuf); + } + } + catch (Exception ex) + { + LastError = ex.ToString(); + LastException = ex; + } + + + } + } + + } + } + + + + + + } + + + + + + public byte[] ExtractFile(RpfFileEntry entry) + { + try + { + using (BinaryReader br = new BinaryReader(File.OpenRead(GetPhysicalFilePath()))) + { + if (entry is RpfBinaryFileEntry) + { + return ExtractFileBinary(entry as RpfBinaryFileEntry, br); + } + else if (entry is RpfResourceFileEntry) + { + return ExtractFileResource(entry as RpfResourceFileEntry, br); + } + else + { + return null; + } + } + } + catch (Exception ex) + { + LastError = ex.ToString(); + LastException = ex; + return null; + } + } + public byte[] ExtractFileBinary(RpfBinaryFileEntry entry, BinaryReader br) + { + br.BaseStream.Position = StartPos + ((long)entry.FileOffset * 512); + + long l = entry.FileSize; + if (l == 0) l = entry.FileUncompressedSize; + + if (l > 0) + { + uint offset = 0;// 0x10; + uint totlen = (uint)l - offset; + + byte[] tbytes = new byte[totlen]; + + br.BaseStream.Position += offset; + br.Read(tbytes, 0, (int)totlen); + + byte[] decr = tbytes; + + if (entry.IsEncrypted) + { + if (IsAESEncrypted) + { + decr = GTACrypto.DecryptAES(tbytes); + } + else //if (IsNGEncrypted) //assume the archive is set to NG encryption if not AES... (comment: fix for openIV modded files) + { + decr = GTACrypto.DecryptNG(tbytes, entry.Name, entry.FileUncompressedSize); + } + //else + //{ } + } + + byte[] defl = decr; + + if (entry.FileSize > 0) //apparently this means it's compressed + { + defl = DecompressBytes(decr); + } + else + { + } + + return defl; + } + + return null; + } + public byte[] ExtractFileResource(RpfResourceFileEntry entry, BinaryReader br) + { + br.BaseStream.Position = StartPos + ((long)entry.FileOffset * 512); + + + if (entry.FileSize > 0) + { + uint offset = 0x10; + uint totlen = entry.FileSize - offset; + + byte[] tbytes = new byte[totlen]; + + + br.BaseStream.Position += offset; + //byte[] hbytes = new byte[16]; //what are these 16 bytes actually used for? + //br.Read(hbytes, 0, 16); + //MetaHash h1 = br.ReadUInt32(); + //MetaHash h2 = br.ReadUInt32(); + //MetaHash h3 = br.ReadUInt32(); + //MetaHash h4 = br.ReadUInt32(); + //long l1 = br.ReadInt64(); + //long l2 = br.ReadInt64(); + + + br.Read(tbytes, 0, (int)totlen); + + byte[] decr = tbytes; + if (entry.IsEncrypted) + { + if (IsAESEncrypted) + { + decr = GTACrypto.DecryptAES(tbytes); + } + else //if (IsNGEncrypted) //assume the archive is set to NG encryption if not AES... (comment: fix for openIV modded files) + { + decr = GTACrypto.DecryptNG(tbytes, entry.Name, entry.FileSize); + } + //else + //{ } + } + + byte[] deflated = DecompressBytes(decr); + + byte[] data = null; + + if (deflated != null) + { + data = deflated; + } + else + { + entry.FileSize -= offset; + data = decr; + } + + + return data; + } + + return null; + } + + public static T GetFile(RpfEntry e) where T : class, PackedFile, new() + { + T file = null; + byte[] data = null; + RpfFileEntry entry = e as RpfFileEntry; + if (entry != null) + { + data = entry.File.ExtractFile(entry); + } + if (data != null) + { + file = new T(); + file.Load(data, entry); + } + return file; + } + public static T GetFile(RpfEntry e, byte[] data) where T : class, PackedFile, new() + { + T file = null; + RpfFileEntry entry = e as RpfFileEntry; + if ((data != null)) + { + if (entry == null) + { + entry = CreateResourceFileEntry(data, 0); + } + file = new T(); + file.Load(data, entry); + } + return file; + } + public static T GetResourceFile(byte[] data) where T : class, PackedFile, new() + { + T file = null; + RpfFileEntry entry = CreateResourceFileEntry(data, 0); + if ((data != null) && (entry != null)) + { + file = new T(); + file.Load(data, entry); + } + return file; + } + + + + public static RpfResourceFileEntry CreateResourceFileEntry(byte[] data, uint ver) + { + var resentry = new RpfResourceFileEntry(); + + //hopefully this format has an RSC7 header... + uint rsc7 = BitConverter.ToUInt32(data, 0); + if (rsc7 == 0x37435352) //RSC7 header present! + { + int version = BitConverter.ToInt32(data, 4);//use this instead of what was given... + resentry.SystemFlags = BitConverter.ToUInt32(data, 8); + resentry.GraphicsFlags = BitConverter.ToUInt32(data, 12); + //if (data.Length > 16) + //{ + // int newlen = data.Length - 16; //trim the header from the data passed to the next step. + // byte[] newdata = new byte[newlen]; + // Buffer.BlockCopy(data, 16, newdata, 0, newlen); + // data = newdata; + //} + //else + //{ + // data = null; //shouldn't happen... empty.. + //} + } + else + { + //direct load from file without the rpf header.. + //assume it's in resource meta format + resentry.SystemFlags = RpfResourceFileEntry.GetFlagsFromSize(data.Length, 0); + resentry.GraphicsFlags = RpfResourceFileEntry.GetFlagsFromSize(0, ver); //graphics type 2 for ymap + } + + resentry.Name = ""; + resentry.NameLower = ""; + + return resentry; + } + + + + public string TestExtractAllFiles() + { + StringBuilder sb = new StringBuilder(); + ExtractedByteCount = 0; + try + { + using (BinaryReader br = new BinaryReader(File.OpenRead(GetPhysicalFilePath()))) + { + foreach (RpfEntry entry in AllEntries) + { + try + { + LastError = string.Empty; + LastException = null; + if (!entry.NameLower.EndsWith(".rpf")) //don't try to extract rpf's, they will be done separately.. + { + if (entry is RpfBinaryFileEntry) + { + RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; + byte[] data = ExtractFileBinary(binentry, br); + if (data == null) + { + if (binentry.FileSize == 0) + { + sb.AppendFormat("{0} : Binary FileSize is 0.", entry.Path); + sb.AppendLine(); + } + else + { + sb.AppendFormat("{0} : {1}", entry.Path, LastError); + sb.AppendLine(); + } + } + else if (data.Length == 0) + { + sb.AppendFormat("{0} : Decompressed output was empty.", entry.Path); + sb.AppendLine(); + } + else + { + ExtractedByteCount += data.Length; + } + } + else if (entry is RpfResourceFileEntry) + { + RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; + byte[] data = ExtractFileResource(resentry, br); + if (data == null) + { + if (resentry.FileSize == 0) + { + sb.AppendFormat("{0} : Resource FileSize is 0.", entry.Path); + sb.AppendLine(); + } + else + { + sb.AppendFormat("{0} : {1}", entry.Path, LastError); + sb.AppendLine(); + } + } + else if (data.Length == 0) + { + sb.AppendFormat("{0} : Decompressed output was empty.", entry.Path); + sb.AppendLine(); + } + else + { + ExtractedByteCount += data.Length; + } + } + } + } + catch (Exception ex) + { + LastError = ex.ToString(); + LastException = ex; + sb.AppendFormat("{0} : {1}", entry.Path, ex.Message); + sb.AppendLine(); + } + } + } + } + catch (Exception ex) + { + LastError = ex.ToString(); + LastException = ex; + sb.AppendFormat("{0} : {1}", Path, ex.Message); + sb.AppendLine(); + return null; + } + return sb.ToString(); + } + + + + + public List GetFiles(string folder, bool recurse) + { + List result = new List(); + string[] parts = folder.ToLower().Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); + RpfDirectoryEntry dir = Root; + for (int i = 0; i < parts.Length; i++) + { + if (dir == null) break; + dir = FindSubDirectory(dir, parts[i]); + } + if (dir != null) + { + GetFiles(dir, result, recurse); + } + return result; + } + public void GetFiles(RpfDirectoryEntry dir, List result, bool recurse) + { + if (dir.Files != null) + { + result.AddRange(dir.Files); + } + if (recurse) + { + if (dir.Directories != null) + { + for (int i = 0; i < dir.Directories.Count; i++) + { + GetFiles(dir.Directories[i], result, recurse); + } + } + } + } + + private RpfDirectoryEntry FindSubDirectory(RpfDirectoryEntry dir, string name) + { + if (dir == null) return null; + if (dir.Directories == null) return null; + for (int i = 0; i < dir.Directories.Count; i++) + { + var cdir = dir.Directories[i]; + if (cdir.Name.ToLower() == name) + { + return cdir; + } + } + return null; + } + + + + + public byte[] DecompressBytes(byte[] bytes) + { + try + { + using (DeflateStream ds = new DeflateStream(new MemoryStream(bytes), CompressionMode.Decompress)) + { + MemoryStream outstr = new MemoryStream(); + ds.CopyTo(outstr); + byte[] deflated = outstr.GetBuffer(); + byte[] outbuf = new byte[outstr.Length]; //need to copy to the right size buffer for output. + Array.Copy(deflated, outbuf, outbuf.Length); + + if (outbuf.Length <= bytes.Length) + { + LastError = "Decompressed data was smaller than compressed data..."; + return null; + } + + return outbuf; + } + } + catch (Exception ex) + { + LastError = "Could not decompress.";// ex.ToString(); + LastException = ex; + return null; + } + } + + + public override string ToString() + { + return Path; + } + } + + + public enum RpfEncryption : uint + { + OPEN = 0x4E45504F, //1313165391 "OPEN", ie. "no encryption?" + AES = 0x0FFFFFF9, //268435449 + NG = 0x0FEFFFFF, //267386879 + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public abstract class RpfEntry + { + public RpfFile File { get; set; } + + public uint NameHash { get; set; } + public uint ShortNameHash { get; set; } + + public uint NameOffset { get; set; } + public string Name { get; set; } + public string NameLower { get; set; } + public string Path { get; set; } + + public uint H1; //first 2 header values from RPF table... + public uint H2; + + public abstract void Read(DataReader reader); + public abstract void Write(DataWriter writer); + + public override string ToString() + { + return Path; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class RpfDirectoryEntry : RpfEntry + { + public uint EntriesIndex { get; set; } + public uint EntriesCount { get; set; } + + public List Directories = new List(); + public List Files = new List(); + + public override void Read(DataReader reader) + { + NameOffset = reader.ReadUInt32(); + uint ident = reader.ReadUInt32(); + if (ident != 0x7FFFFF00u) + { + throw new Exception("Error in RPF7 directory entry."); + } + EntriesIndex = reader.ReadUInt32(); + EntriesCount = reader.ReadUInt32(); + } + public override void Write(DataWriter writer) + { + writer.Write(NameOffset); + writer.Write(0x7FFFFF00u); + writer.Write(EntriesIndex); + writer.Write(EntriesCount); + } + public override string ToString() + { + return "Directory: " + Path; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public abstract class RpfFileEntry : RpfEntry + { + public uint FileOffset { get; set; } + public uint FileSize { get; set; } + public bool IsEncrypted { get; set; } + + public virtual long GetFileSize() + { + return FileSize; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class RpfBinaryFileEntry : RpfFileEntry + { + public uint FileUncompressedSize { get; set; } + + public override void Read(DataReader reader) + { + NameOffset = reader.ReadUInt16(); + + var buf1 = reader.ReadBytes(3); + FileSize = (uint)buf1[0] + (uint)(buf1[1] << 8) + (uint)(buf1[2] << 16); + + var buf2 = reader.ReadBytes(3); + FileOffset = (uint)buf2[0] + (uint)(buf2[1] << 8) + (uint)(buf2[2] << 16); + + FileUncompressedSize = reader.ReadUInt32(); + + switch (reader.ReadUInt32()) + { + case 0: IsEncrypted = false; break; + case 1: IsEncrypted = true; break; + default: + throw new Exception("Error in RPF7 file entry."); + } + } + public override void Write(DataWriter writer) + { + writer.Write((ushort)NameOffset); + + var buf1 = new byte[] { + (byte)((FileSize >> 0) & 0xFF), + (byte)((FileSize >> 8) & 0xFF), + (byte)((FileSize >> 16) & 0xFF) + }; + writer.Write(buf1); + + var buf2 = new byte[] { + (byte)((FileOffset >> 0) & 0xFF), + (byte)((FileOffset >> 8) & 0xFF), + (byte)((FileOffset >> 16) & 0xFF) + }; + writer.Write(buf2); + + writer.Write(FileUncompressedSize); + + if (IsEncrypted) + writer.Write((uint)1); + else + writer.Write((uint)0); + } + public override string ToString() + { + return "Binary file: " + Path; + } + + public override long GetFileSize() + { + return FileUncompressedSize; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class RpfResourceFileEntry : RpfFileEntry + { + public uint SystemFlags { get; set; } + public uint GraphicsFlags { get; set; } + + + public static int GetSizeFromFlags(uint flags) + { + //dexfx simplified version + var s0 = ((flags >> 27) & 0x1) << 0; // 1 bit - 27 (*1) + var s1 = ((flags >> 26) & 0x1) << 1; // 1 bit - 26 (*2) + var s2 = ((flags >> 25) & 0x1) << 2; // 1 bit - 25 (*4) + var s3 = ((flags >> 24) & 0x1) << 3; // 1 bit - 24 (*8) + var s4 = ((flags >> 17) & 0x7F) << 4; // 7 bits - 17 - 23 (*16) (max 127 * 16) + var s5 = ((flags >> 11) & 0x3F) << 5; // 6 bits - 11 - 16 (*32) (max 63 * 32) + var s6 = ((flags >> 7) & 0xF) << 6; // 4 bits - 7 - 10 (*64) (max 15 * 64) + var s7 = ((flags >> 5) & 0x3) << 7; // 2 bits - 5 - 6 (*128) (max 3 * 128) + var s8 = ((flags >> 4) & 0x1) << 8; // 1 bit - 4 (*256) + var ss = ((flags >> 0) & 0xF); // 4 bits - 0 - 3 + var baseSize = 0x200 << (int)ss; + var size = baseSize * (s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8); + return (int)size; + + + //var type = flags >> 28; + //var test = GetFlagsFromSize((int)size, type); + //s0 = ((test >> 27) & 0x1) << 0; // 1 bit - 27 (*1) + //s1 = ((test >> 26) & 0x1) << 1; // 1 bit - 26 (*2) + //s2 = ((test >> 25) & 0x1) << 2; // 1 bit - 25 (*4) + //s3 = ((test >> 24) & 0x1) << 3; // 1 bit - 24 (*8) + //s4 = ((test >> 17) & 0x7F) << 4; // 7 bits - 17 - 23 (*16) (max 127 * 16) + //s5 = ((test >> 11) & 0x3F) << 5; // 6 bits - 11 - 16 (*32) (max 63 * 32) + //s6 = ((test >> 7) & 0xF) << 6; // 4 bits - 7 - 10 (*64) (max 15 * 64) + //s7 = ((test >> 5) & 0x3) << 7; // 2 bits - 5 - 6 (*128) (max 3 * 128) + //s8 = ((test >> 4) & 0x1) << 8; // 1 bit - 4 (*256) + //ss = ((test >> 0) & 0xF); // 4 bits - 0 - 3 + //baseSize = 0x200 << (int)ss; + //var tsize = baseSize * (s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8); + //if (tsize != size) + //{ } + + + //if (s8 == 256) + //{ } + //if ((s0 != 0) || (s1 != 0) || (s2 != 0) || (s3 != 0)) + //{ } + + + //return (int)size; + + //examples: + //size:8192, ss:0, s4:1 (ytd) + //size:16384, ss:0, s5:1 (ytyp) + //size:24576, ss:0, s4:1, s5:1 (ytyp) + //size:40960, ss:0, s4:1, s5:2 (ytyp) + //size:49152, ss:0, s4:2, s5:2 (ytyp) + //size:237568, ss:0, s4:5, s7:1, s8:1 (yft) + //size:262144, ss:1, s8:1 (yft) + //size:589824, ss:1, s6:9 (ytd) + //size:663552, ss:1, s3:1, s4:12, s6:1, s7:3 (ydd) + //size:606208, ss:2, s3:1, s4:2, s8:1 (ydr) + //size:958464, ss:2, s2:1, s4:1, s6:3, s8:1 (ydr) + //size:966656, ss:2, s3:1, s4:1, s6:3, s8:1 (ydr) + //size:1695744, ss:2, s2:1, s3:1, s4:5, s5:3, s7:3, s8:1 (ydr) + //size:2768896, ss:3, s2:1, s4:24, s5:1, s6:4 (ydd) + //size:4063232, ss:4, s4:15, s7:2 (ytd) + //size:8650752, ss:5, s4:13, s6:5 (ytd) + + + + + + + + #region original neo version (system) + //const int RESOURCE_IDENT = 0x37435352; + //const int BASE_SIZE = 0x2000; + //var SystemPagesDiv16 = (int)(SystemFlags >> 27) & 0x1; + //var SystemPagesDiv8 = (int)(SystemFlags >> 26) & 0x1; + //var SystemPagesDiv4 = (int)(SystemFlags >> 25) & 0x1; + //var SystemPagesDiv2 = (int)(SystemFlags >> 24) & 0x1; + //var SystemPagesMul1 = (int)(SystemFlags >> 17) & 0x7F; + //var SystemPagesMul2 = (int)(SystemFlags >> 11) & 0x3F; + //var SystemPagesMul4 = (int)(SystemFlags >> 7) & 0xF; + //var SystemPagesMul8 = (int)(SystemFlags >> 5) & 0x3; + //var SystemPagesMul16 = (int)(SystemFlags >> 4) & 0x1; + //var SystemPagesSizeShift = (int)(SystemFlags >> 0) & 0xF; + //var systemBaseSize = BASE_SIZE << SystemPagesSizeShift; + //return + // (systemBaseSize * SystemPagesDiv16) / 16 + + // (systemBaseSize * SystemPagesDiv8) / 8 + + // (systemBaseSize * SystemPagesDiv4) / 4 + + // (systemBaseSize * SystemPagesDiv2) / 2 + + // (systemBaseSize * SystemPagesMul1) * 1 + + // (systemBaseSize * SystemPagesMul2) * 2 + + // (systemBaseSize * SystemPagesMul4) * 4 + + // (systemBaseSize * SystemPagesMul8) * 8 + + // (systemBaseSize * SystemPagesMul16) * 16; + #endregion + + + #region original neo version (graphics) + //const int RESOURCE_IDENT = 0x37435352; + //const int BASE_SIZE = 0x2000; + //var GraphicsPagesDiv16 = (int)(GraphicsFlags >> 27) & 0x1; + //var GraphicsPagesDiv8 = (int)(GraphicsFlags >> 26) & 0x1; + //var GraphicsPagesDiv4 = (int)(GraphicsFlags >> 25) & 0x1; + //var GraphicsPagesDiv2 = (int)(GraphicsFlags >> 24) & 0x1; + //var GraphicsPagesMul1 = (int)(GraphicsFlags >> 17) & 0x7F; + //var GraphicsPagesMul2 = (int)(GraphicsFlags >> 11) & 0x3F; + //var GraphicsPagesMul4 = (int)(GraphicsFlags >> 7) & 0xF; + //var GraphicsPagesMul8 = (int)(GraphicsFlags >> 5) & 0x3; + //var GraphicsPagesMul16 = (int)(GraphicsFlags >> 4) & 0x1; + //var GraphicsPagesSizeShift = (int)(GraphicsFlags >> 0) & 0xF; + //var graphicsBaseSize = BASE_SIZE << GraphicsPagesSizeShift; + //return + // graphicsBaseSize * GraphicsPagesDiv16 / 16 + + // graphicsBaseSize * GraphicsPagesDiv8 / 8 + + // graphicsBaseSize * GraphicsPagesDiv4 / 4 + + // graphicsBaseSize * GraphicsPagesDiv2 / 2 + + // graphicsBaseSize * GraphicsPagesMul1 * 1 + + // graphicsBaseSize * GraphicsPagesMul2 * 2 + + // graphicsBaseSize * GraphicsPagesMul4 * 4 + + // graphicsBaseSize * GraphicsPagesMul8 * 8 + + // graphicsBaseSize * GraphicsPagesMul16 * 16; + #endregion + + } + public static uint GetFlagsFromSize(int size, uint version) + { + //WIP - may make crashes :( + //type: see SystemSize and GraphicsSize below + + //aim for s4: blocksize (0 remainder for 0x2000 block) + int origsize = size; + int remainder = size & 0x1FF; + int blocksize = 0x200; + if (remainder != 0) + { + size = (size - remainder) + blocksize; //round up to the minimum blocksize + } + + uint blockcount = (uint)size >> 9; //how many blocks of the minimum size (0x200) + uint ss = 0; + while (blockcount > 1024) + { + ss++; + blockcount = blockcount >> 1; + } + if (ss > 0) + { + size = origsize; + blocksize = blocksize << (int)ss; //adjust the block size to reduce the block count. + remainder = size & blocksize; + if(remainder!=0) + { + size = (size - remainder) + blocksize; //readjust size with round-up + } + } + + var s0 = (blockcount >> 0) & 0x1; //*1 X + var s1 = (blockcount >> 1) & 0x1; //*2 X + var s2 = (blockcount >> 2) & 0x1; //*4 X + var s3 = (blockcount >> 3) & 0x1; //*8 X + var s4 = (blockcount >> 4) & 0x7F; //*16 7 bits XXXXXXX + var s5 = (blockcount >> 5) & 0x3F; //*32 6 bits XXXXXX + var s6 = (blockcount >> 6) & 0xF; //*64 4 bits XXXX + var s7 = (blockcount >> 7) & 0x3; //*128 2 bits XX + var s8 = (blockcount >> 8) & 0x1; //*256 X + + if (ss > 4) + { } + if (s4 > 0x7F) + { } //too big... + //needs more work to include higher bits.. + + + uint f = 0; + f |= (version & 0xF) << 28; + f |= (s0 & 0x1) << 27; + f |= (s1 & 0x1) << 26; + f |= (s2 & 0x1) << 25; + f |= (s3 & 0x1) << 24; + f |= (s4 & 0x7F) << 17; + f |= (ss & 0xF); + + + + return f; + + + //var s0 = ((flags >> 27) & 0x1) << 0; // 1 bit - 27 (*1) + //var s1 = ((flags >> 26) & 0x1) << 1; // 1 bit - 26 (*2) + //var s2 = ((flags >> 25) & 0x1) << 2; // 1 bit - 25 (*4) + //var s3 = ((flags >> 24) & 0x1) << 3; // 1 bit - 24 (*8) + //var s4 = ((flags >> 17) & 0x7F) << 4; // 7 bits - 17 - 23 (*16) (max 127 * 16) + //var s5 = ((flags >> 11) & 0x3F) << 5; // 6 bits - 11 - 16 (*32) (max 63 * 32) + //var s6 = ((flags >> 7) & 0xF) << 6; // 4 bits - 7 - 10 (*64) (max 15 * 64) + //var s7 = ((flags >> 5) & 0x3) << 7; // 2 bits - 5 - 6 (*128) (max 3 * 128) + //var s8 = ((flags >> 4) & 0x1) << 8; // 1 bit - 4 (*256) + //var ss = ((flags >> 0) & 0xF); // 4 bits - 0 - 3 + //var baseSize = 0x200 << (int)ss; + //var size = baseSize * (s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8); + + + } + public static uint GetFlagsFromBlocks(uint blockCount, uint blockSize, uint version) + { + + //dexfx test version - seems to work mostly... + + uint s0 = 0; + uint s1 = 0; + uint s2 = 0; + uint s3 = 0; + uint s4 = 0; + uint s5 = 0; + uint s6 = 0; + uint s7 = 0; + uint s8 = 0; + uint ss = 0; + + uint bst = blockSize; + if (blockCount > 0) + { + while (bst > 0x200) //ss is number of bits to shift 0x200 to get blocksize... + { + ss++; + bst = bst >> 1; + } + } + s0 = (blockCount >> 0) & 0x1; //*1 X + s1 = (blockCount >> 1) & 0x1; //*2 X + s2 = (blockCount >> 2) & 0x1; //*4 X + s3 = (blockCount >> 3) & 0x1; //*8 X + s4 = (blockCount >> 4) & 0x7F; //*16 7 bits XXXXXXX + //s5 = (blockCount >> 5) & 0x3F; //*32 6 bits XXXXXX + //s6 = (blockCount >> 6) & 0xF; //*64 4 bits XXXX + //s7 = (blockCount >> 7) & 0x3; //*128 2 bits XX + //s8 = (blockCount >> 8) & 0x1; //*256 X + + + //if (blockCount > 0) + //{ + // var curblocksize = 0x2000u; + // var totsize = blockCount * blockSize; + // var totcount = totsize / curblocksize; + // if ((totsize % curblocksize) > 0) totcount++; + // ss = 4; + // while (totcount > 0x7f) + // { + // ss++; + // curblocksize = curblocksize << 1; + // totcount = totsize / curblocksize; + // if ((totsize % curblocksize) > 0) totcount++; + // if (ss >= 16) + // { break; } + // } + // s4 = totcount >> 4; + // s3 = (totcount >> 3) & 1; + // s2 = (totcount >> 2) & 1; + // s1 = (totcount >> 1) & 1; + // s0 = (totcount >> 0) & 1; + //} + + + + if (ss > 0xF) + { } //too big... + if (s4 > 0x7F) + { } //too big... + //needs more work to include higher bits.. + + + uint f = 0; + f |= (version & 0xF) << 28; + f |= (s0 & 0x1) << 27; + f |= (s1 & 0x1) << 26; + f |= (s2 & 0x1) << 25; + f |= (s3 & 0x1) << 24; + f |= (s4 & 0x7F) << 17; + f |= (s5 & 0x3F) << 11; + f |= (s6 & 0xF) << 7; + f |= (s7 & 0x3) << 5; + f |= (s8 & 0x1) << 4; + f |= (ss & 0xF); + + + + return f; + } + public static int GetVersionFromFlags(uint sysFlags, uint gfxFlags) + { + var sv = (sysFlags >> 28) & 0xF; + var gv = (gfxFlags >> 28) & 0xF; + return (int)((sv << 4) + gv); + } + + + public int Version + { + get + { + return GetVersionFromFlags(SystemFlags, GraphicsFlags); + } + } + + + public int SystemSize + { + get + { + var sv = (SystemFlags >> 28); + switch(sv) + { + case 0: break; //ytd, ytyp, ... + case 10:break;//ydr, ydd, yft + case 4:break; //ypt + case 2:break; //ycd + case 1:break;//yed + default:break; + } + + return GetSizeFromFlags(SystemFlags); + } + } + public int GraphicsSize + { + get + { + var gv = (GraphicsFlags >> 28); + switch (gv) + { + case 0: break; //empty? some vehicle addon yft + case 1: break; //ynd + case 2: break; //ytyp, ymap + case 4: break; //yfd + case 5: break; //ydd, ydr, yft + case 9: break; //yed + case 10: break; //ysc + case 11: break; //ybn + case 13: break; //ytd + case 14: break; //ycd + default: break; + } + + return GetSizeFromFlags(GraphicsFlags); + } + } + + public override void Read(DataReader reader) + { + NameOffset = reader.ReadUInt16(); + + var buf1 = reader.ReadBytes(3); + FileSize = (uint)buf1[0] + (uint)(buf1[1] << 8) + (uint)(buf1[2] << 16); + + var buf2 = reader.ReadBytes(3); + FileOffset = ((uint)buf2[0] + (uint)(buf2[1] << 8) + (uint)(buf2[2] << 16)) & 0x7FFFFF; + + SystemFlags = reader.ReadUInt32(); + GraphicsFlags = reader.ReadUInt32(); + + // there are sometimes resources with length=0xffffff which actually + // means length>=0xffffff + if (FileSize == 0xFFFFFF) + { + BinaryReader cfr = File.CurrentFileReader; + long opos = cfr.BaseStream.Position; + cfr.BaseStream.Position = File.StartPos + ((long)FileOffset * 512); //need to use the base offset!! + var buf = cfr.ReadBytes(16); + FileSize = ((uint)buf[7] << 0) | ((uint)buf[14] << 8) | ((uint)buf[5] << 16) | ((uint)buf[2] << 24); + cfr.BaseStream.Position = opos; + } + + } + public override void Write(DataWriter writer) + { + writer.Write((ushort)NameOffset); + + var buf1 = new byte[] { + (byte)((FileSize >> 0) & 0xFF), + (byte)((FileSize >> 8) & 0xFF), + (byte)((FileSize >> 16) & 0xFF) + }; + writer.Write(buf1); + + var buf2 = new byte[] { + (byte)((FileOffset >> 0) & 0xFF), + (byte)((FileOffset >> 8) & 0xFF), + (byte)(((FileOffset >> 16) & 0xFF) | 0x80) + }; + writer.Write(buf2); + + writer.Write(SystemFlags); + writer.Write(GraphicsFlags); + } + public override string ToString() + { + return "Resource file: " + Path; + } + + public override long GetFileSize() + { + return (FileSize == 0) ? (long)(SystemSize + GraphicsSize) : FileSize; + } + } + + + + public interface PackedFile //interface for the different file types to use + { + void Load(byte[] data, RpfFileEntry entry); + } + + + + + + + + + + +} \ No newline at end of file diff --git a/GameFiles/Resources/RpfManager.cs b/GameFiles/Resources/RpfManager.cs new file mode 100644 index 0000000..7a244d6 --- /dev/null +++ b/GameFiles/Resources/RpfManager.cs @@ -0,0 +1,423 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.GameFiles +{ + public class RpfManager + { + //for caching and management of RPF file data. + + public string Folder { get; private set; } + public string[] ExcludePaths { get; set; } + public bool EnableMods { get; set; } + public Action UpdateStatus { get; private set; } + public Action ErrorLog { get; private set; } + + public List BaseRpfs { get; private set; } + public List ModRpfs { get; private set; } + public List DlcRpfs { get; private set; } + public List AllRpfs { get; private set; } + public List DlcNoModRpfs { get; private set; } + public List AllNoModRpfs { get; private set; } + public Dictionary RpfDict { get; private set; } + public Dictionary EntryDict { get; private set; } + public Dictionary ModRpfDict { get; private set; } + public Dictionary ModEntryDict { get; private set; } + + public volatile bool IsInited = false; + + public void Init(string folder, Action updateStatus, Action errorLog, bool rootOnly = false) + { + UpdateStatus = updateStatus; + ErrorLog = errorLog; + + string replpath = folder + "\\"; + var sopt = rootOnly ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories; + string[] allfiles = Directory.GetFiles(folder, "*.rpf", sopt); + + BaseRpfs = new List(); + ModRpfs = new List(); + DlcRpfs = new List(); + AllRpfs = new List(); + DlcNoModRpfs = new List(); + AllNoModRpfs = new List(); + RpfDict = new Dictionary(); + EntryDict = new Dictionary(); + ModRpfDict = new Dictionary(); + ModEntryDict = new Dictionary(); + + foreach (string rpfpath in allfiles) + { + try + { + RpfFile rf = new RpfFile(rpfpath, rpfpath.Replace(replpath, "")); + + if (ExcludePaths != null) + { + bool excl = false; + for (int i = 0; i < ExcludePaths.Length; i++) + { + if (rf.Path.StartsWith(ExcludePaths[i])) + { + excl = true; + break; + } + } + if (excl) continue; //skip files in exclude paths. + } + + rf.ScanStructure(updateStatus, errorLog); + + AddRpfFile(rf, false, false); + } + catch (Exception ex) + { + errorLog(rpfpath + ": " + ex.ToString()); + } + } + + updateStatus("Building jenkindex..."); + BuildBaseJenkIndex(); + updateStatus("Scan complete"); + + IsInited = true; + } + + public void Init(List allRpfs) + { + //fast init used by RPF explorer's File cache + AllRpfs = allRpfs; + + BaseRpfs = new List(); + ModRpfs = new List(); + DlcRpfs = new List(); + DlcNoModRpfs = new List(); + AllNoModRpfs = new List(); + RpfDict = new Dictionary(); + EntryDict = new Dictionary(); + ModRpfDict = new Dictionary(); + ModEntryDict = new Dictionary(); + foreach (var rpf in allRpfs) + { + RpfDict[rpf.Path] = rpf; + if (rpf.AllEntries == null) continue; + foreach (var entry in rpf.AllEntries) + { + EntryDict[entry.Path] = entry; + } + } + + IsInited = true; + } + + + private void AddRpfFile(RpfFile file, bool isdlc, bool ismod) + { + isdlc = isdlc || (file.NameLower == "dlc.rpf") || (file.NameLower == "update.rpf"); + ismod = ismod || (file.Path.StartsWith("mods\\")); + + if (file.AllEntries != null) + { + AllRpfs.Add(file); + if (!ismod) + { + AllNoModRpfs.Add(file); + } + if (isdlc) + { + DlcRpfs.Add(file); + if (!ismod) + { + DlcNoModRpfs.Add(file); + } + } + else + { + if (ismod) + { + ModRpfs.Add(file); + } + else + { + BaseRpfs.Add(file); + } + } + if (ismod) + { + ModRpfDict[file.Path.Substring(5)] = file; + } + + RpfDict[file.Path] = file; + + foreach (RpfEntry entry in file.AllEntries) + { + try + { + if (!string.IsNullOrEmpty(entry.Name)) + { + if (ismod) + { + ModEntryDict[entry.Path] = entry; + ModEntryDict[entry.Path.Substring(5)] = entry; + } + else + { + EntryDict[entry.Path] = entry; + } + + if (entry is RpfFileEntry) + { + RpfFileEntry fentry = entry as RpfFileEntry; + entry.NameHash = JenkHash.GenHash(entry.NameLower); + int ind = entry.NameLower.LastIndexOf('.'); + entry.ShortNameHash = (ind > 0) ? JenkHash.GenHash(entry.NameLower.Substring(0, ind)) : entry.NameHash; + if (entry.ShortNameHash != 0) + { + //EntryHashDict[entry.ShortNameHash] = entry; + } + } + + } + } + catch (Exception ex) + { + file.LastError = ex.ToString(); + file.LastException = ex; + ErrorLog(entry.Path + ": " + ex.ToString()); + } + } + } + + if (file.Children != null) + { + foreach (RpfFile cfile in file.Children) + { + AddRpfFile(cfile, isdlc, ismod); + } + } + } + + + + public RpfFile FindRpfFile(string path) + { + RpfFile file = null; //check the dictionary + + if (EnableMods && ModRpfDict.TryGetValue(path, out file)) + { + return file; + } + + if (RpfDict.TryGetValue(path, out file)) + { + return file; + } + + string lpath = path.ToLower(); //try look at names etc + foreach (RpfFile tfile in AllRpfs) + { + if (tfile.NameLower == lpath) + { + return tfile; + } + if (tfile.Path == lpath) + { + return tfile; + } + } + + return file; + } + + + public RpfEntry GetEntry(string path) + { + RpfEntry entry; + string pathl = path.ToLower(); + if (EnableMods && ModEntryDict.TryGetValue(pathl, out entry)) + { + return entry; + } + EntryDict.TryGetValue(pathl, out entry); + if (entry == null) + { + pathl = pathl.Replace("/", "\\"); + pathl = pathl.Replace("common:", "common.rpf"); + if (EnableMods && ModEntryDict.TryGetValue(pathl, out entry)) + { + return entry; + } + EntryDict.TryGetValue(pathl, out entry); + } + return entry; + } + public byte[] GetFileData(string path) + { + byte[] data = null; + RpfFileEntry entry = GetEntry(path) as RpfFileEntry; + if (entry != null) + { + data = entry.File.ExtractFile(entry); + } + return data; + } + public string GetFileUTF8Text(string path) + { + byte[] bytes = GetFileData(path); + if (bytes == null) + { return string.Empty; } //file not found.. + if ((bytes.Length > 3) && (bytes[0] == 0xEF) && (bytes[1] == 0xBB) && (bytes[2] == 0xBF)) + { + byte[] newb = new byte[bytes.Length - 3]; + for (int i = 3; i < bytes.Length; i++) + { + newb[i - 3] = bytes[i]; + } + bytes = newb; //trim starting 3 "magic" bytes? + } + return Encoding.UTF8.GetString(bytes); + } + public XmlDocument GetFileXml(string path) + { + XmlDocument doc = new XmlDocument(); + string text = GetFileUTF8Text(path); + if (!string.IsNullOrEmpty(text)) + { + doc.LoadXml(text); + } + return doc; + } + + public T GetFile(string path) where T : class, PackedFile, new() + { + T file = null; + byte[] data = null; + RpfFileEntry entry = GetEntry(path) as RpfFileEntry; + if (entry != null) + { + data = entry.File.ExtractFile(entry); + } + if (data != null) + { + file = new T(); + file.Load(data, entry); + } + return file; + } + public T GetFile(RpfEntry e) where T : class, PackedFile, new() + { + T file = null; + byte[] data = null; + RpfFileEntry entry = e as RpfFileEntry; + if (entry != null) + { + data = entry.File.ExtractFile(entry); + } + if (data != null) + { + file = new T(); + file.Load(data, entry); + } + return file; + } + public bool LoadFile(T file, RpfEntry e) where T : class, PackedFile + { + byte[] data = null; + RpfFileEntry entry = e as RpfFileEntry; + if (entry != null) + { + data = entry.File.ExtractFile(entry); + } + if (data != null) + { + file.Load(data, entry); + return true; + } + return false; + } + + + + public void BuildBaseJenkIndex() + { + JenkIndex.Clear(); + foreach (RpfFile file in AllRpfs) + { + try + { + JenkIndex.Ensure(file.Name); + foreach (RpfEntry entry in file.AllEntries) + { + var nlow = entry.NameLower; + if (string.IsNullOrEmpty(nlow)) continue; + JenkIndex.Ensure(entry.Name); + JenkIndex.Ensure(nlow); + //JenkIndex.Ensure(entry.Path); + //JenkIndex.Ensure(entry.Path.ToLower()); + int ind = nlow.LastIndexOf('.'); + if (ind > 0) + { + JenkIndex.Ensure(entry.Name.Substring(0, ind)); + JenkIndex.Ensure(nlow.Substring(0, ind)); + + //if (ind < entry.Name.Length - 2) + //{ + // JenkIndex.Ensure(entry.Name.Substring(0, ind) + ".#" + entry.Name.Substring(ind + 2)); + // JenkIndex.Ensure(entry.NameLower.Substring(0, ind) + ".#" + entry.NameLower.Substring(ind + 2)); + //} + } + if (nlow.EndsWith(".ydr") || nlow.EndsWith(".yft")) + { + var sname = nlow.Substring(0, nlow.Length - 4); + JenkIndex.Ensure(sname + "_lod"); + JenkIndex.Ensure(sname + "_loda"); + JenkIndex.Ensure(sname + "_lodb"); + } + if (nlow.EndsWith(".ydd")) + { + if (nlow.EndsWith("_children.ydd")) + { + var strn = nlow.Substring(0, nlow.Length - 13); + JenkIndex.Ensure(strn); + JenkIndex.Ensure(strn + "_lod"); + JenkIndex.Ensure(strn + "_loda"); + JenkIndex.Ensure(strn + "_lodb"); + } + var idx = nlow.LastIndexOf('_'); + if (idx > 0) + { + var str1 = nlow.Substring(0, idx); + var idx2 = str1.LastIndexOf('_'); + if (idx2 > 0) + { + var str2 = str1.Substring(0, idx2); + JenkIndex.Ensure(str2 + "_lod"); + var maxi = 100; + for (int i = 1; i <= maxi; i++) + { + var str3 = str2 + "_" + i.ToString().PadLeft(2, '0'); + //JenkIndex.Ensure(str3); + JenkIndex.Ensure(str3 + "_lod"); + } + } + } + } + + + } + + } + catch + { + //failing silently!! not so good really + } + } + } + + } +} diff --git a/GameFiles/Resources/Texture.cs b/GameFiles/Resources/Texture.cs new file mode 100644 index 0000000..6d3894a --- /dev/null +++ b/GameFiles/Resources/Texture.cs @@ -0,0 +1,591 @@ +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class TextureDictionary : ResourceFileBase + { + public override long BlockLength + { + get + { + return 64; + } + } + + // structure data + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000001 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public ResourceSimpleList64Ptr TextureNameHashesPtr { get; set; } + public uint[] TextureNameHashes { get; set; } + public ResourcePointerList64 Textures { get; set; } + + public Dictionary Dict { get; set; } + public long MemoryUsage + { + get + { + long val = 0; + if ((Textures != null) && (Textures.data_items != null)) + { + foreach (var tex in Textures.data_items) + { + if (tex != null) + { + val += tex.MemoryUsage; + } + } + } + return val; + } + } + + public TextureDictionary() + { + //this.TextureNameHashes = new ResourceSimpleList64(); + this.Textures = new ResourcePointerList64(); + } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.TextureNameHashesPtr = reader.ReadStruct(); + this.TextureNameHashes = reader.ReadUintsAt(this.TextureNameHashesPtr.EntriesPointer, this.TextureNameHashesPtr.EntriesCount); + //this.TextureNameHashes = reader.ReadBlock>(); + this.Textures = reader.ReadBlock>(); + + var dict = new Dictionary(); + if ((Textures != null) && (Textures.data_items != null) && (TextureNameHashes != null)) + { + for (int i = 0; (i < Textures.data_items.Length) && (i < TextureNameHashes.Length); i++) + { + var tex = Textures.data_items[i]; + var hash = TextureNameHashes[i]; + dict[hash] = tex; + } + } + Dict = new Dictionary(dict); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + //writer.WriteBlock(this.TextureNameHashes); //TODO: fix! + //writer.WriteBlock(this.Textures); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + //new Tuple(0x20, TextureNameHashes), //TODO: fix! + new Tuple(0x30, Textures) + }; + } + + public Dictionary GetDictionary() + { + Dictionary td = new Dictionary(); + if ((Textures != null) && (Textures.data_items != null)) + { + var texs = Textures.data_items; + var hashes = TextureNameHashes; + for (int i = 0; (i < texs.Length) && (i < hashes.Length); i++) + { + td.Add(hashes[i], texs[i]); + } + } + return td; + } + + public Texture Lookup(uint hash) + { + Texture tex = null; + if (Dict != null) + { + Dict.TryGetValue(hash, out tex); + } + return tex; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class TextureBase : ResourceSystemBlock + { + public override long BlockLength + { + get { return 64; } + } + + // structure data + public uint VFT { get; set; } + public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_8h { get; set; } // 0x00000000 + public uint Unknown_Ch { get; set; } // 0x00000000 + public uint Unknown_10h { get; set; } // 0x00000000 + public uint Unknown_14h { get; set; } // 0x00000000 + public uint Unknown_18h { get; set; } // 0x00000000 + public uint Unknown_1Ch { get; set; } // 0x00000000 + public uint Unknown_20h { get; set; } // 0x00000000 + public uint Unknown_24h { get; set; } // 0x00000000 + public ulong NamePointer { get; set; } + public uint Unknown_30h { get; set; } + public uint Unknown_34h { get; set; } // 0x00000000 + public uint Unknown_38h { get; set; } // 0x00000000 + public uint Unknown_3Ch { get; set; } // 0x00000000 + + // reference data + public string Name { get; set; } + public uint NameHash { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.VFT = reader.ReadUInt32(); + this.Unknown_4h = reader.ReadUInt32(); + this.Unknown_8h = reader.ReadUInt32(); + this.Unknown_Ch = reader.ReadUInt32(); + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.Unknown_18h = reader.ReadUInt32(); + this.Unknown_1Ch = reader.ReadUInt32(); + this.Unknown_20h = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.NamePointer = reader.ReadUInt64(); + this.Unknown_30h = reader.ReadUInt32(); + this.Unknown_34h = reader.ReadUInt32(); + this.Unknown_38h = reader.ReadUInt32(); + this.Unknown_3Ch = reader.ReadUInt32(); + + // read reference data + this.Name = reader.ReadStringAt( //BlockAt( + this.NamePointer // offset + ); + + if (!string.IsNullOrEmpty(Name)) + { + NameHash = JenkHash.GenHash(Name.ToLower()); + } + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // update structure data + //this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); //TODO: fix + + // write structure data + writer.Write(this.VFT); + writer.Write(this.Unknown_4h); + writer.Write(this.Unknown_8h); + writer.Write(this.Unknown_Ch); + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.Unknown_18h); + writer.Write(this.Unknown_1Ch); + writer.Write(this.Unknown_20h); + writer.Write(this.Unknown_24h); + writer.Write(this.NamePointer); + writer.Write(this.Unknown_30h); + writer.Write(this.Unknown_34h); + writer.Write(this.Unknown_38h); + writer.Write(this.Unknown_3Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(); + //if (Name != null) list.Add(Name); //TODO: fix + return list.ToArray(); + } + + public override string ToString() + { + return "TextureBase: " + Name; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Texture : TextureBase + { + public override long BlockLength + { + get { return 144; } + } + + // structure data + public uint Unknown_40h { get; set; } + public uint Unknown_44h { get; set; } // 0x00000000 + public uint Unknown_48h { get; set; } + public uint Unknown_4Ch { get; set; } // 0x00000000 + public ushort Width { get; set; } + public ushort Height { get; set; } + public ushort Unknown_54h { get; set; } // 0x0001 + public ushort Stride { get; set; } + public TextureFormat Format { get; set; } + public byte Unknown_5Ch { get; set; } // 0x00 + public byte Levels { get; set; } + public ushort Unknown_5Eh { get; set; } // 0x0000 + public uint Unknown_60h { get; set; } // 0x00000000 + public uint Unknown_64h { get; set; } // 0x00000000 + public uint Unknown_68h { get; set; } // 0x00000000 + public uint Unknown_6Ch { get; set; } // 0x00000000 + public ulong DataPointer { get; set; } + public uint Unknown_78h { get; set; } // 0x00000000 + public uint Unknown_7Ch { get; set; } // 0x00000000 + public uint Unknown_80h { get; set; } // 0x00000000 + public uint Unknown_84h { get; set; } // 0x00000000 + public uint Unknown_88h { get; set; } // 0x00000000 + public uint Unknown_8Ch { get; set; } // 0x00000000 + + // reference data + public TextureData Data { get; set; } + + public long MemoryUsage + { + get + { + long val = 0; + if (Data != null) + { + val += Data.FullData.LongLength; + } + return val; + } + } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + // read structure data + this.Unknown_40h = reader.ReadUInt32(); + this.Unknown_44h = reader.ReadUInt32(); + this.Unknown_48h = reader.ReadUInt32(); + this.Unknown_4Ch = reader.ReadUInt32(); + this.Width = reader.ReadUInt16(); + this.Height = reader.ReadUInt16(); + this.Unknown_54h = reader.ReadUInt16(); + this.Stride = reader.ReadUInt16(); + this.Format = (TextureFormat)reader.ReadUInt32(); + this.Unknown_5Ch = reader.ReadByte(); + this.Levels = reader.ReadByte(); + this.Unknown_5Eh = reader.ReadUInt16(); + this.Unknown_60h = reader.ReadUInt32(); + this.Unknown_64h = reader.ReadUInt32(); + this.Unknown_68h = reader.ReadUInt32(); + this.Unknown_6Ch = reader.ReadUInt32(); + this.DataPointer = reader.ReadUInt64(); + this.Unknown_78h = reader.ReadUInt32(); + this.Unknown_7Ch = reader.ReadUInt32(); + this.Unknown_80h = reader.ReadUInt32(); + this.Unknown_84h = reader.ReadUInt32(); + this.Unknown_88h = reader.ReadUInt32(); + this.Unknown_8Ch = reader.ReadUInt32(); + + // read reference data + this.Data = reader.ReadBlockAt( + this.DataPointer, // offset + this.Format, + this.Width, + this.Height, + this.Levels, + this.Stride + ); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + this.DataPointer = (ulong)this.Data.FilePosition; + + // write structure data + writer.Write(this.Unknown_40h); + writer.Write(this.Unknown_44h); + writer.Write(this.Unknown_48h); + writer.Write(this.Unknown_4Ch); + writer.Write(this.Width); + writer.Write(this.Height); + writer.Write(this.Unknown_54h); + writer.Write(this.Stride); + writer.Write((uint)this.Format); + writer.Write(this.Unknown_5Ch); + writer.Write(this.Levels); + writer.Write(this.Unknown_5Eh); + writer.Write(this.Unknown_60h); + writer.Write(this.Unknown_64h); + writer.Write(this.Unknown_68h); + writer.Write(this.Unknown_6Ch); + writer.Write(this.DataPointer); + writer.Write(this.Unknown_78h); + writer.Write(this.Unknown_7Ch); + writer.Write(this.Unknown_80h); + writer.Write(this.Unknown_84h); + writer.Write(this.Unknown_88h); + writer.Write(this.Unknown_8Ch); + } + + /// + /// Returns a list of data blocks which are referenced by this block. + /// + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + list.Add(Data); + return list.ToArray(); + } + + public override string ToString() + { + return "Texture: " + Width.ToString() + "x" + Height.ToString() + ": " + Name; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class TextureData : ResourceGraphicsBlock + { + public override long BlockLength + { + get + { + return FullData.Length; + } + } + + public byte[] FullData { get; set; } + + /// + /// Reads the data-block from a stream. + /// + public override void Read(ResourceDataReader reader, params object[] parameters) + { + uint format = Convert.ToUInt32(parameters[0]); + int Width = Convert.ToInt32(parameters[1]); + int Height = Convert.ToInt32(parameters[2]); + int Levels = Convert.ToInt32(parameters[3]); + int Stride = Convert.ToInt32(parameters[4]); + + int fullLength = 0; + int length = Stride * Height; + for (int i = 0; i < Levels; i++) + { + fullLength += length; + length /= 4; + } + + FullData = reader.ReadBytes(fullLength); + } + + /// + /// Writes the data-block to a stream. + /// + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + writer.Write(FullData); + } + } + + + public enum TextureFormat : uint + { + D3DFMT_A8R8G8B8 = 21, + D3DFMT_A1R5G5B5 = 25, + D3DFMT_A8 = 28, + D3DFMT_A8B8G8R8 = 32, + D3DFMT_L8 = 50, + + // fourCC + D3DFMT_DXT1 = 0x31545844, + D3DFMT_DXT3 = 0x33545844, + D3DFMT_DXT5 = 0x35545844, + D3DFMT_ATI1 = 0x31495441, + D3DFMT_ATI2 = 0x32495441, + D3DFMT_BC7 = 0x20374342, + + //UNKNOWN + } + + public static class TextureFormats + { + public static SharpDX.DXGI.Format GetDXGIFormat(TextureFormat fmt) + { + SharpDX.DXGI.Format format = SharpDX.DXGI.Format.Unknown; + switch (fmt) + { + // compressed + case TextureFormat.D3DFMT_DXT1: format = SharpDX.DXGI.Format.BC1_UNorm; break; + case TextureFormat.D3DFMT_DXT3: format = SharpDX.DXGI.Format.BC2_UNorm; break; + case TextureFormat.D3DFMT_DXT5: format = SharpDX.DXGI.Format.BC3_UNorm; break; + case TextureFormat.D3DFMT_ATI1: format = SharpDX.DXGI.Format.BC4_UNorm; break; + case TextureFormat.D3DFMT_ATI2: format = SharpDX.DXGI.Format.BC5_UNorm; break; + case TextureFormat.D3DFMT_BC7: format = SharpDX.DXGI.Format.BC7_UNorm; break; + + // uncompressed + case TextureFormat.D3DFMT_A1R5G5B5: format = SharpDX.DXGI.Format.B5G5R5A1_UNorm; break; + case TextureFormat.D3DFMT_A8: format = SharpDX.DXGI.Format.A8_UNorm; break; + case TextureFormat.D3DFMT_A8B8G8R8: format = SharpDX.DXGI.Format.R8G8B8A8_UNorm; break; + case TextureFormat.D3DFMT_L8: format = SharpDX.DXGI.Format.R8_UNorm; break; + case TextureFormat.D3DFMT_A8R8G8B8: format = SharpDX.DXGI.Format.B8G8R8A8_UNorm; break; + } + return format; + } + + public static int ByteSize(TextureFormat fmt) + { + switch (fmt) + { + // compressed + case TextureFormat.D3DFMT_DXT1: return 4;// BC1_UNorm + case TextureFormat.D3DFMT_DXT3: return 8;// BC2_UNorm + case TextureFormat.D3DFMT_DXT5: return 8;// BC3_UNorm + case TextureFormat.D3DFMT_ATI1: return 4;// BC4_UNorm + case TextureFormat.D3DFMT_ATI2: return 8;// BC5_UNorm + case TextureFormat.D3DFMT_BC7: return 8;// BC7_UNorm + + // uncompressed + case TextureFormat.D3DFMT_A1R5G5B5: return 16;// B5G5R5A1_UNorm + case TextureFormat.D3DFMT_A8: return 8;// A8_UNorm + case TextureFormat.D3DFMT_A8B8G8R8: return 32;// R8G8B8A8_UNorm + case TextureFormat.D3DFMT_L8: return 8;// R8_UNorm + case TextureFormat.D3DFMT_A8R8G8B8: return 32;// B8G8R8A8_UNorm + + default: return 0; + } + } + + + public static void ComputePitch(Format fmt, int width, int height, out int rowPitch, out int slicePitch, uint flags) + { + int nbw, nbh; + switch (fmt) + { + case Format.BC1_Typeless: + case Format.BC1_UNorm: + case Format.BC1_UNorm_SRgb: + case Format.BC4_Typeless: + case Format.BC4_UNorm: + case Format.BC4_SNorm: + nbw = Math.Max(1, (width + 3) / 4); + nbh = Math.Max(1, (height + 3) / 4); + rowPitch = nbw * 8; + slicePitch = rowPitch * nbh; + break; + case Format.BC2_Typeless: + case Format.BC2_UNorm: + case Format.BC2_UNorm_SRgb: + case Format.BC3_Typeless: + case Format.BC3_UNorm: + case Format.BC3_UNorm_SRgb: + case Format.BC5_Typeless: + case Format.BC5_UNorm: + case Format.BC5_SNorm: + case Format.BC6H_Typeless: + case Format.BC6H_Uf16: + case Format.BC6H_Sf16: + case Format.BC7_Typeless: + case Format.BC7_UNorm: + case Format.BC7_UNorm_SRgb: + nbw = Math.Max(1, (width + 3) / 4); + nbh = Math.Max(1, (height + 3) / 4); + rowPitch = nbw * 16; + slicePitch = rowPitch * nbh; + break; + + case Format.R8G8_B8G8_UNorm: + case Format.G8R8_G8B8_UNorm: + case Format.YUY2: + rowPitch = ((width + 1) >> 1) * 4; + slicePitch = rowPitch * height; + break; + + case Format.Y210: + case Format.Y216: + rowPitch = ((width + 1) >> 1) * 8; + slicePitch = rowPitch * height; + break; + + case Format.NV12: + case Format.Opaque420: + rowPitch = ((width + 1) >> 1) * 2; + slicePitch = rowPitch * (height + ((height + 1) >> 1)); + break; + + case Format.P010: + case Format.P016: + //case Format.XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + //case Format.XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + //case Format.XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + rowPitch = ((width + 1) >> 1) * 4; + slicePitch = rowPitch * (height + ((height + 1) >> 1)); + break; + + case Format.NV11: + rowPitch = ((width + 3) >> 2) * 4; + slicePitch = rowPitch * height * 2; + break; + + //case Format.WIN10_DXGI_FORMAT_P208: + // rowPitch = ((width + 1) >> 1) * 2; + // slicePitch = rowPitch * height * 2; + // break; + + //case Format.WIN10_DXGI_FORMAT_V208: + // rowPitch = width; + // slicePitch = rowPitch * (height + (((height + 1) >> 1) * 2)); + // break; + + //case Format.WIN10_DXGI_FORMAT_V408: + // rowPitch = width; + // slicePitch = rowPitch * (height + ((height >> 1) * 4)); + // break; + + default: + int bpp = FormatHelper.SizeOfInBytes(fmt) * 8; + // Default byte alignment + rowPitch = (width * bpp + 7) / 8; + slicePitch = rowPitch * height; + break; + } + } + + } + +} diff --git a/GameFiles/Resources/VehicleRecord.cs b/GameFiles/Resources/VehicleRecord.cs new file mode 100644 index 0000000..6bdcdbf --- /dev/null +++ b/GameFiles/Resources/VehicleRecord.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + public class VehicleRecordList : ResourceFileBase + { + public override long BlockLength => 0x20; + + public ResourceSimpleList64 Entries; + + public VehicleRecordList() + { + this.Entries = new ResourceSimpleList64(); + } + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + this.Entries = reader.ReadBlock>(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + writer.WriteBlock(this.Entries); + } + + public override Tuple[] GetParts() + { + return new Tuple[] { + new Tuple(16, Entries) + }; + } + } + + + public class VehicleRecordEntry : ResourceSystemBlock + { + // this looks exactly like an rrr entry: + // -> http://www.gtamodding.com/wiki/Carrec + + public override long BlockLength => 0x20; + + // structure data + public uint Time; + public short VelocityX; + public short VelocityY; + public short VelocityZ; + public sbyte RightX; + public sbyte RightY; + public sbyte RightZ; + public sbyte TopX; + public sbyte TopY; + public sbyte TopZ; + public byte SteeringAngle; + public byte GasPedalPower; + public byte BrakePedalPower; + public byte HandbrakeUsed; + public float PositionX; + public float PositionY; + public float PositionZ; + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.Time = reader.ReadUInt32(); + this.VelocityX = reader.ReadInt16(); + this.VelocityY = reader.ReadInt16(); + this.VelocityZ = reader.ReadInt16(); + this.RightX = (sbyte)reader.ReadByte(); + this.RightY = (sbyte)reader.ReadByte(); + this.RightZ = (sbyte)reader.ReadByte(); + this.TopX = (sbyte)reader.ReadByte(); + this.TopY = (sbyte)reader.ReadByte(); + this.TopZ = (sbyte)reader.ReadByte(); + this.SteeringAngle = reader.ReadByte(); + this.GasPedalPower = reader.ReadByte(); + this.BrakePedalPower = reader.ReadByte(); + this.HandbrakeUsed = reader.ReadByte(); + this.PositionX = reader.ReadSingle(); + this.PositionY = reader.ReadSingle(); + this.PositionZ = reader.ReadSingle(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.Time); + writer.Write(this.VelocityX); + writer.Write(this.VelocityY); + writer.Write(this.VelocityZ); + writer.Write(this.RightX); + writer.Write(this.RightY); + writer.Write(this.RightZ); + writer.Write(this.TopX); + writer.Write(this.TopY); + writer.Write(this.TopZ); + writer.Write(this.SteeringAngle); + writer.Write(this.GasPedalPower); + writer.Write(this.BrakePedalPower); + writer.Write(this.HandbrakeUsed); + writer.Write(this.PositionX); + writer.Write(this.PositionY); + writer.Write(this.PositionZ); + } + } + + +} diff --git a/GameFiles/Resources/VertexTypes.cs b/GameFiles/Resources/VertexTypes.cs new file mode 100644 index 0000000..df736fc --- /dev/null +++ b/GameFiles/Resources/VertexTypes.cs @@ -0,0 +1,1460 @@ +using SharpDX; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + + public enum VertexType : uint + { + Default = 89, //PNCT + DefaultEx = 16473, //PNCTX + PNCCT = 121, + PNCCTTTT = 1017, + PCCNCCTTX = 16639, + PCCNCCT = 127, + PNCTTTX = 16857, + PNCTTX = 16601, + PNCTTTX_2 = 19545, + PNCTTTX_3 = 17113, + PNCCTTX = 16633, + PNCCTTX_2 = 17017, + PNCCTTTX = 17145, + PCCNCCTX = 16511, + PCCNCTX = 16479, + PCCNCT = 95, + PNCCTT = 249, + PNCCTX = 16505, + PCT = 81, + PT = 65, + PTT = 193, + PNC = 25, + PC = 17, + PCC = 7, + PCCH2H4 = 2147500121, //0x80004059 (16473 + 0x80000000) DefaultEx Cloth? + PNCH2 = 2147483737, //0x80000059 (89 + 0x80000000) Default Cloth? + PNCTTTTX = 19673, //normal_spec_detail_dpm_vertdecal_tnt + PNCTTTT = 985, + PCCNCCTT = 255, + PCTT = 209, + PCCCCT = 119, + PCCNC = 31, + PCCNCTT = 223, + PCCNCTTX = 16607, + PCCNCTTT = 479, + PNCTT = 217, + PNCTTT = 473, + } + + + + public struct VertexTypeDefault //id: 84500486, stride: 36, flags: 89, refs: 76099 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + }; + } + } + + public struct VertexTypeDefaultEx //id: 168386566, stride: 52, flags: 16473, refs: 32337 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord; + public Vector4 Tangent; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 36, 0), + }; + } + } + + public struct VertexTypePNCCT //id: 93937670, stride: 40, flags: 121, refs: 31413 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour0; + public uint Colour1; + public Vector2 Texcoord; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 28, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0), + }; + } + } + + public struct VertexTypePNCCTTTT //id: 1436115100, stride: 64, flags: 1017, refs: 28673 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour0; + public uint Colour1; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + public Vector2 Texcoord3; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 28, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 40, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 48, 0), + new InputElement("TEXCOORD", 3, Format.R32G32_Float, 56, 0), + }; + } + } + + public struct VertexTypePCCNCCTTX //id: 1520003478, stride: 72, flags: 16639, refs: 11178 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public uint Colour3; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector4 Tangents; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("COLOR", 3, Format.R8G8B8A8_UNorm, 36, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 40, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 48, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 56, 0), + }; + } + } + + public struct VertexTypePCCNCCT //id: 93940118, stride: 48, flags: 127, refs: 10396 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public uint Colour3; + public Vector2 Texcoord; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("COLOR", 3, Format.R8G8B8A8_UNorm, 36, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 40, 0), + }; + } + } + + public struct VertexTypePNCTTTX //id: 1510563852, stride: 68, flags: 16857, refs: 3688 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + public Vector4 Tangents; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 44, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 52, 0), + }; + } + } + + public struct VertexTypePNCTTTX_2 //id: 168413446, stride: 68, flags: 19545, refs: 72 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + public Vector4 Tangents; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 44, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 52, 0), + }; + } + } + + public struct VertexTypePNCTTTX_3 //id: 1510563990, stride: 68, flags: 17113, refs: 43 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + public Vector4 Tangents; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 44, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 52, 0), + }; + } + } + + public struct VertexTypePNCTTX //id: 1510563846, stride: 60, flags: 16601, refs: 2712 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector4 Tangents; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 36, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 44, 0), + }; + } + } + + public struct VertexTypePNCCTTX //id: 1520001030, stride: 64, flags: 16633, refs: 2635 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour0; + public uint Colour1; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector4 Tangents; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 28, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 40, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 48, 0), + }; + } + } + + public struct VertexTypePNCCTTTX //id: 1520001174, stride: 72, flags: 17145, refs: 2238 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour0; + public uint Colour1; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + public Vector4 Tangents; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 28, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 40, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 48, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 56, 0), + }; + } + } + + public struct VertexTypePCCNCCTX //id: 177826198, stride: 64, flags: 16511, refs: 1990 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public uint Colour3; + public Vector2 Texcoord; + public Vector4 Tangent; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("COLOR", 3, Format.R8G8B8A8_UNorm, 36, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 40, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 48, 0), + }; + } + } + + public struct VertexTypePNCCTTX_2 //id: 177823894, stride: 64, flags: 17017, refs: 1800 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour0; + public uint Colour1; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector4 Tangent; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 28, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 40, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 48, 0), + }; + } + } + + public struct VertexTypePCCNCTX //id: 168389014, stride: 60, flags: 16479, refs: 1736 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public Vector2 Texcoord; + public Vector4 Tangent; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 36, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 44, 0), + }; + } + } + + public struct VertexTypePNCCTT //id: 1436114950, stride: 48, flags: 249, refs: 1704 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour0; + public uint Colour1; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 28, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 40, 0), + }; + } + } + + public struct VertexTypePNCCTX //id: 177823750, stride: 56, flags: 16505, refs: 1338 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour0; + public uint Colour1; + public Vector2 Texcoord; + public Vector4 Tangent; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 28, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 40, 0), + }; + } + } + + public struct VertexTypePCT //id: 84475910, stride: 24, flags: 81, refs: 102 + { + public Vector3 Position; + public uint Colour; + public Vector2 Texcoord; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0), + }; + } + } + + public struct VertexTypePT //id: 83886086, stride: 20, flags: 65, refs: 159 //water pools seem to use this + { + public Vector3 Position; + public Vector2 Texcoord; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 12, 0), + }; + } + } + + public struct VertexTypePTT //id: 1426063366, stride: 28, flags: 193, refs: 1 (skydome) + { + public Vector3 Position; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 12, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 20, 0), + }; + } + } + + public struct VertexTypePNC //id: 614406, stride: 28, flags: 25, refs: 380 // tunnel shadow casters seem use this + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + }; + } + } + + public struct VertexTypePCCNCT //id: 84502934, stride: 44, flags: 95, refs: 806 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public Vector2 Texcoord; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 36, 0), + }; + } + } + + public struct VertexTypePC //id: 589830, stride: 16, flags: 17, refs: 405 + { + public Vector3 Position; + public uint Colour; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + }; + } + } + + public struct VertexTypePCC //id: 2454, stride: 20, flags: 7, refs: 242 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + }; + } + } + + public struct VertexTypePNCTTTT //id: 1426677916, stride: 60, flags: 985, refs: 150 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + public Vector2 Texcoord3; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 44, 0), + new InputElement("TEXCOORD", 3, Format.R32G32_Float, 52, 0), + }; + } + } + + public struct VertexTypePCCNCCTT //id: 1436117398, stride: 56, flags: 255, refs: 99 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public uint Colour3; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("COLOR", 3, Format.R8G8B8A8_UNorm, 36, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 40, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 48, 0), + }; + } + } + + public struct VertexTypePCTT //id: 1426653190, stride: 32, flags: 209, refs: 79 + { + public Vector3 Position; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 24, 0), + }; + } + } + + public struct VertexTypePNCTTTTX //id: 1510590726, stride: 76, flags: 19673, refs: 3 //beach graffiti trees - normal_spec_detail_dpm_vertdecal_tnt.sps + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + public Vector2 Texcoord3; + public Vector4 Tangent; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 44, 0), + new InputElement("TEXCOORD", 3, Format.R32G32_Float, 52, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 60, 0), + }; + } + } + + public struct VertexTypePCCCCT //id: 93915542, stride: 36, flags: 119, refs: 2 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public uint Colour2; + public uint Colour3; + public Vector2 Texcoord; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 20, 0), + new InputElement("COLOR", 3, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + }; + } + } + + public struct VertexTypePCCNC //id: 616854, stride: 36, flags: 31, refs: 1 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + }; + } + } + + + + + public struct VertexTypePCCH2H4 //id: 34185222, stride: 32, flags: 16473, types: 216172782140628998, refs: 2191 (yft only) - frag cloth normalmapped + { + public Vector3 Position; + public uint NormalPacked;// Vector3 Normal; + public uint Colour; + public ushort TexcoordX;// Vector2 Texcoord; + public ushort TexcoordY; + public ushort TangentX; // Vector4 Tangent; + public ushort TangentY; + public ushort TangentZ; + public ushort TangentW; + + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R8G8B8A8_SNorm, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("TEXCOORD", 0, Format.R16G16_Float, 20, 0), + new InputElement("TANGENT", 0, Format.R16G16B16A16_Float, 24, 0), + }; + } + } + + public struct VertexTypePNCH2 //id: 17391622, stride: 32, flags: 89, types: 216172782140612614, refs: 1174 (yft only) - frag cloth default + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public ushort TexcoordX;// Vector2 Texcoord; + public ushort TexcoordY; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R16G16_Float, 28, 0), + }; + } + } + + + + public struct VertexTypePCCNCTT //id: 1426680214, stride: 52, flags: 223, types: 8598872888530528662, refs: 1470 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 44, 0), + }; + } + } + + public struct VertexTypePCCNCTTX //id: 1510566294, stride: 68, flags: 16607, types: 8598872888530528662, refs: 1478 (+9) + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector4 Tangent; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 44, 0), + new InputElement("TANGENT", 0, Format.R32G32B32A32_Float, 52, 0), + }; + } + } + + public struct VertexTypePCCNCTTT //id: 1426680220, stride: 60, flags: 479, types: 8598872888530528662, refs: 1290 + { + public Vector3 Position; + public uint Colour0; + public uint Colour1; + public Vector3 Normal; + public uint Colour2; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 12, 0), + new InputElement("COLOR", 1, Format.R8G8B8A8_UNorm, 16, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 20, 0), + new InputElement("COLOR", 2, Format.R8G8B8A8_UNorm, 32, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 44, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 52, 0), + }; + } + } + + public struct VertexTypePNCTT //id: 1426677766, stride: 44, flags: 217, types: 8598872888530528662, refs: 4434 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 36, 0), + }; + } + } + + public struct VertexTypePNCTTT //id: 1426677772, stride: 52, flags: 473, types: 8598872888530528662, refs: 65 + { + public Vector3 Position; + public Vector3 Normal; + public uint Colour; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + + public static InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0), + new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 24, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0), + new InputElement("TEXCOORD", 1, Format.R32G32_Float, 36, 0), + new InputElement("TEXCOORD", 2, Format.R32G32_Float, 44, 0), + }; + } + } + + + + + + + + + + + + + + + + /* + + //full types output from all ydr/ydd files + + + public struct VertexType89 //id: 84500486, stride: 36, flags: 89, types: 8598872888530528662, refs: 76099 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + } + + public struct VertexType121 //id: 93937670, stride: 40, flags: 121, types: 8598872888530528662, refs: 31413 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + } + + public struct VertexType193 //id: 1426063366, stride: 28, flags: 193, types: 8598872888530528662, refs: 1 + { + public Vector3 Component1; + public Vector2 Component2; + public Vector2 Component3; + } + + public struct VertexType16473 //id: 168386566, stride: 52, flags: 16473, types: 8598872888530528662, refs: 32337 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector4 Component5; + } + + public struct VertexType209 //id: 1426653190, stride: 32, flags: 209, types: 8598872888530528662, refs: 79 + { + public Vector3 Component1; + public uint Component2; + public Vector2 Component3; + public Vector2 Component4; + } + + public struct VertexType95 //id: 84502934, stride: 44, flags: 95, types: 8598872888530528662, refs: 806 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public Vector2 Component6; + } + + public struct VertexType17145 //id: 1520001174, stride: 72, flags: 17145, types: 8598872888530528662, refs: 2238 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector2 Component7; + public Vector4 Component8; + } + + public struct VertexType16601 //id: 1510563846, stride: 60, flags: 16601, types: 8598872888530528662, refs: 2712 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector4 Component6; + } + + public struct VertexType249 //id: 1436114950, stride: 48, flags: 249, types: 8598872888530528662, refs: 1704 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + public Vector2 Component6; + } + + public struct VertexType16857 //id: 1510563852, stride: 68, flags: 16857, types: 8598872888530528662, refs: 3688 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType17017 //id: 177823894, stride: 64, flags: 17017, types: 8598872888530528662, refs: 1800 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType16505 //id: 177823750, stride: 56, flags: 16505, types: 8598872888530528662, refs: 1338 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + public Vector4 Component6; + } + + public struct VertexType16633 //id: 1520001030, stride: 64, flags: 16633, types: 8598872888530528662, refs: 2635 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType16479 //id: 168389014, stride: 60, flags: 16479, types: 8598872888530528662, refs: 1736 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType16511 //id: 177826198, stride: 64, flags: 16511, types: 8598872888530528662, refs: 1990 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public uint Component6; + public Vector2 Component7; + public Vector4 Component8; + } + + public struct VertexType119 //id: 93915542, stride: 36, flags: 119, types: 8598872888530528662, refs: 2 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public uint Component4; + public uint Component5; + public Vector2 Component6; + } + + public struct VertexType16607 //id: 1510566294, stride: 68, flags: 16607, types: 8598872888530528662, refs: 9 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public Vector2 Component6; + public Vector2 Component7; + public Vector4 Component8; + } + + public struct VertexType25 //id: 614406, stride: 28, flags: 25, types: 8598872888530528662, refs: 380 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + } + + public struct VertexType81 //id: 84475910, stride: 24, flags: 81, types: 8598872888530528662, refs: 102 + { + public Vector3 Component1; + public uint Component2; + public Vector2 Component3; + } + + public struct VertexType19545 //id: 168413446, stride: 68, flags: 19545, types: 8598872888530528662, refs: 72 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType19673 //id: 1510590726, stride: 76, flags: 19673, types: 8598872888530528662, refs: 3 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector2 Component7; + public Vector4 Component8; + } + + public struct VertexType17 //id: 589830, stride: 16, flags: 17, types: 8598872888530528662, refs: 405 + { + public Vector3 Component1; + public uint Component2; + } + + public struct VertexType16639 //id: 1520003478, stride: 72, flags: 16639, types: 8598872888530528662, refs: 11178 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public uint Component6; + public Vector2 Component7; + public Vector2 Component8; + public Vector4 Component9; + } + + public struct VertexType127 //id: 93940118, stride: 48, flags: 127, types: 8598872888530528662, refs: 10396 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public uint Component6; + public Vector2 Component7; + } + + public struct VertexType65 //id: 83886086, stride: 20, flags: 65, types: 8598872888530528662, refs: 159 + { + public Vector3 Component1; + public Vector2 Component2; + } + + public struct VertexType1017 //id: 1436115100, stride: 64, flags: 1017, types: 8598872888530528662, refs: 28673 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector2 Component7; + public Vector2 Component8; + } + + public struct VertexType985 //id: 1426677916, stride: 60, flags: 985, types: 8598872888530528662, refs: 150 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector2 Component7; + } + + public struct VertexType17113 //id: 1510563990, stride: 68, flags: 17113, types: 8598872888530528662, refs: 43 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType255 //id: 1436117398, stride: 56, flags: 255, types: 8598872888530528662, refs: 99 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public uint Component6; + public Vector2 Component7; + public Vector2 Component8; + } + + public struct VertexType7 //id: 2454, stride: 20, flags: 7, types: 8598872888530528662, refs: 242 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + } + + public struct VertexType31 //id: 616854, stride: 36, flags: 31, types: 8598872888530528662, refs: 1 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + } + + + + + */ + + + + + + + + + /* + + + //full types output from all yft files + + public struct VertexType16639 //id: 1520003478, stride: 72, flags: 16639, types: 8598872888530528662, refs: 6 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public uint Component6; + public Vector2 Component7; + public Vector2 Component8; + public Vector4 Component9; + } + + public struct VertexType89 //id: 84500486, stride: 36, flags: 89, types: 8598872888530528662, refs: 2705 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + } + + public struct VertexType95 //id: 84502934, stride: 44, flags: 95, types: 8598872888530528662, refs: 2662 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public Vector2 Component6; + } + + public struct VertexType16473 //id: 34185222, stride: 32, flags: 16473, types: 216172782140628998, refs: 2191 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public ushort2 Component4; + public ushort4 Component5; + } + + public struct VertexType16473 //id: 168386566, stride: 52, flags: 16473, types: 8598872888530528662, refs: 2540 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector4 Component5; + } + + public struct VertexType16601 //id: 1510563846, stride: 60, flags: 16601, types: 8598872888530528662, refs: 6422 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector4 Component6; + } + + public struct VertexType16479 //id: 168389014, stride: 60, flags: 16479, types: 8598872888530528662, refs: 1749 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType89 //id: 17391622, stride: 32, flags: 89, types: 216172782140612614, refs: 1174 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public ushort2 Component4; + } + + public struct VertexType127 //id: 93940118, stride: 48, flags: 127, types: 8598872888530528662, refs: 1 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public uint Component6; + public Vector2 Component7; + } + + public struct VertexType121 //id: 93937670, stride: 40, flags: 121, types: 8598872888530528662, refs: 14 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + } + + public struct VertexType16633 //id: 1520001030, stride: 64, flags: 16633, types: 8598872888530528662, refs: 1 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType16505 //id: 177823750, stride: 56, flags: 16505, types: 8598872888530528662, refs: 26 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public uint Component4; + public Vector2 Component5; + public Vector4 Component6; + } + + public struct VertexType223 //id: 1426680214, stride: 52, flags: 223, types: 8598872888530528662, refs: 1470 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public Vector2 Component6; + public Vector2 Component7; + } + + public struct VertexType16607 //id: 1510566294, stride: 68, flags: 16607, types: 8598872888530528662, refs: 1478 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public Vector2 Component6; + public Vector2 Component7; + public Vector4 Component8; + } + + public struct VertexType479 //id: 1426680220, stride: 60, flags: 479, types: 8598872888530528662, refs: 1290 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public Vector2 Component6; + public Vector2 Component7; + public Vector2 Component8; + } + + public struct VertexType16511 //id: 177826198, stride: 64, flags: 16511, types: 8598872888530528662, refs: 1 + { + public Vector3 Component1; + public uint Component2; + public uint Component3; + public Vector3 Component4; + public uint Component5; + public uint Component6; + public Vector2 Component7; + public Vector4 Component8; + } + + public struct VertexType25 //id: 614406, stride: 28, flags: 25, types: 8598872888530528662, refs: 8 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + } + + public struct VertexType16857 //id: 1510563852, stride: 68, flags: 16857, types: 8598872888530528662, refs: 5 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector2 Component6; + public Vector4 Component7; + } + + public struct VertexType217 //id: 1426677766, stride: 44, flags: 217, types: 8598872888530528662, refs: 4434 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + } + + public struct VertexType473 //id: 1426677772, stride: 52, flags: 473, types: 8598872888530528662, refs: 65 + { + public Vector3 Component1; + public Vector3 Component2; + public uint Component3; + public Vector2 Component4; + public Vector2 Component5; + public Vector2 Component6; + } + + + */ + + + + +} diff --git a/GameFiles/Resources/WaypointRecord.cs b/GameFiles/Resources/WaypointRecord.cs new file mode 100644 index 0000000..66af7db --- /dev/null +++ b/GameFiles/Resources/WaypointRecord.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + public class WaypointRecordList : ResourceFileBase + { + public override long BlockLength => 0x30; + + public uint Unknown_10h; // 0x00000000 + public uint Unknown_14h; // 0x00000000 + public ulong EntriesPointer; + public uint EntriesCount; + public uint Unknown_24h; // 0x00000000 + public uint Unknown_28h; // 0x00000000 + public uint Unknown_2Ch; // 0x00000000 + + public ResourceSimpleArray Entries; + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + base.Read(reader, parameters); + + this.Unknown_10h = reader.ReadUInt32(); + this.Unknown_14h = reader.ReadUInt32(); + this.EntriesPointer = reader.ReadUInt64(); + this.EntriesCount = reader.ReadUInt32(); + this.Unknown_24h = reader.ReadUInt32(); + this.Unknown_28h = reader.ReadUInt32(); + this.Unknown_2Ch = reader.ReadUInt32(); + + this.Entries = reader.ReadBlockAt>( + this.EntriesPointer, // offset + this.EntriesCount + ); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + base.Write(writer, parameters); + + //// update structure data + //this.EntriesPointer = (ulong)(this.Entries?.Position ?? 0); + //this.EntriesCount = (uint)(this.Entries?.Count ?? 0); + + // write structure data + writer.Write(this.Unknown_10h); + writer.Write(this.Unknown_14h); + writer.Write(this.EntriesPointer); + writer.Write(this.EntriesCount); + writer.Write(this.Unknown_24h); + writer.Write(this.Unknown_28h); + writer.Write(this.Unknown_2Ch); + } + + public override IResourceBlock[] GetReferences() + { + var list = new List(base.GetReferences()); + if (Entries != null) list.Add(Entries); + return list.ToArray(); + } + } + + + public class WaypointRecordEntry : ResourceSystemBlock + { + public override long BlockLength => 20; + + public float PositionX; + public float PositionY; + public float PositionZ; + public ushort Unk0; + public ushort Unk1; + public ushort Unk2; + public ushort Unk3; + + public override void Read(ResourceDataReader reader, params object[] parameters) + { + // read structure data + this.PositionX = reader.ReadSingle(); + this.PositionY = reader.ReadSingle(); + this.PositionZ = reader.ReadSingle(); + this.Unk0 = reader.ReadUInt16(); + this.Unk1 = reader.ReadUInt16(); + this.Unk2 = reader.ReadUInt16(); + this.Unk3 = reader.ReadUInt16(); + } + + public override void Write(ResourceDataWriter writer, params object[] parameters) + { + // write structure data + writer.Write(this.PositionX); + writer.Write(this.PositionY); + writer.Write(this.PositionZ); + writer.Write(this.Unk0); + writer.Write(this.Unk1); + writer.Write(this.Unk2); + writer.Write(this.Unk3); + } + } + + +} diff --git a/GameFiles/Utils/GTACrypto.cs b/GameFiles/Utils/GTACrypto.cs new file mode 100644 index 0000000..fce4e1d --- /dev/null +++ b/GameFiles/Utils/GTACrypto.cs @@ -0,0 +1,251 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//shamelessly stolen + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public class GTACrypto + { + + + public static byte[] DecryptAES(byte[] data) + { + return DecryptAESData(data, GTA5Keys.PC_AES_KEY); + } + + public static byte[] DecryptAESData(byte[] data, byte[] key, int rounds = 1) + { + var rijndael = Rijndael.Create(); + rijndael.KeySize = 256; + rijndael.Key = key; + rijndael.BlockSize = 128; + rijndael.Mode = CipherMode.ECB; + rijndael.Padding = PaddingMode.None; + + var buffer = (byte[])data.Clone(); + var length = data.Length - data.Length % 16; + + // decrypt... + if (length > 0) + { + var decryptor = rijndael.CreateDecryptor(); + for (var roundIndex = 0; roundIndex < rounds; roundIndex++) + decryptor.TransformBlock(buffer, 0, length, buffer, 0); + } + + return buffer; + } + public static byte[] EncryptAESData(byte[] data, byte[] key, int rounds = 1) + { + var rijndael = Rijndael.Create(); + rijndael.KeySize = 256; + rijndael.Key = key; + rijndael.BlockSize = 128; + rijndael.Mode = CipherMode.ECB; + rijndael.Padding = PaddingMode.None; + + var buffer = (byte[])data.Clone(); + var length = data.Length - data.Length % 16; + + // encrypt... + if (length > 0) + { + var encryptor = rijndael.CreateEncryptor(); + for (var roundIndex = 0; roundIndex < rounds; roundIndex++) + encryptor.TransformBlock(buffer, 0, length, buffer, 0); + } + + return buffer; + } + + + + + + public static byte[] GetNGKey(string name, uint length) + { + uint hash = GTA5Hash.CalculateHash(name); + uint keyidx = (hash + length + (101 - 40)) % 0x65; + return GTA5Keys.PC_NG_KEYS[keyidx]; + } + + + public static byte[] DecryptNG(byte[] data, string name, uint length) + { + byte[] key = GetNGKey(name, length); + return DecryptNG(data, key); + } + + public static byte[] DecryptNG(byte[] data, byte[] key) + { + var decryptedData = new byte[data.Length]; + + var keyuints = new uint[key.Length / 4]; + Buffer.BlockCopy(key, 0, keyuints, 0, key.Length); + + for (int blockIndex = 0; blockIndex < data.Length / 16; blockIndex++) + { + var encryptedBlock = new byte[16]; + Array.Copy(data, 16 * blockIndex, encryptedBlock, 0, 16); + var decryptedBlock = DecryptNGBlock(encryptedBlock, keyuints); + Array.Copy(decryptedBlock, 0, decryptedData, 16 * blockIndex, 16); + } + + if (data.Length % 16 != 0) + { + var left = data.Length % 16; + Buffer.BlockCopy(data, data.Length - left, decryptedData, data.Length - left, left); + } + + return decryptedData; + } + + public static byte[] DecryptNGBlock(byte[] data, uint[] key) + { + var buffer = data; + + // prepare key... + var subKeys = new uint[17][]; + for (int i = 0; i < 17; i++) + { + subKeys[i] = new uint[4]; + subKeys[i][0] = key[4 * i + 0]; + subKeys[i][1] = key[4 * i + 1]; + subKeys[i][2] = key[4 * i + 2]; + subKeys[i][3] = key[4 * i + 3]; + } + + buffer = DecryptNGRoundA(buffer, subKeys[0], GTA5Keys.PC_NG_DECRYPT_TABLES[0]); + buffer = DecryptNGRoundA(buffer, subKeys[1], GTA5Keys.PC_NG_DECRYPT_TABLES[1]); + for (int k = 2; k <= 15; k++) + buffer = DecryptNGRoundB(buffer, subKeys[k], GTA5Keys.PC_NG_DECRYPT_TABLES[k]); + buffer = DecryptNGRoundA(buffer, subKeys[16], GTA5Keys.PC_NG_DECRYPT_TABLES[16]); + + return buffer; + } + + + // round 1,2,16 + public static byte[] DecryptNGRoundA(byte[] data, uint[] key, uint[][] table) + { + var x1 = + table[0][data[0]] ^ + table[1][data[1]] ^ + table[2][data[2]] ^ + table[3][data[3]] ^ + key[0]; + var x2 = + table[4][data[4]] ^ + table[5][data[5]] ^ + table[6][data[6]] ^ + table[7][data[7]] ^ + key[1]; + var x3 = + table[8][data[8]] ^ + table[9][data[9]] ^ + table[10][data[10]] ^ + table[11][data[11]] ^ + key[2]; + var x4 = + table[12][data[12]] ^ + table[13][data[13]] ^ + table[14][data[14]] ^ + table[15][data[15]] ^ + key[3]; + + var result = new byte[16]; + Array.Copy(BitConverter.GetBytes(x1), 0, result, 0, 4); + Array.Copy(BitConverter.GetBytes(x2), 0, result, 4, 4); + Array.Copy(BitConverter.GetBytes(x3), 0, result, 8, 4); + Array.Copy(BitConverter.GetBytes(x4), 0, result, 12, 4); + return result; + } + + + + // round 3-15 + public static byte[] DecryptNGRoundB(byte[] data, uint[] key, uint[][] table) + { + var x1 = + table[0][data[0]] ^ + table[7][data[7]] ^ + table[10][data[10]] ^ + table[13][data[13]] ^ + key[0]; + var x2 = + table[1][data[1]] ^ + table[4][data[4]] ^ + table[11][data[11]] ^ + table[14][data[14]] ^ + key[1]; + var x3 = + table[2][data[2]] ^ + table[5][data[5]] ^ + table[8][data[8]] ^ + table[15][data[15]] ^ + key[2]; + var x4 = + table[3][data[3]] ^ + table[6][data[6]] ^ + table[9][data[9]] ^ + table[12][data[12]] ^ + key[3]; + + //var result = new byte[16]; + //Array.Copy(BitConverter.GetBytes(x1), 0, result, 0, 4); + //Array.Copy(BitConverter.GetBytes(x2), 0, result, 4, 4); + //Array.Copy(BitConverter.GetBytes(x3), 0, result, 8, 4); + //Array.Copy(BitConverter.GetBytes(x4), 0, result, 12, 4); + //return result; + + var result = new byte[16]; + result[0] = (byte)((x1 >> 0) & 0xFF); + result[1] = (byte)((x1 >> 8) & 0xFF); + result[2] = (byte)((x1 >> 16) & 0xFF); + result[3] = (byte)((x1 >> 24) & 0xFF); + result[4] = (byte)((x2 >> 0) & 0xFF); + result[5] = (byte)((x2 >> 8) & 0xFF); + result[6] = (byte)((x2 >> 16) & 0xFF); + result[7] = (byte)((x2 >> 24) & 0xFF); + result[8] = (byte)((x3 >> 0) & 0xFF); + result[9] = (byte)((x3 >> 8) & 0xFF); + result[10] = (byte)((x3 >> 16) & 0xFF); + result[11] = (byte)((x3 >> 24) & 0xFF); + result[12] = (byte)((x4 >> 0) & 0xFF); + result[13] = (byte)((x4 >> 8) & 0xFF); + result[14] = (byte)((x4 >> 16) & 0xFF); + result[15] = (byte)((x4 >> 24) & 0xFF); + return result; + } + + + + } +} diff --git a/GameFiles/Utils/GTAKeys.cs b/GameFiles/Utils/GTAKeys.cs new file mode 100644 index 0000000..f8cd655 --- /dev/null +++ b/GameFiles/Utils/GTAKeys.cs @@ -0,0 +1,1472 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* + This file contains only SHA1 hashes of all interesting values. There is NO key. +*/ + + +//shamelessly stolen + +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + public static class GTA5Keys + { + public static string ToS = "(c)2017"; + + // aes decryption/encryption key... + public static byte[] PC_AES_KEY; // 32 + + // ng decryption/encryption expanded keys... + public static byte[][] PC_NG_KEYS; // 101, 272 + + // ng decryption tables... + public static uint[][][] PC_NG_DECRYPT_TABLES; // 17, 16, 256 + + // ng encryption tables... + // -> some of these tables can be calculated from decryption tables + public static uint[][][] PC_NG_ENCRYPT_TABLES; // 17, 16, 256 + + // ng encryption look-up-tables + // -> some of these look-up-tables can be calculated from decryption tables + public static GTA5NGLUT[][] PC_NG_ENCRYPT_LUTs; // 17, 16 + + // hash lookup-table... + public static byte[] PC_LUT; // 256 + + + + public static void Generate(byte[] exeData, Action updateStatus) //Stream exeStr)// + { + var exeStr = new MemoryStream(exeData); + + updateStatus("Searching for AES key..."); + PC_AES_KEY = HashSearch.SearchHash(exeStr, GTA5KeyHashes.PC_AES_KEY_HASH, 0x20); + //updateStatus("aes key found"); + + updateStatus("Searching for NG keys..."); + PC_NG_KEYS = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_KEY_HASHES, 0x110); + //updateStatus("ng keys found"); + + updateStatus("Searching for NG decrypt tables..."); + var tabs = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_DECRYPT_TABLE_HASHES, 0x400); + //updateStatus("ng decrypt tables found"); + + updateStatus("Searching for NG hash lookup tables..."); + // 17 rounds + PC_NG_DECRYPT_TABLES = new uint[17][][]; + for (int i = 0; i < 17; i++) + { + // + PC_NG_DECRYPT_TABLES[i] = new uint[16][]; + for (int j = 0; j < 16; j++) + { + var buf = tabs[j + 16 * i]; + PC_NG_DECRYPT_TABLES[i][j] = new uint[256]; + Buffer.BlockCopy(buf, 0, PC_NG_DECRYPT_TABLES[i][j], 0, 1024); + } + } + + PC_LUT = HashSearch.SearchHash(exeStr, GTA5KeyHashes.PC_LUT_HASH, 0x100); + //updateStatus("ng hash LUTs found"); + + + + updateStatus("Calculating NG encryption tables..."); + PC_NG_ENCRYPT_TABLES = new uint[17][][]; + for (int i = 0; i < 17; i++) + { + PC_NG_ENCRYPT_TABLES[i] = new uint[16][]; + for (int j = 0; j < 16; j++) + { + PC_NG_ENCRYPT_TABLES[i][j] = new uint[256]; + for (int k = 0; k < 256; k++) + { + PC_NG_ENCRYPT_TABLES[i][j][k] = 0; + } + } + } + + PC_NG_ENCRYPT_LUTs = new GTA5NGLUT[17][]; + for (int i = 0; i < 17; i++) + { + PC_NG_ENCRYPT_LUTs[i] = new GTA5NGLUT[16]; + for (int j = 0; j < 16; j++) + PC_NG_ENCRYPT_LUTs[i][j] = new GTA5NGLUT(); + } + + + + + updateStatus("Calculating NG encryption tables (1/17)..."); + PC_NG_ENCRYPT_TABLES[0] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[0]); + //updateStatus("ng encrypt table 1 of 17 calculated"); + + updateStatus("Calculating NG encryption tables (2/17)..."); + PC_NG_ENCRYPT_TABLES[1] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[1]); + //updateStatus("ng encrypt table 2 of 17 calculated"); + + for (int k = 2; k <= 15; k++) + { + updateStatus("Calculating NG encryption tables (" + (k + 1).ToString() + "/17)..."); + PC_NG_ENCRYPT_LUTs[k] = LookUpTableGenerator.BuildLUTs2(PC_NG_DECRYPT_TABLES[k]); + //updateStatus("ng encrypt table " + (k + 1).ToString() + " of 17 calculated"); + } + + updateStatus("Calculating NG encryption tables (17/17)..."); + PC_NG_ENCRYPT_TABLES[16] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[16]); + //updateStatus("ng encrypt table 17 of 17 calculated"); + + updateStatus("Complete."); + } + + + public static void GenerateV2(byte[] exeData, Action updateStatus) + { + var exeStr = new MemoryStream(exeData); + + updateStatus?.Invoke("Searching for AES key..."); + PC_AES_KEY = HashSearch.SearchHash(exeStr, GTA5KeyHashes.PC_AES_KEY_HASH, 0x20); + + Settings.Default.Key = Convert.ToBase64String(PC_AES_KEY); + Settings.Default.Save(); + + updateStatus?.Invoke("Complete."); + } + + + + public static void LoadFromPath(string path = ".\\Keys") + { + //PC_AES_KEY = File.ReadAllBytes(path + "\\gtav_aes_key.dat"); + //PC_NG_KEYS = CryptoIO.ReadNgKeys(path + "\\gtav_ng_key.dat"); + //PC_NG_DECRYPT_TABLES = CryptoIO.ReadNgTables(path + "\\gtav_ng_decrypt_tables.dat"); + ////PC_NG_ENCRYPT_TABLES = CryptoIO.ReadNgTables(path + "\\gtav_ng_encrypt_tables.dat"); + ////PC_NG_ENCRYPT_LUTs = CryptoIO.ReadNgLuts(path + "\\gtav_ng_encrypt_luts.dat"); + //PC_LUT = File.ReadAllBytes(path + "\\gtav_hash_lut.dat"); + + //GenerateMagicData(path); + UseMagicData(path); + } + + public static void SaveToPath(string path = ".\\Keys") + { + File.WriteAllBytes(path + "\\gtav_aes_key.dat", PC_AES_KEY); + CryptoIO.WriteNgKeys(path + "\\gtav_ng_key.dat", PC_NG_KEYS); + CryptoIO.WriteNgTables(path + "\\gtav_ng_decrypt_tables.dat", PC_NG_DECRYPT_TABLES); + CryptoIO.WriteNgTables(path + "\\gtav_ng_encrypt_tables.dat", PC_NG_ENCRYPT_TABLES); + CryptoIO.WriteLuts(path + "\\gtav_ng_encrypt_luts.dat", PC_NG_ENCRYPT_LUTs); + File.WriteAllBytes(path + "\\gtav_hash_lut.dat", PC_LUT); + } + + + + + private static void GenerateMagicData(string path = ".\\Keys") + { + //byte[] b1 = File.ReadAllBytes(path + "\\gtav_aes_key.dat"); + byte[] b2 = File.ReadAllBytes(path + "\\gtav_ng_key.dat"); + byte[] b3 = File.ReadAllBytes(path + "\\gtav_ng_decrypt_tables.dat"); + byte[] b4 = File.ReadAllBytes(path + "\\gtav_hash_lut.dat"); + + int bl = b2.Length + b3.Length + b4.Length; //b1.Length + + byte[] b = new byte[bl]; + int bp = 0; + //Buffer.BlockCopy(b1, 0, b, bp, b1.Length); bp += b1.Length; // 32 + Buffer.BlockCopy(b2, 0, b, bp, b2.Length); bp += b2.Length; // 27472 + Buffer.BlockCopy(b3, 0, b, bp, b3.Length); bp += b3.Length; // 278528 + Buffer.BlockCopy(b4, 0, b, bp, b4.Length); bp += b4.Length; // 256 + + byte[] db = null; + using (MemoryStream dms = new MemoryStream()) + { + using (DeflateStream ds = new DeflateStream(dms, CompressionMode.Compress)) + { + ds.Write(b, 0, b.Length); + ds.Close(); + db = dms.ToArray(); + } + } + + if (db == null) + { + throw new Exception("Error deflating data."); + } + + db = GTACrypto.EncryptAESData(db, PC_AES_KEY); + + + //Random rnd = new Random((int)JenkHash.GenHash("Super secret seed")); + Random rnd = new Random((int)JenkHash.GenHash(PC_AES_KEY)); + int dbl = db.Length; + byte[] rb1 = new byte[dbl]; + byte[] rb2 = new byte[dbl]; + byte[] rb3 = new byte[dbl]; + byte[] rb4 = new byte[dbl]; + rnd.NextBytes(rb1); + rnd.NextBytes(rb2); + rnd.NextBytes(rb3); + rnd.NextBytes(rb4); + byte[] fb = new byte[dbl]; + for (int i = 0; i < dbl; i++) + { + fb[i] = (byte)((db[i] + rb1[i] + rb2[i] + rb3[i] + rb4[i]) & 0xFF); + } + + File.WriteAllBytes(path + "\\magic.dat", fb); + + } + + private static void UseMagicData(string path) + { + + if (string.IsNullOrEmpty(Settings.Default.Key)) + { + byte[] exedata = File.ReadAllBytes(path + "\\gta5.exe"); + GenerateV2(exedata, null); + } + else + { + PC_AES_KEY = Convert.FromBase64String(Settings.Default.Key); + } + //GenerateMagicData(); + + + //Random rnd = new Random((int)JenkHash.GenHash("Super secret seed")); + Random rnd = new Random((int)JenkHash.GenHash(PC_AES_KEY)); + byte[] m = Resources.magic; + int dbl = m.Length; + byte[] rb1 = new byte[dbl]; + byte[] rb2 = new byte[dbl]; + byte[] rb3 = new byte[dbl]; + byte[] rb4 = new byte[dbl]; + rnd.NextBytes(rb1); + rnd.NextBytes(rb2); + rnd.NextBytes(rb3); + rnd.NextBytes(rb4); + byte[] db = new byte[dbl]; + for (int i = 0; i < dbl; i++) + { + db[i] = (byte)((m[i] - rb1[i] - rb2[i] - rb3[i] - rb4[i]) & 0xFF); + } + + db = GTACrypto.DecryptAESData(db, PC_AES_KEY); + + byte[] b = null; + using (MemoryStream dms = new MemoryStream(db)) + { + using (DeflateStream ds = new DeflateStream(dms, CompressionMode.Decompress)) + { + using (MemoryStream outstr = new MemoryStream()) + { + ds.CopyTo(outstr); + b = outstr.GetBuffer(); + } + } + } + if (b == null) + { + throw new Exception("Error inflating magic data."); + } + + //byte[] b1 = new byte[32]; + byte[] b2 = new byte[27472]; + byte[] b3 = new byte[278528]; + byte[] b4 = new byte[256]; + int bp = 0; + //Buffer.BlockCopy(b, bp, b1, 0, b1.Length); bp += b1.Length; // 32 + Buffer.BlockCopy(b, bp, b2, 0, b2.Length); bp += b2.Length; // 27472 + Buffer.BlockCopy(b, bp, b3, 0, b3.Length); bp += b3.Length; // 278528 + Buffer.BlockCopy(b, bp, b4, 0, b4.Length); bp += b4.Length; // 256 + + //PC_AES_KEY = b1; + PC_NG_KEYS = CryptoIO.ReadNgKeys(b2); + PC_NG_DECRYPT_TABLES = CryptoIO.ReadNgTables(b3); + PC_LUT = b4; + } + + + } + + + + + public static class GTA5KeyHashes + { + // aes decryption/encryption key... + public static byte[] PC_AES_KEY_HASH = new byte[] { 0xA0, 0x79, 0x61, 0x28, 0xA7, 0x75, 0x72, 0x0A, 0xC2, 0x04, 0xD9, 0x81, 0x9F, 0x68, 0xC1, 0x72, 0xE3, 0x95, 0x2C, 0x6D }; + + // ng decryption/encryption expanded keys... + public static byte[][] PC_NG_KEY_HASHES = new byte[101][] { + new byte[] { 0xEB, 0x09, 0x15, 0x12, 0x03, 0x97, 0xCE, 0x2E, 0x17, 0x82, 0x8D, 0xD7, 0x7E, 0x32, 0x18, 0xD9, 0x77, 0xA1, 0x85, 0xF7 }, + new byte[] { 0xD7, 0x40, 0xB3, 0xC8, 0x9F, 0xE3, 0xA1, 0x9A, 0x92, 0x65, 0xDC, 0xEE, 0xFB, 0x45, 0x4C, 0x16, 0x2D, 0xB4, 0x53, 0x68 }, + new byte[] { 0x85, 0xF4, 0x3E, 0x5B, 0xAB, 0x4A, 0xBC, 0xAD, 0x76, 0xD8, 0x07, 0x15, 0xBB, 0x39, 0x32, 0xE9, 0xE7, 0xEC, 0xC5, 0xE2 }, + new byte[] { 0xB8, 0x6D, 0x64, 0x1E, 0x44, 0x17, 0xF3, 0xDD, 0xD8, 0x01, 0x98, 0x55, 0x14, 0xEF, 0x79, 0x73, 0x22, 0xF2, 0xD6, 0x57 }, + new byte[] { 0xE1, 0x27, 0xAE, 0xDB, 0x60, 0x43, 0x51, 0x31, 0xAB, 0x6D, 0x44, 0xF8, 0xBC, 0x02, 0x46, 0xB9, 0x52, 0x38, 0xB1, 0x0B }, + new byte[] { 0x15, 0xBE, 0x8F, 0x36, 0xB7, 0xE7, 0x26, 0xB3, 0x28, 0x7A, 0x77, 0x85, 0x88, 0x85, 0x94, 0x12, 0xEB, 0x0C, 0xAA, 0x66 }, + new byte[] { 0x28, 0x72, 0x6A, 0xEC, 0x3B, 0x14, 0x19, 0x7C, 0x0E, 0x54, 0x8B, 0xAA, 0x5C, 0x8D, 0xF5, 0x12, 0x84, 0x98, 0xC4, 0x75 }, + new byte[] { 0xAD, 0xDC, 0xB1, 0xBE, 0xF3, 0x98, 0x6E, 0x4A, 0x3A, 0x31, 0xF4, 0xED, 0xA4, 0xDB, 0xCE, 0xB6, 0x1A, 0x6C, 0x91, 0x47 }, + new byte[] { 0xB9, 0xD4, 0xF6, 0xA1, 0x19, 0x90, 0x66, 0x47, 0xD1, 0x85, 0x83, 0x08, 0x3F, 0xCF, 0x4E, 0x1D, 0xFB, 0x0F, 0x74, 0x26 }, + new byte[] { 0x0F, 0x3F, 0x35, 0x99, 0x1A, 0xC0, 0xB1, 0xAA, 0xB1, 0x12, 0x84, 0x05, 0x9D, 0x96, 0x9B, 0x4A, 0xC7, 0xA0, 0x3B, 0x13 }, + new byte[] { 0x3B, 0xA9, 0x01, 0x6A, 0x98, 0x44, 0x47, 0x0D, 0x46, 0x33, 0xEF, 0x2E, 0x6A, 0xC6, 0x3C, 0x77, 0xAF, 0x9A, 0xCC, 0x99 }, + new byte[] { 0xDB, 0xF6, 0x28, 0x3C, 0xF8, 0x2E, 0xDC, 0x4E, 0x1D, 0xA5, 0xCB, 0xDD, 0xA6, 0xFA, 0x21, 0x8E, 0xB8, 0xAE, 0x72, 0xBB }, + new byte[] { 0xA4, 0xBF, 0x04, 0xE7, 0x2F, 0x5E, 0x9D, 0xBD, 0x7B, 0xF8, 0x50, 0x77, 0x67, 0x69, 0xB6, 0x2F, 0x56, 0x8D, 0xC7, 0xF9 }, + new byte[] { 0x6A, 0xAE, 0xA0, 0x64, 0xB9, 0xBB, 0xE7, 0xF1, 0xED, 0xAE, 0xF4, 0x7F, 0x8B, 0x83, 0x5F, 0x0E, 0xA8, 0xD5, 0x06, 0x6B }, + new byte[] { 0x1B, 0xB1, 0x18, 0xB6, 0xC1, 0x19, 0x2B, 0x98, 0xAF, 0x11, 0x98, 0xCB, 0x73, 0xC3, 0xE1, 0xE5, 0xAE, 0x48, 0xDD, 0xA1 }, + new byte[] { 0x4B, 0x97, 0x33, 0x2A, 0x27, 0x28, 0xFF, 0x46, 0xD8, 0xBD, 0x73, 0x61, 0x5D, 0x14, 0xCF, 0x47, 0xD3, 0xC2, 0xC9, 0xA0 }, + new byte[] { 0x66, 0x15, 0x42, 0x97, 0x46, 0x57, 0x96, 0x16, 0x5A, 0x87, 0x6F, 0x5E, 0xF6, 0x84, 0xB3, 0xA0, 0xDB, 0x5C, 0x6D, 0x58 }, + new byte[] { 0xF5, 0xB5, 0xE7, 0x6F, 0x77, 0xFE, 0x13, 0xAC, 0xC2, 0xF9, 0x2D, 0xEA, 0xD0, 0xD9, 0xC5, 0xCD, 0x05, 0x9A, 0xC0, 0x48 }, + new byte[] { 0x8A, 0x0C, 0x59, 0xBD, 0x88, 0x0D, 0x28, 0x18, 0x3D, 0xE9, 0x8B, 0x2C, 0xB0, 0x9A, 0xD0, 0xE1, 0xBE, 0x0C, 0x03, 0x23 }, + new byte[] { 0x26, 0xA7, 0xBC, 0x77, 0x22, 0x5F, 0x67, 0xBC, 0x3D, 0xD5, 0xD5, 0x05, 0x53, 0xB9, 0xD8, 0x2D, 0xD2, 0x80, 0x80, 0x26 }, + new byte[] { 0x66, 0x40, 0x17, 0x57, 0x5B, 0x70, 0x7B, 0x76, 0x71, 0x91, 0x56, 0xED, 0xFB, 0x5E, 0xC9, 0x7B, 0x55, 0x77, 0x5C, 0x40 }, + new byte[] { 0xEC, 0x90, 0xAB, 0xB0, 0x46, 0x6E, 0x62, 0xF1, 0xB9, 0xDB, 0xFB, 0xF2, 0x4E, 0xAE, 0x2F, 0x20, 0x54, 0x74, 0xA1, 0xDA }, + new byte[] { 0x4A, 0xA3, 0x51, 0x73, 0x61, 0x98, 0x34, 0x18, 0x8D, 0x9E, 0x76, 0x59, 0x89, 0x68, 0x2A, 0x1C, 0x1A, 0x2D, 0x27, 0x77 }, + new byte[] { 0xB5, 0xDF, 0x02, 0x8B, 0xB9, 0x86, 0x0C, 0x84, 0x0D, 0x75, 0x45, 0x77, 0xFF, 0x9C, 0x02, 0xEB, 0x7D, 0x65, 0x09, 0x29 }, + new byte[] { 0x86, 0x26, 0xF9, 0xF0, 0xA7, 0xA9, 0x79, 0x55, 0x72, 0x14, 0x6F, 0x92, 0xAC, 0xC1, 0x06, 0x12, 0xCD, 0x60, 0x75, 0x7D }, + new byte[] { 0xCD, 0xA4, 0xC6, 0x4F, 0x0F, 0x94, 0x65, 0x11, 0x57, 0x4D, 0xF5, 0xC6, 0xA0, 0x19, 0x8E, 0x7B, 0x51, 0xEE, 0xBC, 0x07 }, + new byte[] { 0xC2, 0xB6, 0x51, 0x28, 0xC5, 0xBF, 0x14, 0x0C, 0xDD, 0x58, 0xFB, 0xAE, 0xFF, 0x43, 0x4A, 0x69, 0x89, 0x23, 0x37, 0x1A }, + new byte[] { 0x14, 0x30, 0xFF, 0x46, 0xEA, 0xFB, 0xCA, 0x55, 0xDF, 0x49, 0x4A, 0x1B, 0x7F, 0xCD, 0x5F, 0xDD, 0xC7, 0x6E, 0x71, 0x2E }, + new byte[] { 0xD0, 0xB6, 0x7E, 0x92, 0xA0, 0xFB, 0x5A, 0x74, 0xCB, 0x2C, 0xFA, 0x60, 0x25, 0xAB, 0xE4, 0x7B, 0x88, 0xE4, 0xD8, 0xAE }, + new byte[] { 0xAE, 0xDB, 0x38, 0xAA, 0x93, 0xEA, 0x10, 0xBC, 0xFF, 0x5D, 0x7B, 0xAB, 0x8F, 0x95, 0x6F, 0x4A, 0x03, 0xA8, 0xF2, 0xF2 }, + new byte[] { 0x81, 0xBF, 0xDA, 0x4A, 0x64, 0x97, 0x3C, 0x36, 0x64, 0x52, 0x13, 0xAE, 0xB5, 0x39, 0xD3, 0x1D, 0xF6, 0xEA, 0x8C, 0x99 }, + new byte[] { 0x9A, 0x1D, 0xE6, 0x96, 0x0F, 0x2C, 0xF2, 0x3F, 0x46, 0xCD, 0x14, 0x04, 0xD4, 0xEE, 0x6E, 0xA7, 0x73, 0xE9, 0x1A, 0x8A }, + new byte[] { 0xB6, 0xE6, 0xD2, 0xFA, 0xE3, 0x95, 0x1C, 0xDD, 0x28, 0x6C, 0x97, 0xA2, 0xE1, 0x54, 0x0F, 0x72, 0xAB, 0x63, 0x20, 0x5D }, + new byte[] { 0xCF, 0x57, 0x29, 0xAF, 0x92, 0x38, 0x1D, 0x0B, 0x5F, 0xCE, 0x3F, 0x11, 0x77, 0x5E, 0x75, 0x96, 0xBE, 0xBD, 0x27, 0x25 }, + new byte[] { 0x19, 0x8E, 0xC1, 0x12, 0xFC, 0xB3, 0xD9, 0x93, 0x8A, 0x6C, 0xA5, 0x13, 0x5D, 0xFB, 0x6D, 0x77, 0xF6, 0xDC, 0x2F, 0xEE }, + new byte[] { 0x04, 0x81, 0x55, 0x6C, 0xD2, 0x59, 0xFB, 0xAD, 0xF8, 0xE1, 0xF1, 0xA7, 0x85, 0x02, 0xA6, 0xF4, 0x7F, 0xA2, 0x2F, 0x62 }, + new byte[] { 0x88, 0x0E, 0xBD, 0x6A, 0xA6, 0x47, 0x17, 0xAD, 0xA1, 0xE6, 0xE0, 0x97, 0x74, 0x53, 0x9C, 0xFE, 0x38, 0xFB, 0x91, 0x52 }, + new byte[] { 0xA1, 0xAE, 0x7D, 0x57, 0x6F, 0xF8, 0x85, 0xE2, 0xA8, 0xFD, 0xB6, 0x01, 0xE3, 0x55, 0x65, 0x60, 0xCD, 0xD8, 0xD3, 0x30 }, + new byte[] { 0x80, 0x26, 0xA6, 0x9B, 0x78, 0x2C, 0x0F, 0xD6, 0x4C, 0xE5, 0x19, 0x42, 0xAC, 0xC8, 0x42, 0x07, 0x54, 0x28, 0xFF, 0x14 }, + new byte[] { 0x89, 0x03, 0xCA, 0x8A, 0x1F, 0xD4, 0x73, 0x0F, 0x68, 0x8A, 0x61, 0x0D, 0xAC, 0xFA, 0x64, 0x7D, 0xC8, 0xAA, 0x96, 0xF2 }, + new byte[] { 0x99, 0x37, 0x9A, 0x14, 0x51, 0x14, 0xB5, 0xD5, 0x99, 0x6A, 0x57, 0x9C, 0xF2, 0xE3, 0x38, 0xAF, 0x70, 0x9C, 0x49, 0xC9 }, + new byte[] { 0x0F, 0x2D, 0x55, 0x01, 0x05, 0x44, 0x55, 0x66, 0x0E, 0xFC, 0x4F, 0xB2, 0xBA, 0x29, 0x9B, 0x5B, 0xCA, 0x29, 0xBC, 0x1A }, + new byte[] { 0xF1, 0x38, 0x5B, 0x67, 0xF4, 0xAF, 0xBE, 0xC9, 0x4F, 0x7A, 0x00, 0xA6, 0x8B, 0x0E, 0x70, 0x0B, 0xA8, 0x6A, 0x81, 0xEE }, + new byte[] { 0x36, 0xB1, 0x05, 0xB7, 0xED, 0x94, 0xCA, 0x95, 0xD3, 0x9E, 0x1C, 0xE2, 0x4D, 0xD9, 0x71, 0x66, 0x46, 0xF2, 0x9B, 0x59 }, + new byte[] { 0x75, 0xC6, 0x12, 0x28, 0xE2, 0x7F, 0x61, 0xF0, 0x4B, 0x71, 0xCD, 0x4D, 0xE8, 0xE3, 0x9A, 0xE4, 0x20, 0xC2, 0x5C, 0xE6 }, + new byte[] { 0x37, 0x0E, 0x44, 0xD7, 0x27, 0x99, 0xE6, 0x2B, 0xB1, 0x34, 0xFA, 0xB7, 0x45, 0x33, 0xF7, 0xCD, 0x3C, 0x0D, 0x77, 0xF5 }, + new byte[] { 0xAA, 0x46, 0xCE, 0xA4, 0x4D, 0x0A, 0xCE, 0xDC, 0x81, 0x59, 0xEC, 0xCF, 0x1E, 0x0F, 0xB4, 0x15, 0xE8, 0x27, 0x18, 0x9E }, + new byte[] { 0xC0, 0x0D, 0x76, 0xBD, 0x70, 0x3B, 0x1B, 0x6F, 0x11, 0x1A, 0x84, 0x2B, 0x0B, 0x19, 0xC6, 0x55, 0xC6, 0x7F, 0x0F, 0x6C }, + new byte[] { 0xF7, 0xA9, 0x4E, 0x1F, 0x06, 0x03, 0xB9, 0xD7, 0x36, 0x0A, 0x34, 0x7F, 0x41, 0x94, 0x1D, 0x57, 0xA1, 0xD0, 0x0A, 0xFA }, + new byte[] { 0xCC, 0xAF, 0x7E, 0x30, 0x26, 0xDE, 0xC8, 0xC9, 0x3C, 0x27, 0x8F, 0x40, 0x32, 0xF5, 0xAB, 0xC4, 0xCB, 0x90, 0x6D, 0xAE }, + new byte[] { 0x39, 0x5D, 0x47, 0xF2, 0xF8, 0x91, 0xFF, 0xD7, 0xE1, 0x75, 0xF3, 0xA0, 0xFA, 0xC3, 0xC2, 0x86, 0x0D, 0xE1, 0xE2, 0x45 }, + new byte[] { 0xB1, 0xC9, 0x1C, 0x3E, 0x77, 0x20, 0xEE, 0x9C, 0xBC, 0xA4, 0x1E, 0x3E, 0x6C, 0x34, 0x40, 0x08, 0x09, 0x27, 0xA7, 0xF5 }, + new byte[] { 0x61, 0x92, 0x6E, 0xF1, 0xA1, 0x0F, 0x71, 0x25, 0x1C, 0xEE, 0xE4, 0x94, 0x8B, 0x29, 0xEA, 0x7E, 0x90, 0x36, 0xE5, 0xE5 }, + new byte[] { 0xD5, 0xDE, 0x91, 0xB6, 0x37, 0x2C, 0x00, 0x73, 0xB8, 0x80, 0x17, 0x19, 0xF4, 0xC0, 0xCE, 0xE6, 0xDF, 0xFB, 0xB5, 0xFC }, + new byte[] { 0x01, 0xE0, 0x43, 0xC0, 0xDA, 0x86, 0xE9, 0x73, 0x51, 0xFA, 0x2E, 0x4A, 0xF1, 0xA4, 0xF6, 0x5B, 0x6A, 0x97, 0x7B, 0x39 }, + new byte[] { 0x80, 0x85, 0x51, 0x20, 0xBA, 0x2E, 0x31, 0x6B, 0xD7, 0xB8, 0x09, 0x30, 0xA5, 0x60, 0xCC, 0x0E, 0x8B, 0x9A, 0x91, 0xD7 }, + new byte[] { 0x06, 0x06, 0xC0, 0xB8, 0x2A, 0x97, 0x94, 0x7D, 0x25, 0x2C, 0xD3, 0x87, 0x8A, 0x9D, 0xBE, 0xFD, 0xEC, 0x17, 0xB4, 0x98 }, + new byte[] { 0x5F, 0xD7, 0x58, 0xEB, 0x71, 0x3A, 0x4B, 0xE0, 0x8E, 0x29, 0x2A, 0xC7, 0x55, 0x75, 0x91, 0xA7, 0x06, 0xA3, 0x2B, 0x2C }, + new byte[] { 0x2A, 0x3C, 0x3F, 0xA1, 0x1C, 0xFA, 0x0F, 0x5F, 0x75, 0x4C, 0x65, 0x56, 0xE0, 0xD9, 0x52, 0x06, 0x11, 0xD6, 0xB4, 0x0B }, + new byte[] { 0xFA, 0xE6, 0xB7, 0x90, 0xB7, 0x87, 0x91, 0xA9, 0x10, 0x84, 0xA1, 0xB5, 0xCA, 0x9A, 0x70, 0x7D, 0x56, 0x07, 0xE4, 0x5F }, + new byte[] { 0x8F, 0x9A, 0xA7, 0x48, 0xF1, 0x14, 0x50, 0x67, 0xFA, 0xC8, 0x0E, 0x18, 0x26, 0x48, 0xED, 0x61, 0x8C, 0x84, 0xAC, 0xCE }, + new byte[] { 0x39, 0xB7, 0xFD, 0x2F, 0xB4, 0xEB, 0x43, 0xE3, 0xC1, 0xCE, 0xF1, 0x5D, 0x9E, 0xF7, 0x16, 0xA6, 0x81, 0x12, 0x25, 0xBA }, + new byte[] { 0xEB, 0x28, 0xF6, 0x34, 0x62, 0x49, 0xA7, 0x99, 0x16, 0x2E, 0x0B, 0xEE, 0xE5, 0x58, 0x92, 0x90, 0xAE, 0x8C, 0xCF, 0x3F }, + new byte[] { 0x51, 0xDA, 0xC7, 0x9D, 0x41, 0x87, 0xB3, 0x94, 0x43, 0xFE, 0x3B, 0xC7, 0xF9, 0x19, 0x72, 0x47, 0x55, 0xAD, 0x27, 0x19 }, + new byte[] { 0x0C, 0xAF, 0xFE, 0x08, 0x02, 0x3E, 0xD8, 0xB5, 0xAC, 0x2A, 0x14, 0x18, 0xBD, 0x42, 0x05, 0xAB, 0xD7, 0x43, 0x3E, 0x9B }, + new byte[] { 0x0F, 0x0B, 0x7A, 0x98, 0xE8, 0x89, 0x63, 0xE9, 0x16, 0xC6, 0x78, 0x78, 0x86, 0x18, 0x7F, 0x3F, 0xCB, 0x7F, 0x9C, 0x39 }, + new byte[] { 0xB6, 0x4A, 0x86, 0x10, 0xAB, 0x90, 0xE1, 0xF2, 0xED, 0xD2, 0x2B, 0xAC, 0x42, 0x38, 0x33, 0x1A, 0xF8, 0x95, 0xB7, 0x5B }, + new byte[] { 0x57, 0x77, 0x12, 0x3E, 0x8F, 0x6A, 0x2B, 0x7F, 0x95, 0x14, 0x14, 0xA0, 0x9E, 0xE0, 0x1B, 0x36, 0x1C, 0x3C, 0xA1, 0xD0 }, + new byte[] { 0x24, 0x87, 0x11, 0x86, 0x54, 0xBC, 0x51, 0x30, 0x3E, 0xA7, 0x79, 0xC5, 0xB2, 0x64, 0x76, 0x97, 0x78, 0x31, 0x3E, 0xBB }, + new byte[] { 0x75, 0x60, 0xA9, 0x20, 0xA9, 0x1A, 0xE7, 0x49, 0x1B, 0x14, 0xD2, 0x7D, 0xEF, 0x75, 0xFB, 0x0B, 0xFC, 0x26, 0x8F, 0xA6 }, + new byte[] { 0xB0, 0x7B, 0x51, 0x09, 0x5D, 0x44, 0xBA, 0xAB, 0x05, 0xF8, 0x9B, 0x5E, 0x8A, 0xC1, 0xBC, 0x73, 0xE1, 0x32, 0x64, 0xA5 }, + new byte[] { 0x1F, 0x8B, 0x33, 0x1D, 0xEF, 0x6E, 0xBE, 0x11, 0x21, 0x2F, 0x2B, 0x61, 0xB8, 0x5E, 0xCC, 0xED, 0xEA, 0xA7, 0x21, 0xD9 }, + new byte[] { 0x72, 0x71, 0x1E, 0xA9, 0x46, 0x60, 0x3E, 0x30, 0xA2, 0x0E, 0x96, 0xDE, 0x49, 0x6B, 0x15, 0x79, 0xCE, 0xFB, 0xEE, 0x4A }, + new byte[] { 0xF7, 0x8A, 0x72, 0x5F, 0xCF, 0x7D, 0xDD, 0xAA, 0x39, 0xBE, 0x6D, 0x48, 0x81, 0x90, 0xD0, 0xEC, 0x66, 0x71, 0x95, 0xBC }, + new byte[] { 0x68, 0x12, 0x9A, 0xAB, 0x54, 0x6E, 0x0D, 0xA8, 0x23, 0xFE, 0x07, 0x42, 0xEA, 0xE3, 0x02, 0x6A, 0xDA, 0x07, 0x48, 0xBE }, + new byte[] { 0xAE, 0x2E, 0x8D, 0x33, 0x41, 0x58, 0x2E, 0x47, 0x41, 0x0F, 0xDB, 0x24, 0xCB, 0xD3, 0xC5, 0x00, 0x1B, 0x3C, 0x40, 0xD2 }, + new byte[] { 0xCD, 0xB4, 0xC7, 0x16, 0x3C, 0x12, 0x40, 0x7C, 0x66, 0x4E, 0x4D, 0x4E, 0x2E, 0x2F, 0xEA, 0xD4, 0x8A, 0xD9, 0x37, 0xD3 }, + new byte[] { 0x4B, 0xB9, 0x75, 0x5B, 0x31, 0xFF, 0x6F, 0xD8, 0xBD, 0xAA, 0x6F, 0xD9, 0xF9, 0xFB, 0x15, 0x8B, 0x73, 0x20, 0x11, 0x49 }, + new byte[] { 0xD4, 0x9B, 0x7A, 0x75, 0xED, 0x05, 0x88, 0xF4, 0x2A, 0x89, 0x52, 0xBD, 0x84, 0xB2, 0x90, 0xBC, 0xE6, 0xAF, 0x4A, 0x0F }, + new byte[] { 0xE5, 0x44, 0x7D, 0x79, 0xD6, 0x8B, 0xEC, 0x55, 0xBB, 0x5E, 0xF5, 0x5B, 0x84, 0xA7, 0xC3, 0x13, 0x5F, 0xD0, 0x0E, 0xB2 }, + new byte[] { 0x64, 0x88, 0x46, 0xCD, 0xAC, 0xB5, 0x31, 0x5D, 0x5F, 0x80, 0x35, 0xCC, 0x8A, 0x52, 0x3F, 0xA8, 0xE6, 0x90, 0xDC, 0x75 }, + new byte[] { 0x2F, 0x02, 0x4D, 0xC8, 0x48, 0xFC, 0xDF, 0xBA, 0x73, 0x5E, 0x82, 0x88, 0x09, 0x9D, 0x00, 0x87, 0x2B, 0xED, 0x00, 0x27 }, + new byte[] { 0xC3, 0x42, 0x7F, 0x3A, 0x4B, 0x9C, 0xCE, 0x8F, 0xA0, 0x4D, 0x55, 0x76, 0x03, 0x01, 0xDC, 0xCD, 0xFA, 0x37, 0x56, 0x73 }, + new byte[] { 0xAA, 0x5C, 0xA4, 0x67, 0x47, 0xF9, 0x64, 0x49, 0x4B, 0x83, 0x8A, 0x24, 0xE3, 0xB5, 0x32, 0xE6, 0x39, 0xB3, 0x43, 0x9C }, + new byte[] { 0xC3, 0xF4, 0x6E, 0x4D, 0x3A, 0x30, 0x08, 0x44, 0xD7, 0x2D, 0x56, 0x70, 0xE6, 0xA6, 0x9F, 0x0A, 0x86, 0xC9, 0xBB, 0xF9 }, + new byte[] { 0x40, 0xE8, 0x7F, 0x72, 0x92, 0xCA, 0x36, 0xF5, 0x35, 0x30, 0xBF, 0xA4, 0x60, 0x89, 0x38, 0xD8, 0x77, 0x6E, 0x70, 0x2B }, + new byte[] { 0x9E, 0xCD, 0x04, 0x16, 0x90, 0xD7, 0x9D, 0xF2, 0x50, 0xC8, 0xF6, 0xE9, 0x8F, 0xC7, 0x71, 0x93, 0x80, 0xB0, 0x26, 0xAC }, + new byte[] { 0x74, 0xE1, 0xAD, 0x78, 0x3B, 0xA4, 0x0B, 0x0F, 0xCF, 0x70, 0x9A, 0x74, 0x15, 0xED, 0xCE, 0x94, 0x17, 0xA3, 0x3C, 0xA9 }, + new byte[] { 0x4A, 0x2A, 0xA2, 0xD4, 0x71, 0x38, 0x55, 0x9A, 0x8F, 0xA2, 0x2A, 0x48, 0xE5, 0x57, 0xEA, 0xA2, 0x43, 0x65, 0x13, 0xF9 }, + new byte[] { 0x2F, 0x23, 0x20, 0xAD, 0xAA, 0x87, 0x97, 0x6C, 0x26, 0xC3, 0xF5, 0x86, 0x80, 0x2C, 0x9B, 0x6A, 0x1C, 0xE4, 0x9A, 0xA5 }, + new byte[] { 0xF4, 0x79, 0x16, 0x18, 0xAB, 0x41, 0xD4, 0xE3, 0x73, 0x7F, 0xE9, 0x79, 0x07, 0xA2, 0xC2, 0xB8, 0x59, 0x3D, 0x86, 0x38 }, + new byte[] { 0x9A, 0x65, 0x84, 0x31, 0x29, 0xD1, 0x18, 0x2A, 0x45, 0xF4, 0x28, 0xB9, 0x31, 0x5A, 0xFA, 0xCA, 0xAE, 0xD0, 0xA7, 0xB9 }, + new byte[] { 0x06, 0x0E, 0x28, 0x25, 0x42, 0x51, 0xAC, 0x22, 0x59, 0x49, 0x9E, 0x43, 0xF6, 0xD5, 0x6D, 0x52, 0x28, 0x8F, 0xBA, 0xD0 }, + new byte[] { 0xEC, 0x55, 0xE5, 0xA1, 0xDA, 0x41, 0x22, 0x76, 0x9F, 0x08, 0x98, 0xE4, 0xBB, 0xEA, 0xE3, 0x59, 0x32, 0x84, 0xAF, 0xC1 }, + new byte[] { 0xC0, 0xF7, 0x43, 0x77, 0xB1, 0x56, 0x50, 0xFC, 0xCA, 0xF7, 0x36, 0x89, 0x1C, 0xF9, 0xF4, 0x45, 0xD3, 0xD0, 0x02, 0x27 }, + new byte[] { 0x6D, 0x1D, 0xEE, 0x18, 0x63, 0xD0, 0xB8, 0xBA, 0x2A, 0x19, 0xD6, 0x93, 0x88, 0xF2, 0x27, 0x03, 0xF7, 0x01, 0x97, 0x13 }, + new byte[] { 0x07, 0x25, 0x38, 0x62, 0x0C, 0xEC, 0x14, 0x68, 0x1B, 0xCF, 0x62, 0xE9, 0x65, 0xB4, 0x46, 0xE7, 0x68, 0xEA, 0x82, 0xF4 }, + new byte[] { 0xE7, 0x68, 0x6E, 0x1F, 0x20, 0x62, 0x69, 0xD7, 0x2A, 0xB6, 0x7B, 0xEB, 0xB5, 0xB9, 0x2C, 0xBD, 0x43, 0xCB, 0xC8, 0xF4 }, + new byte[] { 0x68, 0xFF, 0xD2, 0xB6, 0x25, 0xA3, 0x06, 0x7C, 0xFA, 0xE5, 0x47, 0x84, 0x89, 0x83, 0x5F, 0xEC, 0x91, 0x0E, 0x13, 0x93 }, + new byte[] { 0x92, 0xF9, 0xF4, 0x11, 0xB7, 0xE9, 0xDC, 0x7E, 0xDE, 0xE4, 0xF2, 0x22, 0x3A, 0x38, 0xC2, 0x7D, 0x57, 0xC2, 0xDB, 0xB8 }, + new byte[] { 0xB3, 0x9B, 0x96, 0xD9, 0x78, 0xE3, 0xF5, 0xC5, 0xB7, 0x6B, 0x12, 0x07, 0xC8, 0xAA, 0x1D, 0xB1, 0x4C, 0x85, 0x38, 0x39 }}; + + // ng decryption tables... + public static byte[][] PC_NG_DECRYPT_TABLE_HASHES = new byte[][] { + new byte[] { 0xCE, 0xAB, 0x97, 0x16, 0xBD, 0xEC, 0x4E, 0xB6, 0xB0, 0x28, 0xD3, 0x56, 0x39, 0xE4, 0x5F, 0x2F, 0x3D, 0x8A, 0xC0, 0x3A }, + new byte[] { 0x61, 0x86, 0x8D, 0xFD, 0xF3, 0x86, 0x92, 0xB0, 0xC0, 0x71, 0xF6, 0xB1, 0xC8, 0x09, 0x67, 0x41, 0x22, 0xD4, 0xB3, 0x03 }, + new byte[] { 0xBD, 0x28, 0x5F, 0x22, 0xD5, 0x7C, 0x53, 0xEB, 0x15, 0xC7, 0x28, 0x30, 0x11, 0x2C, 0xD8, 0x0B, 0xF9, 0xDB, 0x0D, 0xC1 }, + new byte[] { 0xCE, 0x23, 0xF5, 0xC5, 0x68, 0x26, 0xF5, 0x3F, 0x78, 0x03, 0xD4, 0xE8, 0x43, 0xCD, 0x19, 0x9A, 0x4D, 0x82, 0xCB, 0xD8 }, + new byte[] { 0xA6, 0xF3, 0xBB, 0xDF, 0x03, 0xFA, 0xCA, 0xF8, 0x93, 0x2D, 0x8E, 0x2E, 0x3B, 0x82, 0x5F, 0x18, 0xD5, 0x4B, 0xF3, 0x8A }, + new byte[] { 0x5B, 0xD1, 0x4C, 0xB2, 0x42, 0x1D, 0x70, 0x11, 0xBA, 0xC1, 0x1E, 0x97, 0xF9, 0xE5, 0x53, 0xE4, 0x80, 0xA4, 0xA9, 0x26 }, + new byte[] { 0x2F, 0x7A, 0x79, 0x53, 0xDB, 0x77, 0x49, 0x9A, 0xDF, 0x2B, 0x76, 0x19, 0xDE, 0x05, 0xFB, 0xBC, 0xCB, 0x37, 0x9C, 0x0D }, + new byte[] { 0xC3, 0x6C, 0xE4, 0x15, 0x62, 0xD8, 0x55, 0xAC, 0x25, 0x17, 0x38, 0x32, 0xD3, 0xFC, 0x1A, 0x13, 0xE1, 0xE4, 0x90, 0x67 }, + new byte[] { 0x31, 0x41, 0xE6, 0xEB, 0xE2, 0xA1, 0xC2, 0xFA, 0x44, 0xD9, 0x72, 0x8E, 0x8D, 0x55, 0x0E, 0xF0, 0x28, 0xB1, 0x19, 0xC6 }, + new byte[] { 0x3D, 0x40, 0x6E, 0xBB, 0xEE, 0x33, 0x93, 0xAB, 0xC8, 0xCE, 0x1C, 0xBE, 0x06, 0x94, 0xB1, 0xCA, 0xF6, 0x72, 0x7F, 0x66 }, + new byte[] { 0x62, 0x1C, 0x68, 0x38, 0x79, 0x92, 0x33, 0xDA, 0xC3, 0xC9, 0x78, 0x5A, 0x35, 0xE7, 0x44, 0x88, 0x16, 0x86, 0x9C, 0x64 }, + new byte[] { 0xD5, 0x93, 0xD9, 0xDD, 0x0C, 0x91, 0xB6, 0x32, 0xA7, 0x96, 0x45, 0x4A, 0x57, 0x6B, 0x05, 0xE2, 0x86, 0xCC, 0xB8, 0x86 }, + new byte[] { 0xC9, 0x33, 0x33, 0xB8, 0x35, 0x07, 0x1D, 0xC4, 0xF0, 0x16, 0xA4, 0xB8, 0x93, 0x60, 0x2B, 0xF5, 0x11, 0x9E, 0x8B, 0x1F }, + new byte[] { 0xDA, 0x99, 0x31, 0x62, 0x1E, 0xE0, 0xAC, 0xBE, 0xF8, 0xF4, 0xF9, 0x95, 0x9B, 0x2D, 0x1D, 0x15, 0x69, 0x57, 0x8D, 0xC2 }, + new byte[] { 0xB9, 0x20, 0xE8, 0x41, 0x15, 0xCA, 0x2B, 0xBF, 0x0A, 0x16, 0x79, 0xE9, 0xDC, 0x7C, 0xD2, 0xD7, 0xF3, 0xF3, 0xEC, 0x99 }, + new byte[] { 0xF6, 0x2B, 0x9D, 0x1C, 0xEE, 0xCE, 0x56, 0xC7, 0x61, 0x28, 0x3A, 0x17, 0x94, 0xF3, 0xA3, 0x09, 0x3B, 0xE7, 0x4F, 0xDE }, + new byte[] { 0x35, 0xCD, 0x71, 0xC3, 0xA4, 0x31, 0x29, 0xA3, 0x57, 0x2A, 0x52, 0xA0, 0x5D, 0x83, 0x95, 0x87, 0xBC, 0x64, 0x0E, 0xA3 }, + new byte[] { 0xD0, 0x71, 0xC0, 0x43, 0x57, 0xCE, 0xF5, 0x86, 0xD8, 0x04, 0xFF, 0x7B, 0x5C, 0x9B, 0x24, 0x7E, 0x4B, 0x05, 0x2B, 0xF0 }, + new byte[] { 0xF5, 0xD1, 0x72, 0xA4, 0x92, 0x78, 0xA9, 0x84, 0x53, 0x49, 0xAD, 0x73, 0x17, 0x8F, 0x2F, 0xEE, 0x8B, 0x0A, 0xAD, 0xBF }, + new byte[] { 0xA5, 0x9E, 0x9B, 0x49, 0x3A, 0xAF, 0x92, 0xDA, 0x8F, 0x4F, 0x3C, 0x20, 0x88, 0x12, 0x89, 0xE1, 0x62, 0x56, 0x95, 0xDA }, + new byte[] { 0xDE, 0x5D, 0x57, 0xA5, 0x08, 0x52, 0xB6, 0xF4, 0x79, 0x8D, 0x9E, 0x52, 0xC4, 0xC5, 0x72, 0x24, 0x5C, 0x13, 0x21, 0xB4 }, + new byte[] { 0x2A, 0x9A, 0x5B, 0x76, 0xF4, 0xBB, 0xD1, 0x56, 0x1F, 0x23, 0xE7, 0xB5, 0x15, 0xA1, 0xAB, 0x1F, 0x6E, 0x33, 0x43, 0xB0 }, + new byte[] { 0xE7, 0x4D, 0x0C, 0x5F, 0x4B, 0x78, 0x6D, 0x32, 0x48, 0x3D, 0x10, 0x0C, 0xA0, 0xAA, 0x4A, 0x1F, 0xCA, 0xB7, 0x4F, 0x50 }, + new byte[] { 0x56, 0xF1, 0xA4, 0xC1, 0x06, 0xDE, 0x83, 0xDA, 0x93, 0x51, 0x32, 0x8B, 0xD1, 0xCA, 0xAA, 0x8C, 0x2E, 0x74, 0xBB, 0x77 }, + new byte[] { 0x1D, 0x50, 0xF9, 0xD2, 0xE6, 0x9B, 0xEC, 0x48, 0xCD, 0x38, 0x58, 0x79, 0x38, 0xE7, 0xC3, 0xEB, 0xCF, 0x77, 0xE7, 0x7B }, + new byte[] { 0x1E, 0xE3, 0x16, 0x88, 0x2A, 0xB9, 0xD7, 0xAE, 0x4A, 0xD9, 0xEB, 0xC8, 0x0D, 0x39, 0xA8, 0x5D, 0xF5, 0x60, 0x19, 0xD1 }, + new byte[] { 0x36, 0x45, 0x6E, 0x8C, 0xD8, 0x1D, 0x0C, 0x6B, 0x3C, 0xA9, 0xA5, 0xEF, 0x2A, 0xFB, 0x08, 0xC4, 0x3E, 0x18, 0x40, 0xAE }, + new byte[] { 0xAA, 0x57, 0x3C, 0xCC, 0x91, 0x64, 0x9C, 0x17, 0xFA, 0xFA, 0xEC, 0x8C, 0x13, 0x7C, 0x43, 0xFD, 0xB1, 0x0C, 0xFC, 0x8E }, + new byte[] { 0x3B, 0xE4, 0xC0, 0xA3, 0xF5, 0x4D, 0x30, 0x75, 0xBD, 0x94, 0xF5, 0x17, 0x41, 0x85, 0x8A, 0xD8, 0x8A, 0x70, 0x14, 0xA6 }, + new byte[] { 0x01, 0x60, 0xBD, 0x1E, 0x73, 0x92, 0x1E, 0xD4, 0x92, 0x03, 0x8F, 0x68, 0x48, 0x9E, 0x6D, 0x53, 0x1F, 0x5A, 0x7D, 0xE6 }, + new byte[] { 0x4C, 0xEA, 0x08, 0xF0, 0x3A, 0xA2, 0x7F, 0xF1, 0xBD, 0x61, 0x31, 0xC1, 0xC3, 0x79, 0xFF, 0x56, 0x04, 0x06, 0x49, 0x04 }, + new byte[] { 0x57, 0x74, 0x33, 0xE6, 0x6C, 0xFA, 0x46, 0xFA, 0x29, 0xB5, 0xF0, 0x26, 0x53, 0xEE, 0x07, 0x40, 0xE2, 0xC2, 0x56, 0xF4 }, + new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC }, + new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F }, + new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 }, + new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F }, + new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 }, + new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F }, + new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 }, + new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 }, + new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 }, + new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 }, + new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 }, + new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 }, + new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC }, + new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 }, + new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 }, + new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 }, + new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F }, + new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 }, + new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 }, + new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F }, + new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 }, + new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B }, + new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 }, + new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 }, + new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 }, + new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E }, + new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 }, + new byte[] { 0x32, 0x3D, 0x56, 0x5F, 0x62, 0x30, 0x7E, 0x60, 0x72, 0xBD, 0x80, 0x8E, 0xA5, 0xED, 0x40, 0x14, 0x4D, 0x05, 0x61, 0xCB }, + new byte[] { 0x10, 0x31, 0xC7, 0xE0, 0x00, 0x14, 0x20, 0xA5, 0x0C, 0x28, 0x29, 0xF5, 0xE8, 0xA9, 0xF5, 0xB5, 0xE3, 0xAD, 0xAF, 0x01 }, + new byte[] { 0x19, 0xF9, 0x24, 0x23, 0xC9, 0xC8, 0x0A, 0x3A, 0xE3, 0x9B, 0xB6, 0x83, 0x19, 0x01, 0x0F, 0x3A, 0x07, 0xAF, 0x19, 0x48 }, + new byte[] { 0x68, 0x3B, 0xF5, 0xB1, 0xBB, 0x4A, 0x1E, 0x84, 0xD2, 0x67, 0x07, 0x35, 0x8F, 0x5C, 0xEE, 0xE4, 0x8D, 0x1A, 0x40, 0x40 }, + new byte[] { 0x96, 0xBE, 0xEA, 0x2F, 0x31, 0x27, 0x79, 0x0D, 0x9D, 0xAA, 0x89, 0x1C, 0x2B, 0x25, 0xF9, 0x3D, 0xC3, 0xF7, 0x8D, 0x33 }, + new byte[] { 0xEB, 0xE1, 0xF6, 0x24, 0x34, 0x9F, 0x34, 0xA4, 0x98, 0x9B, 0x6C, 0xB5, 0x4D, 0x71, 0xC6, 0x17, 0x5E, 0x49, 0xEF, 0x06 }, + new byte[] { 0xB6, 0xF8, 0x03, 0x89, 0x76, 0x2C, 0x30, 0xAF, 0xA4, 0x8B, 0xFA, 0xD5, 0xB2, 0x1E, 0xDE, 0x7B, 0x16, 0xEA, 0xDE, 0x00 }, + new byte[] { 0xE3, 0x5C, 0x12, 0x32, 0xE6, 0xFF, 0x18, 0x07, 0x4F, 0xB2, 0x54, 0x72, 0x0C, 0xC0, 0x02, 0x03, 0x62, 0xFA, 0xCF, 0xB5 }, + new byte[] { 0x22, 0x35, 0xB4, 0xC4, 0x39, 0x5C, 0x8D, 0x32, 0x78, 0xD3, 0x18, 0xFF, 0xA9, 0xA9, 0x49, 0x71, 0x6A, 0x15, 0x89, 0x86 }, + new byte[] { 0xCA, 0xD0, 0xFE, 0xB1, 0x57, 0x03, 0x24, 0xAE, 0xC7, 0x0A, 0xE6, 0x4C, 0x95, 0x77, 0xB9, 0xA2, 0x52, 0x6F, 0x82, 0x14 }, + new byte[] { 0x61, 0x28, 0xA2, 0x29, 0xA6, 0x05, 0x1F, 0x9B, 0x75, 0xEE, 0x05, 0xE6, 0x76, 0x89, 0x4A, 0x93, 0x7A, 0xD9, 0xD3, 0xA7 }, + new byte[] { 0xBA, 0xA2, 0xA7, 0xF0, 0x9D, 0x90, 0xCF, 0x88, 0x2A, 0x10, 0x51, 0x43, 0x1D, 0xB6, 0xE8, 0xB8, 0x14, 0x4B, 0xCC, 0xB1 }, + new byte[] { 0xAC, 0x87, 0x83, 0xBA, 0xB9, 0xBF, 0xB3, 0x82, 0x4B, 0x11, 0x21, 0x51, 0x10, 0x54, 0xC9, 0x8D, 0x1C, 0x91, 0x57, 0x93 }, + new byte[] { 0x5C, 0xD9, 0x28, 0xDE, 0x94, 0xA8, 0xA7, 0x80, 0x38, 0x40, 0x85, 0x7B, 0x9B, 0x90, 0x4C, 0xB9, 0xAC, 0x46, 0x1A, 0xE4 }, + new byte[] { 0x1B, 0xB9, 0x0E, 0x90, 0x54, 0x94, 0x30, 0xD7, 0xB6, 0xED, 0x22, 0x73, 0xE5, 0x0E, 0xD9, 0xF8, 0xD1, 0x89, 0x07, 0xC6 }, + new byte[] { 0xB5, 0xFB, 0x97, 0x72, 0x29, 0x80, 0x46, 0x9E, 0x98, 0x32, 0x16, 0xA8, 0xDD, 0x67, 0xE3, 0x08, 0xE5, 0x2F, 0xD4, 0x7B }, + new byte[] { 0x99, 0xD7, 0x23, 0x19, 0xEB, 0x25, 0x35, 0x50, 0x85, 0xB2, 0x07, 0xF6, 0x35, 0x05, 0x9A, 0x1E, 0xB7, 0x70, 0xEA, 0xB0 }, + new byte[] { 0x43, 0x98, 0x81, 0x8B, 0x29, 0x39, 0xB0, 0xA8, 0x4A, 0xE9, 0xF3, 0x5E, 0x34, 0x08, 0xB6, 0x06, 0x43, 0xC9, 0x65, 0x9A }, + new byte[] { 0x22, 0x29, 0x15, 0x79, 0xF0, 0x0E, 0x98, 0x23, 0x40, 0x02, 0xE7, 0x42, 0x73, 0xFE, 0xC6, 0xB9, 0x19, 0xD1, 0x75, 0x95 }, + new byte[] { 0xC4, 0x01, 0xA3, 0xB4, 0xDA, 0x0B, 0xBA, 0xA3, 0x0D, 0x7A, 0xEF, 0x7D, 0xD9, 0x3D, 0xC3, 0x30, 0x6D, 0xC0, 0x92, 0x58 }, + new byte[] { 0x0E, 0xBB, 0x73, 0x38, 0xF7, 0x1B, 0x31, 0x63, 0x3B, 0x08, 0x61, 0x2D, 0xF1, 0x70, 0xAD, 0x52, 0x61, 0x9E, 0xE8, 0x35 }, + new byte[] { 0x68, 0xA8, 0xC5, 0x39, 0x6C, 0x87, 0x6D, 0xE1, 0x60, 0x7B, 0x1C, 0x78, 0xD2, 0x75, 0xF0, 0xB0, 0xD0, 0x15, 0x00, 0xFB }, + new byte[] { 0x98, 0xCC, 0xA6, 0xC6, 0x2C, 0xE2, 0x56, 0xFE, 0x15, 0xD0, 0x93, 0xDE, 0x11, 0x0C, 0xDA, 0x11, 0x7C, 0x5D, 0x9D, 0x1D }, + new byte[] { 0x8E, 0xE8, 0x1A, 0x0D, 0x52, 0xAA, 0x76, 0x2D, 0xC4, 0x93, 0x79, 0xE9, 0xB6, 0x44, 0x63, 0xD9, 0x64, 0x76, 0x8E, 0xF1 }, + new byte[] { 0xEC, 0xB5, 0x72, 0x84, 0x60, 0x55, 0xAF, 0xCE, 0x9A, 0x1E, 0x4D, 0x8B, 0x21, 0x87, 0x5E, 0x25, 0xBE, 0x0C, 0xC0, 0x4E }, + new byte[] { 0xB6, 0xF4, 0xF6, 0xBC, 0x64, 0x34, 0xC3, 0xB5, 0x2D, 0xDE, 0xBA, 0xF2, 0xCA, 0xBF, 0x7F, 0x52, 0xCD, 0xE5, 0x45, 0xC1 }, + new byte[] { 0x33, 0xE2, 0xBE, 0xBD, 0xAA, 0x14, 0x04, 0xC6, 0x23, 0x96, 0xF4, 0x69, 0x78, 0x33, 0x48, 0xB6, 0x5D, 0x1A, 0xF0, 0xC0 }, + new byte[] { 0xEE, 0x0B, 0x31, 0xC0, 0x16, 0x73, 0x23, 0xD7, 0xE4, 0x82, 0xB1, 0xE2, 0x38, 0xDE, 0x99, 0xD7, 0x92, 0x66, 0x59, 0xAB }, + new byte[] { 0x8F, 0x9E, 0xC7, 0xAB, 0x3F, 0x5B, 0x97, 0xCF, 0xAC, 0x1D, 0xBA, 0x83, 0x88, 0x67, 0x90, 0xEF, 0xE1, 0xEF, 0xA4, 0xE1 }, + new byte[] { 0x2C, 0xF3, 0xF2, 0x12, 0x07, 0xDD, 0x8F, 0x2C, 0xBA, 0x24, 0x10, 0x4F, 0xDA, 0x7B, 0xEC, 0x21, 0x01, 0x16, 0xD4, 0x45 }, + new byte[] { 0xB9, 0xE1, 0x5D, 0xE5, 0xA0, 0x83, 0xC1, 0xAA, 0x9E, 0xAB, 0x09, 0x9B, 0x7E, 0x09, 0x39, 0x5E, 0x2C, 0xE0, 0x2B, 0xE4 }, + new byte[] { 0x43, 0x23, 0xB0, 0xAA, 0x5F, 0x01, 0x51, 0x74, 0x89, 0x04, 0xA4, 0xB2, 0xC4, 0x03, 0x3D, 0x5E, 0x9A, 0xF0, 0x1D, 0xBB }}; + + // hash lookup-table... + public static byte[] PC_LUT_HASH = new byte[] { 0x88, 0xD3, 0x79, 0x3B, 0x8E, 0x7A, 0x6C, 0xAC, 0xAA, 0x8B, 0x89, 0x28, 0x97, 0xBE, 0x72, 0x8D, 0x9E, 0x7F, 0xBA, 0xD4 }; + } + + + + public class GTA5NGLUT + { + public byte[][] LUT0; + public byte[][] LUT1; + public byte[] Indices; + + public GTA5NGLUT() + { + LUT0 = new byte[256][]; + for (int i = 0; i < 256; i++) + LUT0[i] = new byte[256]; + + LUT1 = new byte[256][]; + for (int i = 0; i < 256; i++) + LUT1[i] = new byte[256]; + + Indices = new byte[65536]; + } + + public byte LookUp(uint value) + { + uint h16 = (value & 0xFFFF0000) >> 16; + uint l8 = (value & 0x0000FF00) >> 8; + uint l0 = (value & 0x000000FF) >> 0; + return LUT0[LUT1[Indices[h16]][l8]][l0]; + } + } + + public static class HashSearch + { + private const long BLOCK_LENGTH = 1048576; + private const long ALIGN_LENGTH = 16; + + public static byte[] SearchHash(Stream stream, byte[] hash, int length = 32) + { + return SearchHashes(stream, new List { hash }, length)[0]; + } + + public static byte[][] SearchHashes(Stream stream, IList hashes, int length = 32) + { + var result = new byte[hashes.Count][]; + + Parallel.For(0, (stream.Length / BLOCK_LENGTH), (long k) => { + + var hashProvider = new SHA1CryptoServiceProvider(); + var buffer = new byte[length]; + for (long i = 0; i < (BLOCK_LENGTH / ALIGN_LENGTH); i++) + { + var position = k * BLOCK_LENGTH + i * ALIGN_LENGTH; + if (position >= stream.Length) + continue; + + lock (stream) + { + stream.Position = position; + stream.Read(buffer, 0, length); + } + + var hash = hashProvider.ComputeHash(buffer); + for (int j = 0; j < hashes.Count; j++) + if (hash.SequenceEqual(hashes[j])) + result[j] = (byte[])buffer.Clone(); + } + + + }); + + return result; + } + } + + + public class RandomGaussRow + { + //private bool[] A = new bool[1024]; + private ulong[] A = new ulong[16]; + public bool B; + + + public bool GetA(int idx) + { + int lidx = idx / 64; + int bidx = idx % 64; + return ((A[lidx] >> bidx) & 0x1) != 0; + } + + public void SetA(int idx) + { + int lidx = idx / 64; + int bidx = idx % 64; + A[lidx] |= (ulong)1 << bidx; + } + + public bool GetB() + { + return B; + } + + public void SetB() + { + this.B = true; + } + + public static RandomGaussRow operator ^(RandomGaussRow r1, RandomGaussRow r2) + { + var newRow = new RandomGaussRow(); + for (int i = 0; i < 16; i++) + newRow.A[i] = r1.A[i] ^ r2.A[i]; + newRow.B = r1.B ^ r2.B; + return newRow; + } + } + + public class RandomGauss + { + private const int TEST_ITERATIONS = 100000; + + public static bool[] Solve( + uint[][] tables, + int inByte0, int inByte1, int inByte2, int inByte3, + int outByte, int outBit) + { + var noKey = new uint[] { 0, 0, 0, 0 }; + var random = new Random(); + + var pivots = new List(); + + var firstPivot = new RandomGaussRow(); + firstPivot.SetA(0); + firstPivot.SetB(); + pivots.Add(firstPivot); + + var buf_encrypted = new byte[16]; + for (int pivotIdx = 1; pivotIdx < 1024; pivotIdx++) + { + while (true) + { + random.NextBytes(buf_encrypted); + + // decrypt + var buf_decrypted = GTACrypto.DecryptNGRoundA( + buf_encrypted, + noKey, + tables); + + // make row + var row = new RandomGaussRow(); + //row.A[0 + buf_decrypted[inByte0]] = true; + //row.A[256 + buf_decrypted[inByte1]] = true; + //row.A[512 + buf_decrypted[inByte2]] = true; + //row.A[768 + buf_decrypted[inByte3]] = true; + //row.B = (buf_encrypted[outByte] & (1 << outBit)) != 0; + row.SetA(0 + buf_decrypted[inByte0]); + row.SetA(256 + buf_decrypted[inByte1]); + row.SetA(512 + buf_decrypted[inByte2]); + row.SetA(768 + buf_decrypted[inByte3]); + if ((buf_encrypted[outByte] & (1 << outBit)) != 0) + row.SetB(); + + if (pivotIdx == 0x2ff) + { + row = new RandomGaussRow(); + row.SetA(0x2ff); + row.SetB(); + } + if (pivotIdx == 0x3ff) + { + row = new RandomGaussRow(); + row.SetA(0x3ff); + row.SetB(); + } + + // apply pivotIdx-1 pivots + for (int k = 0; k < pivotIdx; k++) + { + if (row.GetA(k)) + { + row ^= pivots[k]; + //var ppp = pivots[k]; + //for (int p = 0; p < 1024; p++) + // row.A[p] ^= ppp.A[p]; + //row.B ^= ppp.B; + } + } + + // check if this row is a new pivot + if (row.GetA(pivotIdx)) + { + pivots.Add(row); + // Console.WriteLine("Found pivot for column " + pivotIdx.ToString()); + break; + } + } + } + + var result = new bool[1024]; + for (int j = 1023; j >= 0; j--) + { + bool val = pivots[j].GetB(); + result[j] = val; + for (int k = 0; k < j; k++) + { + if (pivots[k].GetA(j)) + pivots[k].B ^= val; + } + } + + return result; + } + + public static uint[][] Solve(uint[][] tables) + { + var result = new uint[16][]; + for (int tabIdx = 0; tabIdx < 16; tabIdx++) + { + result[tabIdx] = new uint[256]; + } + + //for (int bitIdx = 0; bitIdx < 128; bitIdx++) + Parallel.For(0, 128, (int bitIdx) => + { + int outByte = bitIdx / 8; + int uintIdx = outByte / 4; + + int inByte0 = 4 * uintIdx + 0; + int inByte1 = 4 * uintIdx + 1; + int inByte2 = 4 * uintIdx + 2; + int inByte3 = 4 * uintIdx + 3; + int outBit = bitIdx % 8; + int z = bitIdx % 32; + + var bitResult = Solve(tables, inByte0, inByte1, inByte2, inByte3, outByte, outBit); + lock (result) + { + for (int i = 0; i < 256; i++) + { + if (bitResult[0 + i]) + result[inByte0][i] |= (uint)(1 << z); + if (bitResult[256 + i]) + result[inByte1][i] |= (uint)(1 << z); + if (bitResult[512 + i]) + result[inByte2][i] |= (uint)(1 << z); + if (bitResult[768 + i]) + result[inByte3][i] |= (uint)(1 << z); + } + } + + }); + + return result; + } + + } + + public class LookUpTableGenerator + { + public static GTA5NGLUT[] BuildLUTs2(uint[][] tables) + { + var temp = new byte[16][]; + for (int i = 0; i < 16; i++) + temp[i] = new byte[65536]; + + var result = new GTA5NGLUT[16]; + for (int i = 0; i < 16; i++) + { + result[i] = new GTA5NGLUT(); + //result[i].Tables = new byte[256][]; + //result[i].LUT = new byte[16777216]; + } + + var tempLUTS = new byte[16][]; + for (int i = 0; i < 16; i++) + tempLUTS[i] = new byte[16777216]; + + var t0 = tables[0]; + var t1 = tables[1]; + var t2 = tables[2]; + var t3 = tables[3]; + var t4 = tables[4]; + var t5 = tables[5]; + var t6 = tables[6]; + var t7 = tables[7]; + var t8 = tables[8]; + var t9 = tables[9]; + var t10 = tables[10]; + var t11 = tables[11]; + var t12 = tables[12]; + var t13 = tables[13]; + var t14 = tables[14]; + var t15 = tables[15]; + + Parallel.For(0, 0x100, (long k1) => + { + for (long k2 = 0; k2 < 0x1000000; k2++) + { + long i = k1 * 0x1000000 + k2; + + byte b0 = (byte)((i >> 0) & 0xFF); + byte b1 = (byte)((i >> 8) & 0xFF); + byte b2 = (byte)((i >> 16) & 0xFF); + byte b3 = (byte)((i >> 24) & 0xFF); + + var x1 = + t0[b0] ^ + t7[b1] ^ + t10[b2] ^ + t13[b3]; + var x2 = + t1[b0] ^ + t4[b1] ^ + t11[b2] ^ + t14[b3]; + var x3 = + t2[b0] ^ + t5[b1] ^ + t8[b2] ^ + t15[b3]; + var x4 = + t3[b0] ^ + t6[b1] ^ + t9[b2] ^ + t12[b3]; + + // the first LUT-compression step is built-it + // because it would take 4GB ram per data byte (and there are 16) + + if (x1 < 65536) + { + temp[0][x1] = b0; + temp[7][x1] = b1; + temp[10][x1] = b2; + temp[13][x1] = b3; + } + + if (x2 < 65536) + { + temp[1][x2] = b0; + temp[4][x2] = b1; + temp[11][x2] = b2; + temp[14][x2] = b3; + } + + if (x3 < 65536) + { + temp[2][x3] = b0; + temp[5][x3] = b1; + temp[8][x3] = b2; + temp[15][x3] = b3; + } + + if (x4 < 65536) + { + temp[3][x4] = b0; + temp[6][x4] = b1; + temp[9][x4] = b2; + temp[12][x4] = b3; + } + + if ((x1 & 0x000000FF) == 0) + { + tempLUTS[0][x1 >> 8] = b0; + tempLUTS[7][x1 >> 8] = b1; + tempLUTS[10][x1 >> 8] = b2; + tempLUTS[13][x1 >> 8] = b3; + } + + if ((x2 & 0x000000FF) == 0) + { + tempLUTS[1][x2 >> 8] = b0; + tempLUTS[4][x2 >> 8] = b1; + tempLUTS[11][x2 >> 8] = b2; + tempLUTS[14][x2 >> 8] = b3; + } + + if ((x3 & 0x000000FF) == 0) + { + tempLUTS[2][x3 >> 8] = b0; + tempLUTS[5][x3 >> 8] = b1; + tempLUTS[8][x3 >> 8] = b2; + tempLUTS[15][x3 >> 8] = b3; + } + + if ((x4 & 0x000000FF) == 0) + { + tempLUTS[3][x4 >> 8] = b0; + tempLUTS[6][x4 >> 8] = b1; + tempLUTS[9][x4 >> 8] = b2; + tempLUTS[12][x4 >> 8] = b3; + } + } + }); + + for (int i = 0; i < 16; i++) + { + result[i].LUT0 = new byte[256][]; + for (int blockIdx = 0; blockIdx < 256; blockIdx++) + { + + var xl = new byte[256]; + for (int k = 0; k < 256; k++) + { + xl[k] = temp[i][256 * blockIdx + k]; + } + + result[i].LUT0[xl[0]] = xl; + } + } + + // compress tables... + // length from 2^24 -> 2^16 + for (int i = 0; i < 16; i++) + { + GTA5NGLUT lut = result[i]; + lut.LUT1 = new byte[256][]; + lut.Indices = new byte[65536]; + + for (int blockIdx = 0; blockIdx < 256; blockIdx++) + { + var xl = new byte[256]; + for (int k = 0; k < 256; k++) + { + xl[k] = tempLUTS[i][256 * blockIdx + k]; + } + + lut.LUT1[xl[0]] = xl; + } + for (int blockIdx = 0; blockIdx < 65536; blockIdx++) + { + lut.Indices[blockIdx] = tempLUTS[i][256 * blockIdx]; + } + } + + return result; + } + } + + + + public class CryptoIO + { + public static byte[][] ReadNgKeys(string fileName) + { + byte[][] result; + + var fs = new FileStream(fileName, FileMode.Open); + var rd = new DataReader(fs); + + result = new byte[101][]; + for (int i = 0; i < 101; i++) + { + result[i] = rd.ReadBytes(272); + } + + fs.Close(); + + return result; + } + public static byte[][] ReadNgKeys(byte[] data) + { + byte[][] result; + + var rd = new DataReader(new MemoryStream(data)); + + result = new byte[101][]; + for (int i = 0; i < 101; i++) + { + result[i] = rd.ReadBytes(272); + } + + + return result; + } + + + public static void WriteNgKeys(string fileName, byte[][] keys) + { + //var fs = new FileStream(fileName, FileMode.Create); + //var wr = new DataWriter(fs); + var ms = new MemoryStream(); + var wr = new DataWriter(ms); + + for (int i = 0; i < 101; i++) + { + wr.Write(keys[i]); + } + + //fs.Close(); + using (var fs = new FileStream(fileName, FileMode.Create)) + { + ms.Position = 0; + ms.CopyTo(fs); + } + + } + + public static uint[][][] ReadNgTables(string fileName) + { + uint[][][] result; + + var fs = new FileStream(fileName, FileMode.Open); + var rd = new DataReader(fs); + + // 17 rounds... + result = new uint[17][][]; + for (int i = 0; i < 17; i++) + { + // 16 bytes... + result[i] = new uint[16][]; + for (int j = 0; j < 16; j++) + { + // 256 entries... + result[i][j] = new uint[256]; + for (int k = 0; k < 256; k++) + { + result[i][j][k] = rd.ReadUInt32(); + } + } + } + + fs.Close(); + + return result; + } + public static uint[][][] ReadNgTables(byte[] data) + { + uint[][][] result; + + var rd = new DataReader(new MemoryStream(data)); + + // 17 rounds... + result = new uint[17][][]; + for (int i = 0; i < 17; i++) + { + // 16 bytes... + result[i] = new uint[16][]; + for (int j = 0; j < 16; j++) + { + // 256 entries... + result[i][j] = new uint[256]; + for (int k = 0; k < 256; k++) + { + result[i][j][k] = rd.ReadUInt32(); + } + } + } + + return result; + } + + + + public static void WriteNgTables(string fileName, uint[][][] tableData) + { + //var fs = new FileStream(fileName, FileMode.Create); + //var wr = new DataWriter(fs); + var ms = new MemoryStream(); + var wr = new DataWriter(ms); + + // 17 rounds... + for (int i = 0; i < 17; i++) + { + // 16 bytes... + for (int j = 0; j < 16; j++) + { + // 256 entries... + for (int k = 0; k < 256; k++) + { + wr.Write(tableData[i][j][k]); + } + } + } + + //fs.Close(); + + using (var fs = new FileStream(fileName, FileMode.Create)) + { + ms.Position = 0; + ms.CopyTo(fs); + } + } + + public static GTA5NGLUT[][] ReadNgLuts(string fileName) + { + GTA5NGLUT[][] result; + + var fs = new FileStream(fileName, FileMode.Open); + var rd = new DataReader(fs); + + // 17 rounds... + result = new GTA5NGLUT[17][]; + for (int i = 0; i < 17; i++) + { + // 16 bytes... + result[i] = new GTA5NGLUT[16]; + for (int j = 0; j < 16; j++) + { + result[i][j] = new GTA5NGLUT(); + + // first compression step (2^32 -> 2^24) + result[i][j].LUT0 = new byte[256][]; + for (int k = 0; k < 256; k++) + { + //result[i][j].LUT0[k] = new byte[256]; + //for (int l = 0; l < 256; l++) + // result[i][j].LUT0[k][l] = rd.ReadByte(); + result[i][j].LUT0[k] = rd.ReadBytes(256); + } + + // second compression step (2^24 -> 2^16) + result[i][j].LUT1 = new byte[256][]; + for (int k = 0; k < 256; k++) + { + //result[i][j].LUT1[k] = new byte[256]; + //for (int l = 0; l < 256; l++) + // result[i][j].LUT1[k][l] = rd.ReadByte(); + result[i][j].LUT1[k] = rd.ReadBytes(256); + } + + // indices + //result[i][j].Indices = new byte[65536]; + //for (int k = 0; k < 65536; k++) + // result[i][j].Indices[k] = rd.ReadByte(); + result[i][j].Indices = rd.ReadBytes(65536); + } + } + + + fs.Close(); + + return result; + } + public static GTA5NGLUT[][] ReadNgLuts(byte[] data) + { + GTA5NGLUT[][] result; + + var rd = new DataReader(new MemoryStream(data)); + + // 17 rounds... + result = new GTA5NGLUT[17][]; + for (int i = 0; i < 17; i++) + { + // 16 bytes... + result[i] = new GTA5NGLUT[16]; + for (int j = 0; j < 16; j++) + { + result[i][j] = new GTA5NGLUT(); + + // first compression step (2^32 -> 2^24) + result[i][j].LUT0 = new byte[256][]; + for (int k = 0; k < 256; k++) + { + //result[i][j].LUT0[k] = new byte[256]; + //for (int l = 0; l < 256; l++) + // result[i][j].LUT0[k][l] = rd.ReadByte(); + result[i][j].LUT0[k] = rd.ReadBytes(256); + } + + // second compression step (2^24 -> 2^16) + result[i][j].LUT1 = new byte[256][]; + for (int k = 0; k < 256; k++) + { + //result[i][j].LUT1[k] = new byte[256]; + //for (int l = 0; l < 256; l++) + // result[i][j].LUT1[k][l] = rd.ReadByte(); + result[i][j].LUT1[k] = rd.ReadBytes(256); + } + + // indices + //result[i][j].Indices = new byte[65536]; + //for (int k = 0; k < 65536; k++) + // result[i][j].Indices[k] = rd.ReadByte(); + result[i][j].Indices = rd.ReadBytes(65536); + } + } + + + return result; + } + + public static void WriteLuts(string fileName, GTA5NGLUT[][] lutData) + { + //var fs = new FileStream(fileName, FileMode.Create); + //var wr = new DataWriter(fs); + var ms = new MemoryStream(); + var wr = new DataWriter(ms); + + // 17 rounds... + for (int i = 0; i < 17; i++) + { + // 16 bytes... + for (int j = 0; j < 16; j++) + { + GTA5NGLUT lut = lutData[i][j]; + + // first compression step (2^32 -> 2^24) + for (int k = 0; k < 256; k++) + for (int l = 0; l < 256; l++) + wr.Write(lut.LUT0[k][l]); + + // second compression step (2^24 -> 2^16) + for (int k = 0; k < 256; k++) + for (int l = 0; l < 256; l++) + wr.Write(lut.LUT1[k][l]); + + // indices + for (int k = 0; k < 65536; k++) + wr.Write(lut.Indices[k]); + } + } + + //fs.Close(); + + using (var fs = new FileStream(fileName, FileMode.Create)) + { + ms.Position = 0; + ms.CopyTo(fs); + } + } + } + + + + public class GTA5Hash + { + public static byte[] LUT; + + static GTA5Hash() + { + // setup constants... + LUT = GTA5Keys.PC_LUT; + } + + public static uint CalculateHash(string text) + { + /* + + func CalculateHash(keys Keys, filename string) (result uint32) { + for _, c := range filename { + temp := 1025 * (uint32(keys.hashLookup[int(c)]) + result) + result = (temp >> 6) ^ temp + } + return 32769 * (((9 * result) >> 11) ^ 9*result) + } + + */ + + + uint result = 0; + for (int index = 0; index < text.Length; index++) + { + var temp = 1025 * (LUT[text[index]] + result); + result = (temp >> 6) ^ temp; + } + + return 32769 * ((9 * result >> 11) ^ (9 * result)); + } + } + + +} diff --git a/GameFiles/Utils/Jenk.cs b/GameFiles/Utils/Jenk.cs new file mode 100644 index 0000000..e08e5b4 --- /dev/null +++ b/GameFiles/Utils/Jenk.cs @@ -0,0 +1,254 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.GameFiles +{ + + public class JenkHash + { + public JenkHashInputEncoding Encoding { get; set; } + public string Text { get; set; } + public int HashInt { get; set; } + public uint HashUint { get; set; } + public string HashHex { get; set; } + + public JenkHash(string text, JenkHashInputEncoding encoding) + { + Encoding = encoding; + Text = text; + HashUint = GenHash(text, encoding); + HashInt = (int)HashUint; + HashHex = "0x" + HashUint.ToString("X"); + } + + + public static uint GenHash(string text, JenkHashInputEncoding encoding) + { + uint h = 0; + byte[] chars; + + switch (encoding) + { + default: + case JenkHashInputEncoding.UTF8: + chars = UTF8Encoding.UTF8.GetBytes(text); + break; + case JenkHashInputEncoding.ASCII: + chars = ASCIIEncoding.ASCII.GetBytes(text); + break; + } + + for (uint i = 0; i < chars.Length; i++) + { + h += chars[i]; + h += (h << 10); + h ^= (h >> 6); + } + h += (h << 3); + h ^= (h >> 11); + h += (h << 15); + + return h; + } + + public static uint GenHash(string text) + { + uint h = 0; + for (int i = 0; i < text.Length; i++) + { + h += (byte)text[i]; + h += (h << 10); + h ^= (h >> 6); + } + h += (h << 3); + h ^= (h >> 11); + h += (h << 15); + + return h; + } + + public static uint GenHash(byte[] data) + { + uint h = 0; + for (uint i = 0; i < data.Length; i++) + { + h += data[i]; + h += (h << 10); + h ^= (h >> 6); + } + h += (h << 3); + h ^= (h >> 11); + h += (h << 15); + return h; + } + + } + + public enum JenkHashInputEncoding + { + UTF8 = 0, + ASCII = 1, + } + + + public class JenkIndMatch + { + public string Hash { get; set; } + public string Value { get; set; } + public double Score { get; set; } + + public JenkIndMatch(string hash, string val) + { + Hash = hash; + Value = val; + CalculateScore(); + } + + public void CalculateScore() + { + + int wordlength = 0; + int wordrank = 0; + + string okwordsymbs = " _-."; + string goodwordsymbs = "_"; + + for (int i = 0; i < Value.Length; i++) + { + char c = Value[i]; + + bool wordchar = (char.IsLetter(c) || char.IsDigit(c) || goodwordsymbs.Contains(c)); + + if (wordchar) + { + wordlength++; + } + else if (okwordsymbs.Contains(c)) + { + //wordlength++; //don't add this to the score, but allow it to continue the chain + } + else + { + if (wordlength > 2) + { + wordrank += wordlength; //linear word increment, ignoring 1-2char matches + } + wordlength = 0; + } + + //wordrank += wordlength; //each sequential letter in a word contributes more to the rank, ie. 1+2+3+4+... + } + if (wordlength > 2) + { + wordrank += wordlength; //linear word increment, ignoring 1-2char matches + } + + + if (Value.Length > 0) + { + //the max value for a given length when 1+2+3+4+5+..n = n(n+1)/2 + //double n = (double)Value.Length; + //double maxscore = n * (n + 1.0) * 0.5; + + double n = (double)Value.Length; + Score = (((double)wordrank) / n); + //Score = (((double)wordrank)); + } + else + { + Score = 0.0; + } + + } + + public override string ToString() + { + return string.Format("{0} -> {1} ({2:0.##})", Hash, Value, Score); + } + } + + public class JenkIndProblem + { + public string Filename { get; set; } + public string Excuse { get; set; } + public int Line { get; set; } + + public JenkIndProblem(string filepath, string excuse, int line) + { + Filename = Path.GetFileName(filepath); + Excuse = excuse; + Line = line; + } + public override string ToString() + { + return string.Format("{0} : {1} at line {2}", Filename, Excuse, Line); + } + } + + + + + + + + public static class JenkIndex + { + public static Dictionary Index = new Dictionary(); + private static object syncRoot = new object(); + + public static void Clear() + { + lock (syncRoot) + { + Index.Clear(); + } + } + + public static bool Ensure(string str) + { + uint hash = JenkHash.GenHash(str); + if (hash == 0) return true; + lock (syncRoot) + { + if (!Index.ContainsKey(hash)) + { + Index.Add(hash, str); + return false; + } + } + return true; + } + + public static string GetString(uint hash) + { + string res; + lock (syncRoot) + { + if (!Index.TryGetValue(hash, out res)) + { + res = hash.ToString(); + } + } + return res; + } + public static string TryGetString(uint hash) + { + string res; + lock (syncRoot) + { + if (!Index.TryGetValue(hash, out res)) + { + res = string.Empty; + } + } + return res; + } + + } + + +} diff --git a/JenkGenForm.Designer.cs b/JenkGenForm.Designer.cs new file mode 100644 index 0000000..c4fd48c --- /dev/null +++ b/JenkGenForm.Designer.cs @@ -0,0 +1,147 @@ +namespace CodeWalker +{ + partial class JenkGenForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(JenkGenForm)); + this.HashHexTextBox = new System.Windows.Forms.TextBox(); + this.HashUnsignedTextBox = new System.Windows.Forms.TextBox(); + this.UTF8RadioButton = new System.Windows.Forms.RadioButton(); + this.ASCIIRadioButton = new System.Windows.Forms.RadioButton(); + this.label2 = new System.Windows.Forms.Label(); + this.HashSignedTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.InputTextBox = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // HashHexTextBox + // + this.HashHexTextBox.Location = new System.Drawing.Point(303, 38); + this.HashHexTextBox.Name = "HashHexTextBox"; + this.HashHexTextBox.Size = new System.Drawing.Size(119, 20); + this.HashHexTextBox.TabIndex = 15; + // + // HashUnsignedTextBox + // + this.HashUnsignedTextBox.Location = new System.Drawing.Point(178, 38); + this.HashUnsignedTextBox.Name = "HashUnsignedTextBox"; + this.HashUnsignedTextBox.Size = new System.Drawing.Size(119, 20); + this.HashUnsignedTextBox.TabIndex = 14; + // + // UTF8RadioButton + // + this.UTF8RadioButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.UTF8RadioButton.AutoSize = true; + this.UTF8RadioButton.Checked = true; + this.UTF8RadioButton.Location = new System.Drawing.Point(303, 13); + this.UTF8RadioButton.Name = "UTF8RadioButton"; + this.UTF8RadioButton.Size = new System.Drawing.Size(55, 17); + this.UTF8RadioButton.TabIndex = 13; + this.UTF8RadioButton.TabStop = true; + this.UTF8RadioButton.Text = "UTF-8"; + this.UTF8RadioButton.UseVisualStyleBackColor = true; + // + // ASCIIRadioButton + // + this.ASCIIRadioButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ASCIIRadioButton.AutoSize = true; + this.ASCIIRadioButton.Location = new System.Drawing.Point(364, 13); + this.ASCIIRadioButton.Name = "ASCIIRadioButton"; + this.ASCIIRadioButton.Size = new System.Drawing.Size(52, 17); + this.ASCIIRadioButton.TabIndex = 12; + this.ASCIIRadioButton.Text = "ASCII"; + this.ASCIIRadioButton.UseVisualStyleBackColor = true; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 41); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(35, 13); + this.label2.TabIndex = 11; + this.label2.Text = "Hash:"; + // + // HashSignedTextBox + // + this.HashSignedTextBox.Location = new System.Drawing.Point(53, 38); + this.HashSignedTextBox.Name = "HashSignedTextBox"; + this.HashSignedTextBox.Size = new System.Drawing.Size(119, 20); + this.HashSignedTextBox.TabIndex = 10; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 15); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(34, 13); + this.label1.TabIndex = 9; + this.label1.Text = "Input:"; + // + // InputTextBox + // + this.InputTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.InputTextBox.Location = new System.Drawing.Point(52, 12); + this.InputTextBox.Name = "InputTextBox"; + this.InputTextBox.Size = new System.Drawing.Size(245, 20); + this.InputTextBox.TabIndex = 8; + this.InputTextBox.TextChanged += new System.EventHandler(this.InputTextBox_TextChanged); + // + // JenkGenForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(437, 73); + this.Controls.Add(this.HashHexTextBox); + this.Controls.Add(this.HashUnsignedTextBox); + this.Controls.Add(this.UTF8RadioButton); + this.Controls.Add(this.ASCIIRadioButton); + this.Controls.Add(this.label2); + this.Controls.Add(this.HashSignedTextBox); + this.Controls.Add(this.label1); + this.Controls.Add(this.InputTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "JenkGenForm"; + this.Text = "Jenkins Hash Generator - CodeWalker by dexyfex"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox HashHexTextBox; + private System.Windows.Forms.TextBox HashUnsignedTextBox; + private System.Windows.Forms.RadioButton UTF8RadioButton; + private System.Windows.Forms.RadioButton ASCIIRadioButton; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox HashSignedTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox InputTextBox; + } +} \ No newline at end of file diff --git a/JenkGenForm.cs b/JenkGenForm.cs new file mode 100644 index 0000000..f7291d9 --- /dev/null +++ b/JenkGenForm.cs @@ -0,0 +1,39 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class JenkGenForm : Form + { + public JenkGenForm() + { + InitializeComponent(); + } + + private void InputTextBox_TextChanged(object sender, EventArgs e) + { + GenerateHash(); + } + + private void GenerateHash() + { + JenkHashInputEncoding encoding = JenkHashInputEncoding.UTF8; + if (ASCIIRadioButton.Checked) encoding = JenkHashInputEncoding.ASCII; + + JenkHash h = new JenkHash(InputTextBox.Text, encoding); + + HashHexTextBox.Text = h.HashHex; + HashSignedTextBox.Text = h.HashInt.ToString(); + HashUnsignedTextBox.Text = h.HashUint.ToString(); + } + + } +} diff --git a/JenkGenForm.resx b/JenkGenForm.resx new file mode 100644 index 0000000..1431f6b --- /dev/null +++ b/JenkGenForm.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/JenkIndForm.Designer.cs b/JenkIndForm.Designer.cs new file mode 100644 index 0000000..808173d --- /dev/null +++ b/JenkIndForm.Designer.cs @@ -0,0 +1,190 @@ +namespace CodeWalker +{ + partial class JenkIndForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(JenkIndForm)); + this.label1 = new System.Windows.Forms.Label(); + this.HashTextBox = new System.Windows.Forms.TextBox(); + this.HexRadioButton = new System.Windows.Forms.RadioButton(); + this.UnsignedRadioButton = new System.Windows.Forms.RadioButton(); + this.SignedRadioButton = new System.Windows.Forms.RadioButton(); + this.MatchTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.label2 = new System.Windows.Forms.Label(); + this.StatusLabel = new System.Windows.Forms.Label(); + this.MainPanel = new System.Windows.Forms.Panel(); + this.LoadStringsButton = new System.Windows.Forms.Button(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.MainPanel.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(35, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Hash:"; + // + // HashTextBox + // + this.HashTextBox.Location = new System.Drawing.Point(44, 9); + this.HashTextBox.Name = "HashTextBox"; + this.HashTextBox.Size = new System.Drawing.Size(134, 20); + this.HashTextBox.TabIndex = 1; + this.HashTextBox.TextChanged += new System.EventHandler(this.HashTextBox_TextChanged); + // + // HexRadioButton + // + this.HexRadioButton.AutoSize = true; + this.HexRadioButton.Checked = true; + this.HexRadioButton.Location = new System.Drawing.Point(184, 10); + this.HexRadioButton.Name = "HexRadioButton"; + this.HexRadioButton.Size = new System.Drawing.Size(44, 17); + this.HexRadioButton.TabIndex = 2; + this.HexRadioButton.TabStop = true; + this.HexRadioButton.Text = "Hex"; + this.HexRadioButton.UseVisualStyleBackColor = true; + this.HexRadioButton.CheckedChanged += new System.EventHandler(this.HexRadioButton_CheckedChanged); + // + // UnsignedRadioButton + // + this.UnsignedRadioButton.AutoSize = true; + this.UnsignedRadioButton.Location = new System.Drawing.Point(234, 10); + this.UnsignedRadioButton.Name = "UnsignedRadioButton"; + this.UnsignedRadioButton.Size = new System.Drawing.Size(70, 17); + this.UnsignedRadioButton.TabIndex = 3; + this.UnsignedRadioButton.Text = "Unsigned"; + this.UnsignedRadioButton.UseVisualStyleBackColor = true; + this.UnsignedRadioButton.CheckedChanged += new System.EventHandler(this.UnsignedRadioButton_CheckedChanged); + // + // SignedRadioButton + // + this.SignedRadioButton.AutoSize = true; + this.SignedRadioButton.Location = new System.Drawing.Point(310, 10); + this.SignedRadioButton.Name = "SignedRadioButton"; + this.SignedRadioButton.Size = new System.Drawing.Size(58, 17); + this.SignedRadioButton.TabIndex = 4; + this.SignedRadioButton.Text = "Signed"; + this.SignedRadioButton.UseVisualStyleBackColor = true; + this.SignedRadioButton.CheckedChanged += new System.EventHandler(this.SignedRadioButton_CheckedChanged); + // + // MatchTextBox + // + this.MatchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MatchTextBox.Location = new System.Drawing.Point(44, 57); + this.MatchTextBox.Multiline = true; + this.MatchTextBox.Name = "MatchTextBox"; + this.MatchTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.MatchTextBox.Size = new System.Drawing.Size(472, 115); + this.MatchTextBox.TabIndex = 5; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 60); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(31, 13); + this.label2.TabIndex = 6; + this.label2.Text = "Text:"; + // + // StatusLabel + // + this.StatusLabel.AutoSize = true; + this.StatusLabel.Location = new System.Drawing.Point(41, 33); + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(10, 13); + this.StatusLabel.TabIndex = 7; + this.StatusLabel.Text = "-"; + // + // MainPanel + // + this.MainPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainPanel.Controls.Add(this.LoadStringsButton); + this.MainPanel.Controls.Add(this.HashTextBox); + this.MainPanel.Controls.Add(this.StatusLabel); + this.MainPanel.Controls.Add(this.label1); + this.MainPanel.Controls.Add(this.label2); + this.MainPanel.Controls.Add(this.HexRadioButton); + this.MainPanel.Controls.Add(this.MatchTextBox); + this.MainPanel.Controls.Add(this.UnsignedRadioButton); + this.MainPanel.Controls.Add(this.SignedRadioButton); + this.MainPanel.Location = new System.Drawing.Point(12, 12); + this.MainPanel.Name = "MainPanel"; + this.MainPanel.Size = new System.Drawing.Size(550, 200); + this.MainPanel.TabIndex = 8; + // + // LoadStringsButton + // + this.LoadStringsButton.Location = new System.Drawing.Point(410, 7); + this.LoadStringsButton.Name = "LoadStringsButton"; + this.LoadStringsButton.Size = new System.Drawing.Size(106, 23); + this.LoadStringsButton.TabIndex = 8; + this.LoadStringsButton.Text = "Load strings file..."; + this.LoadStringsButton.UseVisualStyleBackColor = true; + this.LoadStringsButton.Click += new System.EventHandler(this.LoadStringsButton_Click); + // + // OpenFileDialog + // + this.OpenFileDialog.Filter = "Text files|*.txt|All files|*.*"; + // + // JenkIndForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(574, 224); + this.Controls.Add(this.MainPanel); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "JenkIndForm"; + this.Text = "Jenkins Hash Lookup - CodeWalker by dexyfex"; + this.MainPanel.ResumeLayout(false); + this.MainPanel.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox HashTextBox; + private System.Windows.Forms.RadioButton HexRadioButton; + private System.Windows.Forms.RadioButton UnsignedRadioButton; + private System.Windows.Forms.RadioButton SignedRadioButton; + private WinForms.TextBoxFix MatchTextBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label StatusLabel; + private System.Windows.Forms.Panel MainPanel; + private System.Windows.Forms.Button LoadStringsButton; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + } +} \ No newline at end of file diff --git a/JenkIndForm.cs b/JenkIndForm.cs new file mode 100644 index 0000000..7728890 --- /dev/null +++ b/JenkIndForm.cs @@ -0,0 +1,246 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class JenkIndForm : Form + { + Dictionary extraStrings = new Dictionary(); + + + + public JenkIndForm(GameFileCache gameFileCache = null) + { + InitializeComponent(); + + if (GlobalText.FullIndexBuilt) + { + IndexBuildComplete(); + } + else + { + MainPanel.Enabled = false; + Cursor = Cursors.WaitCursor; + + if ((gameFileCache == null) || (gameFileCache.IsInited == false)) + { + Task.Run(() => + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); + GameFileCache gfc = new GameFileCache(); + gfc.DoFullStringIndex = true; + gfc.Init(UpdateStatus, UpdateStatus); + IndexBuildComplete(); + }); + } + else + { + Task.Run(() => + { + UpdateStatus("Loading strings..."); + gameFileCache.DoFullStringIndex = true; + gameFileCache.InitStringDicts(); + IndexBuildComplete(); + }); + } + } + + } + + + + + private void UpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { UpdateStatus(text); })); + } + else + { + StatusLabel.Text = text; + } + } + catch { } + } + private void IndexBuildComplete() + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { IndexBuildComplete(); })); + } + else + { + StatusLabel.Text = "Index built"; + MainPanel.Enabled = true; + Cursor = Cursors.Default; + } + } + catch { } + } + + + private void FindHash() + { + uint hash = 0; + string hashtxt = HashTextBox.Text; + MatchTextBox.Text = ""; + if (HexRadioButton.Checked) + { + try + { + hash = Convert.ToUInt32(hashtxt, 16); + } + catch + { + StatusLabel.Text = "Invalid hex value!"; + return; + } + } + else if (UnsignedRadioButton.Checked) + { + try + { + hash = uint.Parse(hashtxt); + } + catch + { + StatusLabel.Text = "Invalid unsigned int value!"; + return; + } + } + else if (SignedRadioButton.Checked) + { + try + { + hash = (uint)int.Parse(hashtxt); + } + catch + { + StatusLabel.Text = "Invalid signed int value!"; + return; + } + } + StatusLabel.Text = Convert.ToString(hash, 16).ToUpper().PadLeft(8, '0'); + + + var str = JenkIndex.TryGetString(hash); + var txt = GlobalText.TryGetString(hash); + var sta = StatsNames.TryGetString(hash); + var ext = TryGetExtraString(hash); + bool hasstr = !string.IsNullOrEmpty(str); + bool hastxt = !string.IsNullOrEmpty(txt); + bool hasext = !string.IsNullOrEmpty(ext); + bool hassta = !string.IsNullOrEmpty(sta); + + if (hasstr && hastxt) + { + MatchTextBox.Text = string.Format("JenkIndex match:\r\n{0}\r\nGlobalText match:\r\n{1}", str, txt); + } + else if (hasstr) + { + MatchTextBox.Text = str; + } + else if (hastxt) + { + MatchTextBox.Text = "GlobalText match:\r\n" + txt; + } + else if (hasext) + { + MatchTextBox.Text = "Extra strings match:\r\n" + ext; + } + else if (hassta) + { + MatchTextBox.Text = "Stats match:\r\n" + sta; + } + else + { + MatchTextBox.Text = "[No match found]"; + } + + + } + + + private string TryGetExtraString(uint hash) + { + string str; + extraStrings.TryGetValue(hash, out str); + return str; + } + + + private void HashTextBox_TextChanged(object sender, EventArgs e) + { + FindHash(); + } + + private void HexRadioButton_CheckedChanged(object sender, EventArgs e) + { + FindHash(); + } + + private void UnsignedRadioButton_CheckedChanged(object sender, EventArgs e) + { + FindHash(); + } + + private void SignedRadioButton_CheckedChanged(object sender, EventArgs e) + { + FindHash(); + } + + private void LoadStringsButton_Click(object sender, EventArgs e) + { + if (OpenFileDialog.ShowDialog(this) != DialogResult.OK) + { + return; + } + + string file = OpenFileDialog.FileName; + if (!File.Exists(file)) + { + return; + } + + try + { + string txt = File.ReadAllText(file); + string[] lines = txt.Split('\n'); + foreach (string line in lines) + { + string str = line.Trim(); + if (str.Length > 2) //remove double quotes from start and end, if both present... + { + if ((str[0] == '\"') && (str[str.Length - 1] == '\"')) + { + str = str.Substring(1, str.Length - 2); + } + } + var hash = JenkHash.GenHash(str); + extraStrings[hash] = str; + } + MessageBox.Show(lines.Length.ToString() + " strings imported successfully."); + } + catch + { + MessageBox.Show("Error reading file."); + } + + } + } +} diff --git a/JenkIndForm.resx b/JenkIndForm.resx new file mode 100644 index 0000000..b151cbe --- /dev/null +++ b/JenkIndForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/KeyBindForm.Designer.cs b/KeyBindForm.Designer.cs new file mode 100644 index 0000000..ec5ca77 --- /dev/null +++ b/KeyBindForm.Designer.cs @@ -0,0 +1,115 @@ +namespace CodeWalker +{ + partial class KeyBindForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(KeyBindForm)); + this.CancellButton = new System.Windows.Forms.Button(); + this.OkButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.KeyLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // CancellButton + // + this.CancellButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.CancellButton.Location = new System.Drawing.Point(150, 54); + this.CancellButton.Name = "CancellButton"; + this.CancellButton.Size = new System.Drawing.Size(75, 23); + this.CancellButton.TabIndex = 0; + this.CancellButton.TabStop = false; + this.CancellButton.Text = "Cancel"; + this.CancellButton.UseVisualStyleBackColor = true; + this.CancellButton.Click += new System.EventHandler(this.CancellButton_Click); + // + // OkButton + // + this.OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.OkButton.Enabled = false; + this.OkButton.Location = new System.Drawing.Point(69, 54); + this.OkButton.Name = "OkButton"; + this.OkButton.Size = new System.Drawing.Size(75, 23); + this.OkButton.TabIndex = 1; + this.OkButton.TabStop = false; + this.OkButton.Text = "Ok"; + this.OkButton.UseVisualStyleBackColor = true; + this.OkButton.Click += new System.EventHandler(this.OkButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(109, 13); + this.label1.TabIndex = 2; + this.label1.Text = "Press the key to bind:"; + // + // KeyLabel + // + this.KeyLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.KeyLabel.Location = new System.Drawing.Point(15, 31); + this.KeyLabel.Name = "KeyLabel"; + this.KeyLabel.Size = new System.Drawing.Size(204, 20); + this.KeyLabel.TabIndex = 3; + this.KeyLabel.Text = "-"; + this.KeyLabel.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // KeyBindForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(237, 89); + this.Controls.Add(this.KeyLabel); + this.Controls.Add(this.label1); + this.Controls.Add(this.OkButton); + this.Controls.Add(this.CancellButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.KeyPreview = true; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "KeyBindForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Bind Key - CodeWalker"; + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.KeyBindForm_KeyDown); + this.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.KeyBindForm_PreviewKeyDown); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button CancellButton; + private System.Windows.Forms.Button OkButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label KeyLabel; + } +} \ No newline at end of file diff --git a/KeyBindForm.cs b/KeyBindForm.cs new file mode 100644 index 0000000..dc33160 --- /dev/null +++ b/KeyBindForm.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class KeyBindForm : Form + { + private Keys _SelectedKey = Keys.None; + public Keys SelectedKey + { + get + { + return _SelectedKey; + } + set + { + _SelectedKey = value; + KeyLabel.Text = _SelectedKey.ToString(); + } + } + + + public KeyBindForm() + { + InitializeComponent(); + KeyLabel.Text = ""; + DialogResult = DialogResult.Cancel; + } + + private void KeyBindForm_KeyDown(object sender, KeyEventArgs e) + { + SelectedKey = e.KeyCode; + OkButton.Enabled = true; + e.Handled = true; + + } + + private void OkButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void CancellButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + private void KeyBindForm_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) + { + e.IsInputKey = true; + } + } +} diff --git a/KeyBindForm.resx b/KeyBindForm.resx new file mode 100644 index 0000000..1431f6b --- /dev/null +++ b/KeyBindForm.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/MainForm.Designer.cs b/MainForm.Designer.cs new file mode 100644 index 0000000..49d660a --- /dev/null +++ b/MainForm.Designer.cs @@ -0,0 +1,224 @@ +namespace CodeWalker +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.ExtractScriptsButton = new System.Windows.Forms.Button(); + this.BinarySearchButton = new System.Windows.Forms.Button(); + this.RPFBrowserButton = new System.Windows.Forms.Button(); + this.WorldButton = new System.Windows.Forms.Button(); + this.ExtractTexturesButton = new System.Windows.Forms.Button(); + this.GCCollectButton = new System.Windows.Forms.Button(); + this.ExtractRawFilesButton = new System.Windows.Forms.Button(); + this.ExtractShadersButton = new System.Windows.Forms.Button(); + this.AboutButton = new System.Windows.Forms.Button(); + this.JenkGenButton = new System.Windows.Forms.Button(); + this.ExtractKeysButton = new System.Windows.Forms.Button(); + this.ProjectButton = new System.Windows.Forms.Button(); + this.JenkIndButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // ExtractScriptsButton + // + this.ExtractScriptsButton.Location = new System.Drawing.Point(12, 41); + this.ExtractScriptsButton.Name = "ExtractScriptsButton"; + this.ExtractScriptsButton.Size = new System.Drawing.Size(108, 23); + this.ExtractScriptsButton.TabIndex = 2; + this.ExtractScriptsButton.Text = "Extract scripts..."; + this.ExtractScriptsButton.UseVisualStyleBackColor = true; + this.ExtractScriptsButton.Click += new System.EventHandler(this.ExtractScriptsButton_Click); + // + // BinarySearchButton + // + this.BinarySearchButton.Location = new System.Drawing.Point(12, 157); + this.BinarySearchButton.Name = "BinarySearchButton"; + this.BinarySearchButton.Size = new System.Drawing.Size(108, 23); + this.BinarySearchButton.TabIndex = 6; + this.BinarySearchButton.Text = "Binary search..."; + this.BinarySearchButton.UseVisualStyleBackColor = true; + this.BinarySearchButton.Click += new System.EventHandler(this.BinarySearchButton_Click); + // + // RPFBrowserButton + // + this.RPFBrowserButton.Location = new System.Drawing.Point(188, 12); + this.RPFBrowserButton.Name = "RPFBrowserButton"; + this.RPFBrowserButton.Size = new System.Drawing.Size(108, 23); + this.RPFBrowserButton.TabIndex = 0; + this.RPFBrowserButton.Text = "RPF Browser..."; + this.RPFBrowserButton.UseVisualStyleBackColor = true; + this.RPFBrowserButton.Click += new System.EventHandler(this.RPFBrowserButton_Click); + // + // WorldButton + // + this.WorldButton.Location = new System.Drawing.Point(12, 186); + this.WorldButton.Name = "WorldButton"; + this.WorldButton.Size = new System.Drawing.Size(108, 23); + this.WorldButton.TabIndex = 7; + this.WorldButton.Text = "World..."; + this.WorldButton.UseVisualStyleBackColor = true; + this.WorldButton.Click += new System.EventHandler(this.WorldButton_Click); + // + // ExtractTexturesButton + // + this.ExtractTexturesButton.Location = new System.Drawing.Point(12, 70); + this.ExtractTexturesButton.Name = "ExtractTexturesButton"; + this.ExtractTexturesButton.Size = new System.Drawing.Size(108, 23); + this.ExtractTexturesButton.TabIndex = 3; + this.ExtractTexturesButton.Text = "Extract textures..."; + this.ExtractTexturesButton.UseVisualStyleBackColor = true; + this.ExtractTexturesButton.Click += new System.EventHandler(this.ExtractTexturesButton_Click); + // + // GCCollectButton + // + this.GCCollectButton.Location = new System.Drawing.Point(188, 157); + this.GCCollectButton.Name = "GCCollectButton"; + this.GCCollectButton.Size = new System.Drawing.Size(108, 23); + this.GCCollectButton.TabIndex = 10; + this.GCCollectButton.Text = "GC Collect"; + this.GCCollectButton.UseVisualStyleBackColor = true; + this.GCCollectButton.Click += new System.EventHandler(this.GCCollectButton_Click); + // + // ExtractRawFilesButton + // + this.ExtractRawFilesButton.Location = new System.Drawing.Point(12, 99); + this.ExtractRawFilesButton.Name = "ExtractRawFilesButton"; + this.ExtractRawFilesButton.Size = new System.Drawing.Size(108, 23); + this.ExtractRawFilesButton.TabIndex = 4; + this.ExtractRawFilesButton.Text = "Extract raw files..."; + this.ExtractRawFilesButton.UseVisualStyleBackColor = true; + this.ExtractRawFilesButton.Click += new System.EventHandler(this.ExtractRawFilesButton_Click); + // + // ExtractShadersButton + // + this.ExtractShadersButton.Location = new System.Drawing.Point(12, 128); + this.ExtractShadersButton.Name = "ExtractShadersButton"; + this.ExtractShadersButton.Size = new System.Drawing.Size(108, 23); + this.ExtractShadersButton.TabIndex = 5; + this.ExtractShadersButton.Text = "Extract shaders..."; + this.ExtractShadersButton.UseVisualStyleBackColor = true; + this.ExtractShadersButton.Click += new System.EventHandler(this.ExtractShadersButton_Click); + // + // AboutButton + // + this.AboutButton.Location = new System.Drawing.Point(188, 215); + this.AboutButton.Name = "AboutButton"; + this.AboutButton.Size = new System.Drawing.Size(108, 23); + this.AboutButton.TabIndex = 9; + this.AboutButton.Text = "About..."; + this.AboutButton.UseVisualStyleBackColor = true; + this.AboutButton.Click += new System.EventHandler(this.AboutButton_Click); + // + // JenkGenButton + // + this.JenkGenButton.Location = new System.Drawing.Point(188, 70); + this.JenkGenButton.Name = "JenkGenButton"; + this.JenkGenButton.Size = new System.Drawing.Size(108, 23); + this.JenkGenButton.TabIndex = 12; + this.JenkGenButton.Text = "JenkGen..."; + this.JenkGenButton.UseVisualStyleBackColor = true; + this.JenkGenButton.Click += new System.EventHandler(this.JenkGenButton_Click); + // + // ExtractKeysButton + // + this.ExtractKeysButton.Location = new System.Drawing.Point(12, 12); + this.ExtractKeysButton.Name = "ExtractKeysButton"; + this.ExtractKeysButton.Size = new System.Drawing.Size(108, 23); + this.ExtractKeysButton.TabIndex = 1; + this.ExtractKeysButton.Text = "Extract keys..."; + this.ExtractKeysButton.UseVisualStyleBackColor = true; + this.ExtractKeysButton.Click += new System.EventHandler(this.ExtractKeysButton_Click); + // + // ProjectButton + // + this.ProjectButton.Location = new System.Drawing.Point(12, 215); + this.ProjectButton.Name = "ProjectButton"; + this.ProjectButton.Size = new System.Drawing.Size(108, 23); + this.ProjectButton.TabIndex = 8; + this.ProjectButton.Text = "Project..."; + this.ProjectButton.UseVisualStyleBackColor = true; + this.ProjectButton.Click += new System.EventHandler(this.ProjectButton_Click); + // + // JenkIndButton + // + this.JenkIndButton.Location = new System.Drawing.Point(188, 99); + this.JenkIndButton.Name = "JenkIndButton"; + this.JenkIndButton.Size = new System.Drawing.Size(108, 23); + this.JenkIndButton.TabIndex = 11; + this.JenkIndButton.Text = "JenkInd..."; + this.JenkIndButton.UseVisualStyleBackColor = true; + this.JenkIndButton.Click += new System.EventHandler(this.JenkIndButton_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(308, 250); + this.Controls.Add(this.JenkIndButton); + this.Controls.Add(this.ProjectButton); + this.Controls.Add(this.ExtractKeysButton); + this.Controls.Add(this.JenkGenButton); + this.Controls.Add(this.AboutButton); + this.Controls.Add(this.ExtractShadersButton); + this.Controls.Add(this.ExtractRawFilesButton); + this.Controls.Add(this.GCCollectButton); + this.Controls.Add(this.ExtractTexturesButton); + this.Controls.Add(this.WorldButton); + this.Controls.Add(this.RPFBrowserButton); + this.Controls.Add(this.BinarySearchButton); + this.Controls.Add(this.ExtractScriptsButton); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "MainForm"; + this.Text = "CodeWalker Menu"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed); + this.Load += new System.EventHandler(this.MainForm_Load); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + private System.Windows.Forms.Button ExtractScriptsButton; + private System.Windows.Forms.Button BinarySearchButton; + private System.Windows.Forms.Button RPFBrowserButton; + private System.Windows.Forms.Button WorldButton; + private System.Windows.Forms.Button ExtractTexturesButton; + private System.Windows.Forms.Button GCCollectButton; + private System.Windows.Forms.Button ExtractRawFilesButton; + private System.Windows.Forms.Button ExtractShadersButton; + private System.Windows.Forms.Button AboutButton; + private System.Windows.Forms.Button JenkGenButton; + private System.Windows.Forms.Button ExtractKeysButton; + private System.Windows.Forms.Button ProjectButton; + private System.Windows.Forms.Button JenkIndButton; + } +} + diff --git a/MainForm.cs b/MainForm.cs new file mode 100644 index 0000000..49136ae --- /dev/null +++ b/MainForm.cs @@ -0,0 +1,138 @@ +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class MainForm : Form + { + private volatile bool worldFormOpen = false; + private WorldForm worldForm = null; + + public MainForm() + { + InitializeComponent(); + } + + private void MainForm_Load(object sender, EventArgs e) + { + } + + private void MainForm_FormClosed(object sender, FormClosedEventArgs e) + { + Settings.Default.Save(); + } + + private void RPFBrowserButton_Click(object sender, EventArgs e) + { + BrowseForm f = new BrowseForm(); + f.Show(this); + } + + private void ExtractScriptsButton_Click(object sender, EventArgs e) + { + ExtractScriptsForm f = new ExtractScriptsForm(); + f.Show(this); + } + + private void ExtractTexturesButton_Click(object sender, EventArgs e) + { + ExtractTexForm f = new ExtractTexForm(); + f.Show(this); + } + + private void ExtractRawFilesButton_Click(object sender, EventArgs e) + { + ExtractRawForm f = new ExtractRawForm(); + f.Show(this); + } + + private void ExtractShadersButton_Click(object sender, EventArgs e) + { + ExtractShadersForm f = new ExtractShadersForm(); + f.Show(this); + } + + private void BinarySearchButton_Click(object sender, EventArgs e) + { + BinarySearchForm f = new BinarySearchForm(); + f.Show(this); + } + + private void WorldButton_Click(object sender, EventArgs e) + { + if (worldFormOpen) + { + //MessageBox.Show("Can only open one world view at a time."); + if (worldForm != null) + { + worldForm.Invoke(new Action(() => { worldForm.Focus(); })); + } + return; + } + + Thread thread = new Thread(new ThreadStart(() => { + try + { + worldFormOpen = true; + using (WorldForm f = new WorldForm()) + { + worldForm = f; + f.ShowDialog(); + worldForm = null; + } + worldFormOpen = false; + } + catch + { + worldFormOpen = false; + } + })); + thread.Start(); + } + + private void GCCollectButton_Click(object sender, EventArgs e) + { + GC.Collect(); + } + + private void AboutButton_Click(object sender, EventArgs e) + { + AboutForm f = new AboutForm(); + f.Show(this); + } + + private void JenkGenButton_Click(object sender, EventArgs e) + { + JenkGenForm f = new JenkGenForm(); + f.Show(this); + } + + private void JenkIndButton_Click(object sender, EventArgs e) + { + JenkIndForm f = new JenkIndForm(); + f.Show(this); + } + + private void ExtractKeysButton_Click(object sender, EventArgs e) + { + ExtractKeysForm f = new ExtractKeysForm(); + f.Show(this); + } + + private void ProjectButton_Click(object sender, EventArgs e) + { + ProjectForm f = new ProjectForm(null); + f.Show(this); + } + } +} diff --git a/MainForm.resx b/MainForm.resx new file mode 100644 index 0000000..a662b38 --- /dev/null +++ b/MainForm.resx @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 182, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2OL+NjZ7AAArX2Ok + 4uz/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 2eP/LjJ1DAxKfYTE4Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//v7//f7//f7//v7//v// + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3OX/gILIR0eVeoHC3eb/8fX/+/z/AAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+Pr/ + +Pr/+Pr/+vv//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3/+vv/+vv/+/z//f3//v7/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8PX/2eP9ZWeqHx1obnOz4Or/8fX/+/z/AAAAAAAAAAAAAAAA/v7/ + +/z/9fj/8vb/8PX/7vT/8fb/9fj/+fr//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///P3/+Pr/9fj/9fj/9Pj/9Pf/9vn/+/z//v7/ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP9ODp9AAA5jZDQ5O7/8PX/+/z/AAAA + AAAAAAAA/v7/+/z/9Pf/7fP/5u//wsz6j5XfuMDx7fL/9vn//P3/AAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f7/+Pr/8/b/5+3/2eH/2uP/ + 5u3/7fP/8/b/+vv//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8PX/3ef/U1ebBgVKio/O + 4uz/8fX/+/z/AAAAAAAA/v///P3/9fj/7fP/4uv/hIzZHSWPAABmU1i14ub/9/r/+/z/AAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P3/9Pf/ + 7/X/09z/TlSzNzWYj5bh5O7/6/L/8vb/+fv//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fX/ + 2eP/QUWIEhBZbnSz3uj/8fb/+/z/AAAAAAAA/f7/+Pr/7/T/6PH/iI7cAABvAABqAABncXjK6O//9fj/ + +/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+/z/8/f/2uD/Z27EAABnAABiBgl4jJTd5vD/6O//8vX/+fv//f7/AAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8fb/2OP/Mjd6AQE6ZGup4er/8fX/+/z/AAAAAAAA+vz/8fX/6/T/xM/8ExyJAABwAABu + GySRxc387fT/9ff//P3/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vz/8/f/1Nr/MzqhAABhAxOBAARyBgp5jpLg5Oz/7PP/9Pf/+vz//v7/ + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP/KCtvBwZOjJHS4Or/8fX/+/z/AAAA/f7/9/n/7fP/3+j/ + UFq3AABtAAZ3BAh6mZ/n5vD/7vP/+Pr//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/6e//sbb1KzWcAABwBhaBAAFyAgp6fITR + 1d777/T/+Pr//f7/AAAAAAAAAAAAAAAAAAAAAAAA+vv/8PX/3+j/WF2hBglTnaTj5O3/8PX/+/z/AAAA + /P3/9Pf/6vL/k5riAAByAAR0AABrY2vE4ur/6vH/9ff//P3/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/9/n/7fL/5O3/ytX/RU6w + AABpAA5+AABuAABnhord6e7/+fv//f7/AAAAAAAAAAAAAAAAAAAAAAAA+vv/7/T/3+j/k5jbT1KdgYjJ + 3uf+8fX/+/z/AAAA+/z/9fn/4ef/NDqhAABnAABrJjCU0Nn/5/D/8fX/+vv//v7/AAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7/+/z/ + 9vn/7vP/6vP/ztb/O0CmAABpAABrQkuoxMn57PH/+Pr//f7/AAAAAAAAAAAAAAAAAAAAAAAA+vv/8PX/ + 2+X/en/CUFGak5nY3+j/8fX//P3/AAAA/P3/9fj/4en/i5DbNT2hIyuTpqzv4uz/7vP/9/n//f7/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAA/v7//P3/9vn/7/P/6vL/ytH/X2i9XWi7wsf/6e//8/f/+Pr//v7/AAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3OX/WF2hW1ylvMD+3uf/8PX/+/z/AAAA/f7/9vn/7fP/4uj/j5Pgf4LV3+X/6fD/ + 9Pf//P3/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///P3/+Pr/8vX/7fP/5+//5u7/6vD/8PT/9vn//P3//v7/ + AAAAAAAAAAAAAAAAAAAA/f7/9/n/7fP/0tz9LDJzNjh/nqTk2uT/7fL/9/n//f7//f7/+fv/8/b/7PL/ + 3eX/zM//5ev/9fj/+fv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///f3/+vv/9/n/9vn/9fj/9vn/ + +fr//P3//v7/AAAAAAAAAAAA/v///f7/+vv/9vn/7/T/5vD/2Ob/VFubERNdoajk4u//5O7/7vP/9vj/ + +fr/+vv/+Pr/9fj/9Pj/9fj/9fj/+Pr//P3/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///v7/ + /f7//P3//P3//f3//v7//v//AAAAAAAAAAAA/f7/+vz/9vn/8fX/7vT/5O3/3eb/z9n/cHjICxN5d37L + z9n/2eP/5O3/6/L/8PT/9Pf/9/n/+vv/+vv/+/z//P3//f3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P3/+Pr/8/b/7vT/6vL/z9r+jZjeQUeq + IiuQCBN3AAFrBRB8Nj2iUViym6XlydH/4+z/6/L/8PT/9/n/+/z//f7//v//AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/9/n/8fX/6/L/3uf/ + mKTkLzibAABoAAB0Fx+HDBh7FSGDAg16AABYAABlCBB/Ji2UhYza1+D/6PL/7fL/9Pf/+vv//f7/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/9/n/ + 8PT/7PT/z9j/XmO+AABtAABcMDSXoajsu8X7VV+5hYzblZ/fTVSxFSKMAABkAABnAAN2Qkmpsbrz5e3/ + 6vH/8fX/+Pr//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAA/P3/9/n/8PX/7PT/vcn3LTOZAABaAgR1ZWzD0Nf/5vL/1OP/l53lzs3/6fP/4+7/sLzwZ23CBxSD + AABnAABlHiaSmqHo3+j/5+//7/T/9vn//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAA/v//AAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7/ + /v7//v7//v7//f7/+/z/9vj/7vP/7PX/tcLzEBeGAABkPEWlqLPt2eX/4e7/3On/uMX1gofVe3vPhYzY + z93+5/X/4e3/lJ3gHiOPAABtAABqChiEbHLIytD/5/D/7PL/8/f/+Pr/+fr/+Pr/+Pr/+Pr/+Pr/+Pr/ + +Pr/+fv/+vv/+/z//f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+fv/9/n/9vj/9fj/9Pf/8fX/7PL/4uv/l6HgDhF7AAN4iZDe0d7/3uz/4vD/w83/VVm3 + ICiSAAFyAABlAABwaHTD1N//2un/3er/w838ZW3BEyOJJzKVAQ16NDmfwsn75fD/5u7/7PL/7vP/7fP/ + 7fP/7fL/7fP/7vP/7/T/8fb/9Pj/9vn/+fr//f3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAA/v7//P3/+Pr/9Pf/8fX/7vT/7PL/6/L/6fH/5u7/6vX/tsD0CQx4AAFwkZvi7ff/4vD/ + 4fD/z9j/OkGlAABiAABwBxWAAAt7BBN+P0uofYLUztb/4O7/6fb/6fP/qa7xQkyoBg56AABqMjugx8/+ + 5fH/4Ov/4On/3uj/3eb/3+j/3uj/1+L/0d3/1d7/3+f/7fL/9vj/+vz//v7/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/f7/+fr/8/f/6/L/2d//v8j6vcf5ucP1wMv8wM3+vMj6PkqoAABo + UF25usP7tsPyvsr6sLrwQ0utAABqAAV1OUameIDRKDWZAAd2GyeOLDecmaHntsL0pbLom6riq7LzUlu0 + AANzBhR/AAZ0NT+ja3bBY2i/XGG6UViyWl65XGG7XGC6TVWvQU6pPkalODygqK7p8vb/+vz//v7/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P3/9/n/7/T/wcj2R0ysExeFERmGDxuIFB6K + FBqICxSEAABsAAByDBiDCRSBBRCADhaFCRODAAh4AxF/AAl4CxeDHSaPAAp6AAN0AA19AAd3CBOBEBqH + BhGBAAh5AABwAAByAAh5BhSCAxWCAABsAABvAABlAABnAABxAABjAABmAABhAABdAABYAABhCAt/q7Lr + 8/f/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P3/+fv/3uT/SE2vAABn + CBB/GiCMLzmfLTWcGByJFRyKGCOOMj2gHymRDxiGGyOPLDCXBRF/AAh3BhaCEyKMICqTKC2WNDqfIzCV + Awx6Eh+JHiaPAAR3AAZ5CxSDICWQX2q7Q1CqAA1+AAFxDxuHiZTbVGC4dHnQnabrTVqzY23EUV62Slau + LjaZXWm9sLjz5ez/9vn/+fv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P3/ + +Pv/4+n+e4LPfoPVpqv2vsf/zNX/zdb/xtH/v8v8pK7spKfysLb3vcr4ws784ej/hI/YAAZ1AAJzVF25 + yM//3Of/5+//i5LcAABpMzyfp6vxoKznlqHhqbbtx9H/8fz/kpvfAABiAABph4zc5PD/2OP/193/3un/ + 1+D/2OH/1+D/0Nr/zNL/3+j/6/L/7/T/9vn//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAA/f7/+Pr/9Pf/6vD/5u3/3+b/4uv/6PD/5+//5O3/5/P/sL3sXmS7mZzoz9f/3+z/4e// + mKLiEiKKCBF/KTWZr7T06/f/3ev/VF2zChSBipPcz9v+4u7/3ur/3ev/5/X/qrPrISmSDRJ2Xmq/3ur/ + 4uv/6vH/7fP/7fL/7/T/7vP/7fP/7fP/8PX/8fX/9Pf/+Pr/+/z//v7/AAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+Pr/9vn/9Pf/8vb/8vb/8/b/9Pf/7/T/6/L/tL/ubXLH + en/Ti43gqavy0t3/nafjMj6fJzaaAAV1GyeOYmW7Nz6fAABgNj6i1N//3uz/2uX/3Oj/5PH/wcj7FR2J + AAN0gong0tr/6fH/7/P/9vj/+Pr/+fv/+fv/+Pr/+Pr/+Pr/+fv/+vv//P3//f7//v//AAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3/+/z/+/z/+/z//f3//f7/ + +fv/8fX/5Oz/jpbfc3jObnXLcXfOk5rks7b4iY3dR1KvDhuEAABoAABlEBV9U12ytcD13Or/3en/3ej/ + 1eL/q7fvGR+MKDKZbnnNxc/76PD/8fX/+fr//f7//v//AAAA/v7//f7//f3//P3//f3//f7//v//AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//f7//v7/AAAA + AAAAAAAAAAAAAAAA/f7/9vn/7/T/yNH5lJrleoDVmZ3pmpzpc3nPfoTWf4bYVFy3HSaLZ3PGsrb8v8r8 + y9n9q7jre4LRf4fUgIvXAwZ1AABrhYjb0NX/6PH/8PX/+Pr//f7/AAAAAAAA/v///f3/+vv/+Pr/9/r/ + 9/n/+Pr/+/z//f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///f7/+/z/+fr/9vj/9/n/ + +vz/+vv/+/z//v7/AAAAAAAAAAAAAAAA/v7/+vz/8/f/7PL/2uT/t8H1srP6vcH+nKTnSlOxV2C7TVaz + WGS8QUqmSlSuSFOtR1GtbXTKVl23ARB5AAh2AABnd33P3eP/4ur/7/T/9/n//P3/AAAAAAAAAAAA/P3/ + 9/n/8vb/7PH/6fD/7PL/7vP/8vb/9vn/+/z//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7/+/z/+Pr/ + 8/b/7/T/8Pb/6vH/3eP97vL++fr//P3/AAAAAAAAAAAAAAAAAAAA/f7/+vv/9fj/7/T/5+//z9f+t7v4 + uLn9Z2zFLzucFCGIMz6gGCCMAAd4AAl2Dx2EER+GXWK8c3XLKzKXd4LP4er/6/L/8PX/9/n//P3//v// + AAAAAAAA/v7/+fv/8/b/7PP/y9H/i4/erLbt4er/5e3/7fP/8/b/+fv//f3//v7/AAAAAAAAAAAAAAAA + /v7/+/z/9vj/8PT/6/L/3+n/x9H9aHTAZGvG3+b9+Pr/+/z/AAAAAAAAAAAAAAAAAAAAAAAA/v7/+/z/ + +Pr/8vb/6/H/3OX+wMn4maDmdHrPWGG6T1a1eoHWcHfOTlayUlq1SlKubHjAxMj/0dn/4+v/7PL/8vb/ + +Pr//P3//v7/AAAAAAAAAAAA/f7/+fr/7vP/xsv5YGXAHymRKjKYYWS9rbLz4u3/6/P/8vb/+fr//f7/ + AAAAAAAAAAAA/v//+/z/9vj/7fL/5e3/xs7/Y23BIiiSAABeLTab3+b/9/r/+/z/AAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAA/f7/+vz/9vj/8PX/6vH/3eb/ydL8xM/6uMPyt733w8j/zNb/1Nz/3OT/4uz/5u7/ + 7fP/8vb/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAA/f7/+fv/7vP/jpHiAAJ1CxaBER6GAABoFRmGbXbH + 0Nf/7PL/9fj//P3/AAAAAAAAAAAA/v7/+fv/8/f/4Of/hYvbKDGZAABuAABdAAZyi5La5+7/9vn/+/z/ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/9ff/8vb/7/X/7fP/6/L/5u3/5ez/6fD/ + 7PP/7/T/8fX/9Pf/9/n/+vv//P3//v7//v//AAAAAAAAAAAAAAAAAAAA/v7/+fv/8fb/2eH9fIbQExqH + AABrAAp6AAFyAABwS0+uztX39vn/+vz/AAAAAAAAAAAA/f7/+Pr/8ff/qbLpAABrAABhAABwDBWAfobX + 5e3/8PX/9vn//f3/AAAAAAAA/v///f7/+/z/+vv/+vv/+vz//P3//v7//v///v7//P3/+vz/+Pr/9/n/ + 9vj/9vj/9vj/9vj/9/n/+fr/+/z//P3//f7//v7//f7//P3/+/z/+vz/+/z//P3//v7/AAAA/v7/+/z/ + 9fj/7/T/5/H/uML1U1e1AAh5AABuAABvMjmdv8bz9vr/+vv/AAAAAAAAAAAA/f7/+fv/7/T/iY7aDxSA + GiONa3XHsr7w4Oj/6/H/9Pf/+vz//v7/AAAA/v///P3/+Pr/9Pf/8/f/9fj/9fj/9vn/+/z//v7/AAAA + AAAAAAAA/v7//f7//P3/+/z/+/z//P3//f7//v//AAAAAAAAAAAA/v7/+/z/9/n/9vn/9vn/9Pj/9vn/ + +/z//v7/AAAA/f7/+vz/9fj/7/T/6vL/3ef/i5PbGRqJBQl5jJbZ6vH/9Pj/+/z/AAAAAAAAAAAA/f7/ + +fv/8fT/1Nn9t7/0wcr54er/7fT/8fX/9fj/+vv//f7/AAAAAAAA/f3/+Pr/8PT/6/L/3uX/ztb/5Or/ + 8/f/+Pr//f7/AAAAAAAAAAAA/f7/+vz/+Pr/+fv/+fv/+vv//f3//v//AAAAAAAAAAAA/P3/9/n/7vL/ + 193/ztf/5u3/7vP/9Pf/+/z//v7/AAAA/v7//P3/+Pr/8fX/7PP/5/D/sLfxoKnk4+r/8vf/9/n//f3/ + AAAAAAAAAAAA/v7/+/z/9vn/9Pf/8vb/8fb/8fX/9Pf/+Pr//P3//v7/AAAAAAAA/v7/+vv/8vb/5+7/ + y9H/WWO9KSmSkZXj6vD/+Pv//P3/AAAAAAAA/f7/+Pr/9fj/8vb/6O7/7vP/9fj/+Pr//f7/AAAAAAAA + /v//+vv/8vb/7PP/hYraKiqKlp7i6PD/7fP/9ff/+/z//v7/AAAAAAAA/f7/+vv/9ff/8fX/8PX/8vb/ + 8/f/9vn/+/z//v7/AAAAAAAAAAAAAAAA/f7/+/z/+vv/+fr/+fr/+vv//P3//v7/AAAAAAAAAAAAAAAA + /P3/9fj/7PL/1d7/RUysAABhAABlg4ja6/D/+Pr//P3/AAAAAAAA+/z/9fj/6e7/2eD/h4/bnaXg7PH/ + 9fj/+/z/AAAAAAAA/v7/+Pr/8PX/y9X1JDGVAABaERWDoKnp6PH/7vP/9/n//P3/AAAAAAAAAAAA/v7/ + /P3/+vv/+fv/+fv/+vv//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAA/v7//v7//v7//v7//v//AAAAAAAA + AAAAAAAAAAAA/v7/+fv/8PX/7PX/ipPdAABsAABlQ1Cp3Ob/7vP/9/n//f7/AAAAAAAA+fv/9Pj/yNH5 + Ule2DBJ8Ljie0df+8fb/+fv//v7/AAAA/v7/+Pr/7/X/hY3YAABxAAl7AABuEBaEs7nz6fH/8fX/+vv/ + /v7/AAAAAAAAAAAAAAAA/v///v7//v7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/9vn/7PL/0tn/LzidAQFsAAB0iZHb6vP/8PT/+fv//v//AAAA + /v7/+Pr/8vf/r7rqAAV4AABdPUen1N//7PL/9vn//f7/AAAA/v7/+fr/7/T/yc75S1G0AABrARKAAABp + Qker0df/7fP/9/n//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P3/9/n/5+7/cXXNAAd2AABuMDebzdT97PL/ + 9vj//P3/AAAAAAAA/v7/9/n/7/X/tL/uFCCLAABqHSqRvcf46fD/9Pf//f3/AAAAAAAA+vv/8vX/6vH/ + yM3+JC2XAABtAAV2Agx9q7Ly7vT/9vn//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/4uj/WWO1AAVx + KTaYu8T07fT/8vb/+vv//v7/AAAAAAAA/v7/9/n/7vX/vsn1Iy2SAABrAQ99mp/o6PD/9Pf//P3/AAAA + AAAA/P3/9/n/7vP/6fL/s7z2DBB/AABeQ0uttrr56e7/+Pr//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/P3/ + +fv/4ef6g4zNbXfFw8v27fT/8vb/+Pr//f3/AAAAAAAAAAAA/v7/9/n/7vT/yNL7MjucAABtBxF/nKLo + 6fH/9Pf//P3/AAAAAAAA/v7/+/z/9fj/7fL/6/T/jZXbLzScrrP14en/7fL/+fv//v7/AAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAA/f7/+vz/8PP91dr34+f/8vb/8/f/9/r//P3//v//AAAAAAAAAAAA/v7/+Pr/8PX/1N3/ + QUqmAQRxBQ98m6Dm7PL/9fj//P3/AAAAAAAAAAAA/v7/+/z/9ff/8PX/5ez/ytH94ej/8vb/9vj/+/z/ + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/MapForm.Designer.cs b/MapForm.Designer.cs new file mode 100644 index 0000000..6aeb6af --- /dev/null +++ b/MapForm.Designer.cs @@ -0,0 +1,847 @@ +namespace CodeWalker +{ + partial class MapForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MapForm)); + this.MapComboBox = new System.Windows.Forms.ComboBox(); + this.LoadingLabel = new System.Windows.Forms.Label(); + this.MainPanel = new System.Windows.Forms.Panel(); + this.MainPanelHideButton = new System.Windows.Forms.Button(); + this.MainTabControl = new System.Windows.Forms.TabControl(); + this.ToolsTabPage = new System.Windows.Forms.TabPage(); + this.ResetMarkersButton = new System.Windows.Forms.Button(); + this.ClearMarkersButton = new System.Windows.Forms.Button(); + this.GoToButton = new System.Windows.Forms.Button(); + this.LocatorStatusLabel = new System.Windows.Forms.Label(); + this.ShowLocatorCheckBox = new System.Windows.Forms.CheckBox(); + this.label5 = new System.Windows.Forms.Label(); + this.LocateTextBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.AddMarkersButton = new System.Windows.Forms.Button(); + this.MultiFindTextBox = new System.Windows.Forms.TextBox(); + this.MarkersTabPage = new System.Windows.Forms.TabPage(); + this.GoToSelectedMarkerButton = new System.Windows.Forms.Button(); + this.CopyMarkersButton = new System.Windows.Forms.Button(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.MarkersListView = new System.Windows.Forms.ListView(); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.OptionsTabPage = new System.Windows.Forms.TabPage(); + this.LocatorStyleComboBox = new System.Windows.Forms.ComboBox(); + this.label6 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.SmoothingUpDown = new System.Windows.Forms.NumericUpDown(); + this.label2 = new System.Windows.Forms.Label(); + this.ZoomSpeedUpDown = new System.Windows.Forms.NumericUpDown(); + this.MarkerStyleComboBox = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.CalibrateTabPage = new System.Windows.Forms.TabPage(); + this.label11 = new System.Windows.Forms.Label(); + this.UnitsPerTexelYTextBox = new System.Windows.Forms.TextBox(); + this.CalibrationErrorLabel = new System.Windows.Forms.Label(); + this.CalibrateButton = new System.Windows.Forms.Button(); + this.CalibrationPointsTextBox = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.SetCoordButton = new System.Windows.Forms.Button(); + this.label12 = new System.Windows.Forms.Label(); + this.WorldCoordTextBox = new System.Windows.Forms.TextBox(); + this.TextureFileLabel = new System.Windows.Forms.Label(); + this.TextureNameLabel = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.UnitsPerTexelXTextBox = new System.Windows.Forms.TextBox(); + this.SetOriginButton = new System.Windows.Forms.Button(); + this.label8 = new System.Windows.Forms.Label(); + this.TextureOriginTextBox = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.TextureCoordTextBox = new System.Windows.Forms.TextBox(); + this.MainPanelShowButton = new System.Windows.Forms.Button(); + this.SelectionPanel = new System.Windows.Forms.Panel(); + this.SelectionPositionTextBox = new System.Windows.Forms.TextBox(); + this.SelectionNameTextBox = new System.Windows.Forms.TextBox(); + this.MainPanel.SuspendLayout(); + this.MainTabControl.SuspendLayout(); + this.ToolsTabPage.SuspendLayout(); + this.MarkersTabPage.SuspendLayout(); + this.OptionsTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.SmoothingUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ZoomSpeedUpDown)).BeginInit(); + this.CalibrateTabPage.SuspendLayout(); + this.SelectionPanel.SuspendLayout(); + this.SuspendLayout(); + // + // MapComboBox + // + this.MapComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.MapComboBox.FormattingEnabled = true; + this.MapComboBox.Location = new System.Drawing.Point(12, 12); + this.MapComboBox.Name = "MapComboBox"; + this.MapComboBox.Size = new System.Drawing.Size(82, 21); + this.MapComboBox.TabIndex = 0; + this.MapComboBox.SelectedIndexChanged += new System.EventHandler(this.MapComboBox_SelectedIndexChanged); + // + // LoadingLabel + // + this.LoadingLabel.AutoSize = true; + this.LoadingLabel.BackColor = System.Drawing.Color.Transparent; + this.LoadingLabel.Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.LoadingLabel.ForeColor = System.Drawing.Color.White; + this.LoadingLabel.Location = new System.Drawing.Point(315, 52); + this.LoadingLabel.Name = "LoadingLabel"; + this.LoadingLabel.Size = new System.Drawing.Size(166, 18); + this.LoadingLabel.TabIndex = 1; + this.LoadingLabel.Text = "Loading texture..."; + this.LoadingLabel.Visible = false; + // + // MainPanel + // + this.MainPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainPanel.BackColor = System.Drawing.Color.Silver; + this.MainPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.MainPanel.Controls.Add(this.MainPanelHideButton); + this.MainPanel.Controls.Add(this.MainTabControl); + this.MainPanel.Location = new System.Drawing.Point(607, 2); + this.MainPanel.Name = "MainPanel"; + this.MainPanel.Size = new System.Drawing.Size(240, 619); + this.MainPanel.TabIndex = 2; + this.MainPanel.Visible = false; + // + // MainPanelHideButton + // + this.MainPanelHideButton.Location = new System.Drawing.Point(198, 7); + this.MainPanelHideButton.Name = "MainPanelHideButton"; + this.MainPanelHideButton.Size = new System.Drawing.Size(31, 23); + this.MainPanelHideButton.TabIndex = 0; + this.MainPanelHideButton.Text = ">>"; + this.MainPanelHideButton.UseVisualStyleBackColor = true; + this.MainPanelHideButton.Click += new System.EventHandler(this.MainPanelHideButton_Click); + // + // MainTabControl + // + this.MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTabControl.Controls.Add(this.ToolsTabPage); + this.MainTabControl.Controls.Add(this.MarkersTabPage); + this.MainTabControl.Controls.Add(this.OptionsTabPage); + this.MainTabControl.Controls.Add(this.CalibrateTabPage); + this.MainTabControl.Location = new System.Drawing.Point(-1, 36); + this.MainTabControl.Name = "MainTabControl"; + this.MainTabControl.SelectedIndex = 0; + this.MainTabControl.Size = new System.Drawing.Size(240, 582); + this.MainTabControl.TabIndex = 1; + // + // ToolsTabPage + // + this.ToolsTabPage.Controls.Add(this.ResetMarkersButton); + this.ToolsTabPage.Controls.Add(this.ClearMarkersButton); + this.ToolsTabPage.Controls.Add(this.GoToButton); + this.ToolsTabPage.Controls.Add(this.LocatorStatusLabel); + this.ToolsTabPage.Controls.Add(this.ShowLocatorCheckBox); + this.ToolsTabPage.Controls.Add(this.label5); + this.ToolsTabPage.Controls.Add(this.LocateTextBox); + this.ToolsTabPage.Controls.Add(this.label4); + this.ToolsTabPage.Controls.Add(this.AddMarkersButton); + this.ToolsTabPage.Controls.Add(this.MultiFindTextBox); + this.ToolsTabPage.Location = new System.Drawing.Point(4, 22); + this.ToolsTabPage.Name = "ToolsTabPage"; + this.ToolsTabPage.Size = new System.Drawing.Size(232, 556); + this.ToolsTabPage.TabIndex = 2; + this.ToolsTabPage.Text = "Tools"; + this.ToolsTabPage.UseVisualStyleBackColor = true; + // + // ResetMarkersButton + // + this.ResetMarkersButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.ResetMarkersButton.Location = new System.Drawing.Point(149, 507); + this.ResetMarkersButton.Name = "ResetMarkersButton"; + this.ResetMarkersButton.Size = new System.Drawing.Size(83, 23); + this.ResetMarkersButton.TabIndex = 9; + this.ResetMarkersButton.Text = "Reset markers"; + this.ResetMarkersButton.UseVisualStyleBackColor = true; + this.ResetMarkersButton.Click += new System.EventHandler(this.ResetMarkersButton_Click); + // + // ClearMarkersButton + // + this.ClearMarkersButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.ClearMarkersButton.Location = new System.Drawing.Point(149, 478); + this.ClearMarkersButton.Name = "ClearMarkersButton"; + this.ClearMarkersButton.Size = new System.Drawing.Size(83, 23); + this.ClearMarkersButton.TabIndex = 8; + this.ClearMarkersButton.Text = "Clear markers"; + this.ClearMarkersButton.UseVisualStyleBackColor = true; + this.ClearMarkersButton.Click += new System.EventHandler(this.ClearMarkersButton_Click); + // + // GoToButton + // + this.GoToButton.Location = new System.Drawing.Point(189, 48); + this.GoToButton.Name = "GoToButton"; + this.GoToButton.Size = new System.Drawing.Size(43, 22); + this.GoToButton.TabIndex = 7; + this.GoToButton.Text = "Go to"; + this.GoToButton.UseVisualStyleBackColor = true; + this.GoToButton.Click += new System.EventHandler(this.GoToButton_Click); + // + // LocatorStatusLabel + // + this.LocatorStatusLabel.AutoSize = true; + this.LocatorStatusLabel.Location = new System.Drawing.Point(3, 72); + this.LocatorStatusLabel.Name = "LocatorStatusLabel"; + this.LocatorStatusLabel.Size = new System.Drawing.Size(193, 13); + this.LocatorStatusLabel.TabIndex = 6; + this.LocatorStatusLabel.Text = "Enter coord above or drag the marker..."; + // + // ShowLocatorCheckBox + // + this.ShowLocatorCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ShowLocatorCheckBox.AutoSize = true; + this.ShowLocatorCheckBox.Checked = true; + this.ShowLocatorCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.ShowLocatorCheckBox.Location = new System.Drawing.Point(101, 32); + this.ShowLocatorCheckBox.Name = "ShowLocatorCheckBox"; + this.ShowLocatorCheckBox.Size = new System.Drawing.Size(88, 17); + this.ShowLocatorCheckBox.TabIndex = 5; + this.ShowLocatorCheckBox.Text = "Show marker"; + this.ShowLocatorCheckBox.UseVisualStyleBackColor = true; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(3, 33); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(79, 13); + this.label5.TabIndex = 4; + this.label5.Text = "Locate: X, Y, Z"; + // + // LocateTextBox + // + this.LocateTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.LocateTextBox.Location = new System.Drawing.Point(0, 49); + this.LocateTextBox.Name = "LocateTextBox"; + this.LocateTextBox.Size = new System.Drawing.Size(189, 20); + this.LocateTextBox.TabIndex = 3; + this.LocateTextBox.Text = "0, 0, 0"; + this.LocateTextBox.TextChanged += new System.EventHandler(this.LocateTextBox_TextChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(3, 142); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(122, 13); + this.label4.TabIndex = 2; + this.label4.Text = "Multi-find: X, Y, Z, Name"; + // + // AddMarkersButton + // + this.AddMarkersButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.AddMarkersButton.Location = new System.Drawing.Point(0, 478); + this.AddMarkersButton.Name = "AddMarkersButton"; + this.AddMarkersButton.Size = new System.Drawing.Size(75, 23); + this.AddMarkersButton.TabIndex = 1; + this.AddMarkersButton.Text = "Add markers"; + this.AddMarkersButton.UseVisualStyleBackColor = true; + this.AddMarkersButton.Click += new System.EventHandler(this.AddMarkersButton_Click); + // + // MultiFindTextBox + // + this.MultiFindTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MultiFindTextBox.Location = new System.Drawing.Point(0, 158); + this.MultiFindTextBox.MaxLength = 999999; + this.MultiFindTextBox.Multiline = true; + this.MultiFindTextBox.Name = "MultiFindTextBox"; + this.MultiFindTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.MultiFindTextBox.Size = new System.Drawing.Size(232, 314); + this.MultiFindTextBox.TabIndex = 0; + // + // MarkersTabPage + // + this.MarkersTabPage.Controls.Add(this.GoToSelectedMarkerButton); + this.MarkersTabPage.Controls.Add(this.CopyMarkersButton); + this.MarkersTabPage.Controls.Add(this.checkBox1); + this.MarkersTabPage.Controls.Add(this.MarkersListView); + this.MarkersTabPage.Location = new System.Drawing.Point(4, 22); + this.MarkersTabPage.Name = "MarkersTabPage"; + this.MarkersTabPage.Padding = new System.Windows.Forms.Padding(3); + this.MarkersTabPage.Size = new System.Drawing.Size(232, 556); + this.MarkersTabPage.TabIndex = 0; + this.MarkersTabPage.Text = "Markers"; + this.MarkersTabPage.UseVisualStyleBackColor = true; + // + // GoToSelectedMarkerButton + // + this.GoToSelectedMarkerButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.GoToSelectedMarkerButton.Location = new System.Drawing.Point(141, 494); + this.GoToSelectedMarkerButton.Name = "GoToSelectedMarkerButton"; + this.GoToSelectedMarkerButton.Size = new System.Drawing.Size(91, 23); + this.GoToSelectedMarkerButton.TabIndex = 3; + this.GoToSelectedMarkerButton.Text = "Go to selected"; + this.GoToSelectedMarkerButton.UseVisualStyleBackColor = true; + this.GoToSelectedMarkerButton.Click += new System.EventHandler(this.GoToSelectedMarkerButton_Click); + // + // CopyMarkersButton + // + this.CopyMarkersButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.CopyMarkersButton.Location = new System.Drawing.Point(0, 494); + this.CopyMarkersButton.Name = "CopyMarkersButton"; + this.CopyMarkersButton.Size = new System.Drawing.Size(75, 23); + this.CopyMarkersButton.TabIndex = 2; + this.CopyMarkersButton.Text = "Copy list"; + this.CopyMarkersButton.UseVisualStyleBackColor = true; + this.CopyMarkersButton.Click += new System.EventHandler(this.CopyMarkersButton_Click); + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(3, 3); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(78, 17); + this.checkBox1.TabIndex = 1; + this.checkBox1.Text = "Visible only"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // MarkersListView + // + this.MarkersListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MarkersListView.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.MarkersListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader4, + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.MarkersListView.FullRowSelect = true; + this.MarkersListView.HideSelection = false; + this.MarkersListView.Location = new System.Drawing.Point(0, 26); + this.MarkersListView.Name = "MarkersListView"; + this.MarkersListView.Size = new System.Drawing.Size(232, 462); + this.MarkersListView.TabIndex = 0; + this.MarkersListView.UseCompatibleStateImageBehavior = false; + this.MarkersListView.View = System.Windows.Forms.View.Details; + this.MarkersListView.DoubleClick += new System.EventHandler(this.MarkersListView_DoubleClick); + // + // columnHeader4 + // + this.columnHeader4.Text = "Name"; + this.columnHeader4.Width = 230; + // + // columnHeader1 + // + this.columnHeader1.Text = "X"; + this.columnHeader1.Width = 75; + // + // columnHeader2 + // + this.columnHeader2.Text = "Y"; + this.columnHeader2.Width = 75; + // + // columnHeader3 + // + this.columnHeader3.Text = "Z"; + this.columnHeader3.Width = 75; + // + // OptionsTabPage + // + this.OptionsTabPage.Controls.Add(this.LocatorStyleComboBox); + this.OptionsTabPage.Controls.Add(this.label6); + this.OptionsTabPage.Controls.Add(this.label3); + this.OptionsTabPage.Controls.Add(this.SmoothingUpDown); + this.OptionsTabPage.Controls.Add(this.label2); + this.OptionsTabPage.Controls.Add(this.ZoomSpeedUpDown); + this.OptionsTabPage.Controls.Add(this.MarkerStyleComboBox); + this.OptionsTabPage.Controls.Add(this.label1); + this.OptionsTabPage.Location = new System.Drawing.Point(4, 22); + this.OptionsTabPage.Name = "OptionsTabPage"; + this.OptionsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.OptionsTabPage.Size = new System.Drawing.Size(232, 556); + this.OptionsTabPage.TabIndex = 1; + this.OptionsTabPage.Text = "Options"; + this.OptionsTabPage.UseVisualStyleBackColor = true; + // + // LocatorStyleComboBox + // + this.LocatorStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.LocatorStyleComboBox.FormattingEnabled = true; + this.LocatorStyleComboBox.Location = new System.Drawing.Point(79, 33); + this.LocatorStyleComboBox.Name = "LocatorStyleComboBox"; + this.LocatorStyleComboBox.Size = new System.Drawing.Size(150, 21); + this.LocatorStyleComboBox.TabIndex = 7; + this.LocatorStyleComboBox.SelectedIndexChanged += new System.EventHandler(this.LocatorStyleComboBox_SelectedIndexChanged); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(3, 36); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(70, 13); + this.label6.TabIndex = 6; + this.label6.Text = "Locator style:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(3, 88); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(60, 13); + this.label3.TabIndex = 5; + this.label3.Text = "Smoothing:"; + // + // SmoothingUpDown + // + this.SmoothingUpDown.DecimalPlaces = 2; + this.SmoothingUpDown.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.SmoothingUpDown.Location = new System.Drawing.Point(79, 86); + this.SmoothingUpDown.Maximum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.SmoothingUpDown.Name = "SmoothingUpDown"; + this.SmoothingUpDown.Size = new System.Drawing.Size(150, 20); + this.SmoothingUpDown.TabIndex = 4; + this.SmoothingUpDown.Value = new decimal(new int[] { + 5, + 0, + 0, + 65536}); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 62); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(69, 13); + this.label2.TabIndex = 3; + this.label2.Text = "Zoom speed:"; + // + // ZoomSpeedUpDown + // + this.ZoomSpeedUpDown.DecimalPlaces = 2; + this.ZoomSpeedUpDown.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.ZoomSpeedUpDown.Location = new System.Drawing.Point(79, 60); + this.ZoomSpeedUpDown.Maximum = new decimal(new int[] { + 5, + 0, + 0, + 0}); + this.ZoomSpeedUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 131072}); + this.ZoomSpeedUpDown.Name = "ZoomSpeedUpDown"; + this.ZoomSpeedUpDown.Size = new System.Drawing.Size(150, 20); + this.ZoomSpeedUpDown.TabIndex = 2; + this.ZoomSpeedUpDown.Value = new decimal(new int[] { + 15, + 0, + 0, + 65536}); + // + // MarkerStyleComboBox + // + this.MarkerStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.MarkerStyleComboBox.FormattingEnabled = true; + this.MarkerStyleComboBox.Location = new System.Drawing.Point(79, 6); + this.MarkerStyleComboBox.Name = "MarkerStyleComboBox"; + this.MarkerStyleComboBox.Size = new System.Drawing.Size(150, 21); + this.MarkerStyleComboBox.TabIndex = 1; + this.MarkerStyleComboBox.SelectedIndexChanged += new System.EventHandler(this.MarkerStyleComboBox_SelectedIndexChanged); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(67, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Marker style:"; + // + // CalibrateTabPage + // + this.CalibrateTabPage.Controls.Add(this.label11); + this.CalibrateTabPage.Controls.Add(this.UnitsPerTexelYTextBox); + this.CalibrateTabPage.Controls.Add(this.CalibrationErrorLabel); + this.CalibrateTabPage.Controls.Add(this.CalibrateButton); + this.CalibrateTabPage.Controls.Add(this.CalibrationPointsTextBox); + this.CalibrateTabPage.Controls.Add(this.label10); + this.CalibrateTabPage.Controls.Add(this.SetCoordButton); + this.CalibrateTabPage.Controls.Add(this.label12); + this.CalibrateTabPage.Controls.Add(this.WorldCoordTextBox); + this.CalibrateTabPage.Controls.Add(this.TextureFileLabel); + this.CalibrateTabPage.Controls.Add(this.TextureNameLabel); + this.CalibrateTabPage.Controls.Add(this.label9); + this.CalibrateTabPage.Controls.Add(this.UnitsPerTexelXTextBox); + this.CalibrateTabPage.Controls.Add(this.SetOriginButton); + this.CalibrateTabPage.Controls.Add(this.label8); + this.CalibrateTabPage.Controls.Add(this.TextureOriginTextBox); + this.CalibrateTabPage.Controls.Add(this.label7); + this.CalibrateTabPage.Controls.Add(this.TextureCoordTextBox); + this.CalibrateTabPage.Location = new System.Drawing.Point(4, 22); + this.CalibrateTabPage.Name = "CalibrateTabPage"; + this.CalibrateTabPage.Size = new System.Drawing.Size(232, 556); + this.CalibrateTabPage.TabIndex = 3; + this.CalibrateTabPage.Text = "Calibrate"; + this.CalibrateTabPage.UseVisualStyleBackColor = true; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(0, 155); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(87, 13); + this.label11.TabIndex = 32; + this.label11.Text = "Units per texel Y:"; + // + // UnitsPerTexelYTextBox + // + this.UnitsPerTexelYTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.UnitsPerTexelYTextBox.Location = new System.Drawing.Point(93, 152); + this.UnitsPerTexelYTextBox.Name = "UnitsPerTexelYTextBox"; + this.UnitsPerTexelYTextBox.Size = new System.Drawing.Size(139, 20); + this.UnitsPerTexelYTextBox.TabIndex = 31; + this.UnitsPerTexelYTextBox.Text = "1"; + // + // CalibrationErrorLabel + // + this.CalibrationErrorLabel.Location = new System.Drawing.Point(6, 488); + this.CalibrationErrorLabel.Name = "CalibrationErrorLabel"; + this.CalibrationErrorLabel.Size = new System.Drawing.Size(226, 36); + this.CalibrationErrorLabel.TabIndex = 30; + this.CalibrationErrorLabel.Text = "No calibration performed"; + this.CalibrationErrorLabel.Visible = false; + // + // CalibrateButton + // + this.CalibrateButton.Location = new System.Drawing.Point(157, 462); + this.CalibrateButton.Name = "CalibrateButton"; + this.CalibrateButton.Size = new System.Drawing.Size(75, 23); + this.CalibrateButton.TabIndex = 29; + this.CalibrateButton.Text = "Calibrate"; + this.CalibrateButton.UseVisualStyleBackColor = true; + this.CalibrateButton.Visible = false; + this.CalibrateButton.Click += new System.EventHandler(this.CalibrateButton_Click); + // + // CalibrationPointsTextBox + // + this.CalibrationPointsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.CalibrationPointsTextBox.Location = new System.Drawing.Point(0, 374); + this.CalibrationPointsTextBox.Multiline = true; + this.CalibrationPointsTextBox.Name = "CalibrationPointsTextBox"; + this.CalibrationPointsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.CalibrationPointsTextBox.Size = new System.Drawing.Size(232, 82); + this.CalibrationPointsTextBox.TabIndex = 28; + this.CalibrationPointsTextBox.Visible = false; + // + // label10 + // + this.label10.Location = new System.Drawing.Point(3, 236); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(226, 135); + this.label10.TabIndex = 27; + this.label10.Text = resources.GetString("label10.Text"); + // + // SetCoordButton + // + this.SetCoordButton.Location = new System.Drawing.Point(157, 184); + this.SetCoordButton.Name = "SetCoordButton"; + this.SetCoordButton.Size = new System.Drawing.Size(68, 23); + this.SetCoordButton.TabIndex = 26; + this.SetCoordButton.Text = "Set coord"; + this.SetCoordButton.UseVisualStyleBackColor = true; + this.SetCoordButton.Click += new System.EventHandler(this.SetCoordButton_Click); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(0, 63); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(68, 13); + this.label12.TabIndex = 25; + this.label12.Text = "World coord:"; + // + // WorldCoordTextBox + // + this.WorldCoordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.WorldCoordTextBox.Location = new System.Drawing.Point(93, 60); + this.WorldCoordTextBox.Name = "WorldCoordTextBox"; + this.WorldCoordTextBox.Size = new System.Drawing.Size(139, 20); + this.WorldCoordTextBox.TabIndex = 24; + this.WorldCoordTextBox.Text = "0, 0"; + // + // TextureFileLabel + // + this.TextureFileLabel.AutoSize = true; + this.TextureFileLabel.Location = new System.Drawing.Point(2, 28); + this.TextureFileLabel.Name = "TextureFileLabel"; + this.TextureFileLabel.Size = new System.Drawing.Size(59, 13); + this.TextureFileLabel.TabIndex = 23; + this.TextureFileLabel.Text = "Texture file"; + // + // TextureNameLabel + // + this.TextureNameLabel.AutoSize = true; + this.TextureNameLabel.Location = new System.Drawing.Point(2, 9); + this.TextureNameLabel.Name = "TextureNameLabel"; + this.TextureNameLabel.Size = new System.Drawing.Size(72, 13); + this.TextureNameLabel.TabIndex = 22; + this.TextureNameLabel.Text = "Texture name"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(0, 132); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(87, 13); + this.label9.TabIndex = 21; + this.label9.Text = "Units per texel X:"; + // + // UnitsPerTexelXTextBox + // + this.UnitsPerTexelXTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.UnitsPerTexelXTextBox.Location = new System.Drawing.Point(93, 129); + this.UnitsPerTexelXTextBox.Name = "UnitsPerTexelXTextBox"; + this.UnitsPerTexelXTextBox.Size = new System.Drawing.Size(139, 20); + this.UnitsPerTexelXTextBox.TabIndex = 20; + this.UnitsPerTexelXTextBox.Text = "1"; + // + // SetOriginButton + // + this.SetOriginButton.Location = new System.Drawing.Point(81, 184); + this.SetOriginButton.Name = "SetOriginButton"; + this.SetOriginButton.Size = new System.Drawing.Size(68, 23); + this.SetOriginButton.TabIndex = 19; + this.SetOriginButton.Text = "Set origin"; + this.SetOriginButton.UseVisualStyleBackColor = true; + this.SetOriginButton.Click += new System.EventHandler(this.SetOriginButton_Click); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(0, 109); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(74, 13); + this.label8.TabIndex = 18; + this.label8.Text = "Texture origin:"; + // + // TextureOriginTextBox + // + this.TextureOriginTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TextureOriginTextBox.Location = new System.Drawing.Point(93, 106); + this.TextureOriginTextBox.Name = "TextureOriginTextBox"; + this.TextureOriginTextBox.Size = new System.Drawing.Size(139, 20); + this.TextureOriginTextBox.TabIndex = 17; + this.TextureOriginTextBox.Text = "0, 0"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(0, 86); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(76, 13); + this.label7.TabIndex = 16; + this.label7.Text = "Texture coord:"; + // + // TextureCoordTextBox + // + this.TextureCoordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TextureCoordTextBox.Location = new System.Drawing.Point(93, 83); + this.TextureCoordTextBox.Name = "TextureCoordTextBox"; + this.TextureCoordTextBox.Size = new System.Drawing.Size(139, 20); + this.TextureCoordTextBox.TabIndex = 15; + this.TextureCoordTextBox.Text = "0, 0"; + // + // MainPanelShowButton + // + this.MainPanelShowButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.MainPanelShowButton.Location = new System.Drawing.Point(806, 10); + this.MainPanelShowButton.Name = "MainPanelShowButton"; + this.MainPanelShowButton.Size = new System.Drawing.Size(31, 23); + this.MainPanelShowButton.TabIndex = 3; + this.MainPanelShowButton.Text = "<<"; + this.MainPanelShowButton.UseVisualStyleBackColor = true; + this.MainPanelShowButton.Click += new System.EventHandler(this.MainPanelShowButton_Click); + // + // SelectionPanel + // + this.SelectionPanel.BackColor = System.Drawing.Color.White; + this.SelectionPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.SelectionPanel.Controls.Add(this.SelectionPositionTextBox); + this.SelectionPanel.Controls.Add(this.SelectionNameTextBox); + this.SelectionPanel.Location = new System.Drawing.Point(12, 73); + this.SelectionPanel.Name = "SelectionPanel"; + this.SelectionPanel.Size = new System.Drawing.Size(180, 42); + this.SelectionPanel.TabIndex = 4; + this.SelectionPanel.Visible = false; + // + // SelectionPositionTextBox + // + this.SelectionPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectionPositionTextBox.BackColor = System.Drawing.Color.White; + this.SelectionPositionTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.SelectionPositionTextBox.Location = new System.Drawing.Point(3, 22); + this.SelectionPositionTextBox.Name = "SelectionPositionTextBox"; + this.SelectionPositionTextBox.ReadOnly = true; + this.SelectionPositionTextBox.Size = new System.Drawing.Size(172, 13); + this.SelectionPositionTextBox.TabIndex = 1; + // + // SelectionNameTextBox + // + this.SelectionNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectionNameTextBox.BackColor = System.Drawing.Color.White; + this.SelectionNameTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.SelectionNameTextBox.Location = new System.Drawing.Point(3, 3); + this.SelectionNameTextBox.Name = "SelectionNameTextBox"; + this.SelectionNameTextBox.ReadOnly = true; + this.SelectionNameTextBox.Size = new System.Drawing.Size(172, 13); + this.SelectionNameTextBox.TabIndex = 0; + // + // MapForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(64))))); + this.ClientSize = new System.Drawing.Size(849, 623); + this.Controls.Add(this.MainPanelShowButton); + this.Controls.Add(this.MainPanel); + this.Controls.Add(this.LoadingLabel); + this.Controls.Add(this.MapComboBox); + this.Controls.Add(this.SelectionPanel); + this.DoubleBuffered = true; + this.Name = "MapForm"; + this.Text = "Map - CodeWalker by dexyfex"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MapForm_FormClosing); + this.ResizeBegin += new System.EventHandler(this.MapForm_ResizeBegin); + this.ResizeEnd += new System.EventHandler(this.MapForm_ResizeEnd); + this.ClientSizeChanged += new System.EventHandler(this.MapForm_ClientSizeChanged); + this.SizeChanged += new System.EventHandler(this.MapForm_SizeChanged); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MapForm_MouseDown); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MapForm_MouseMove); + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MapForm_MouseUp); + this.MainPanel.ResumeLayout(false); + this.MainTabControl.ResumeLayout(false); + this.ToolsTabPage.ResumeLayout(false); + this.ToolsTabPage.PerformLayout(); + this.MarkersTabPage.ResumeLayout(false); + this.MarkersTabPage.PerformLayout(); + this.OptionsTabPage.ResumeLayout(false); + this.OptionsTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.SmoothingUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ZoomSpeedUpDown)).EndInit(); + this.CalibrateTabPage.ResumeLayout(false); + this.CalibrateTabPage.PerformLayout(); + this.SelectionPanel.ResumeLayout(false); + this.SelectionPanel.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ComboBox MapComboBox; + private System.Windows.Forms.Label LoadingLabel; + private System.Windows.Forms.Panel MainPanel; + private System.Windows.Forms.Button MainPanelHideButton; + private System.Windows.Forms.Button MainPanelShowButton; + private System.Windows.Forms.TabControl MainTabControl; + private System.Windows.Forms.TabPage MarkersTabPage; + private System.Windows.Forms.TabPage OptionsTabPage; + private System.Windows.Forms.ComboBox MarkerStyleComboBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ListView MarkersListView; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.Button CopyMarkersButton; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown ZoomSpeedUpDown; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.NumericUpDown SmoothingUpDown; + private System.Windows.Forms.TabPage ToolsTabPage; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button AddMarkersButton; + private System.Windows.Forms.TextBox MultiFindTextBox; + private System.Windows.Forms.TextBox LocateTextBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.CheckBox ShowLocatorCheckBox; + private System.Windows.Forms.ComboBox LocatorStyleComboBox; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label LocatorStatusLabel; + private System.Windows.Forms.Button GoToButton; + private System.Windows.Forms.TabPage CalibrateTabPage; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.TextBox WorldCoordTextBox; + private System.Windows.Forms.Label TextureFileLabel; + private System.Windows.Forms.Label TextureNameLabel; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox UnitsPerTexelXTextBox; + private System.Windows.Forms.Button SetOriginButton; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox TextureOriginTextBox; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox TextureCoordTextBox; + private System.Windows.Forms.Button SetCoordButton; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Button CalibrateButton; + private System.Windows.Forms.TextBox CalibrationPointsTextBox; + private System.Windows.Forms.Label CalibrationErrorLabel; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TextBox UnitsPerTexelYTextBox; + private System.Windows.Forms.Button ClearMarkersButton; + private System.Windows.Forms.Button ResetMarkersButton; + private System.Windows.Forms.Button GoToSelectedMarkerButton; + private System.Windows.Forms.Panel SelectionPanel; + private System.Windows.Forms.TextBox SelectionPositionTextBox; + private System.Windows.Forms.TextBox SelectionNameTextBox; + } +} \ No newline at end of file diff --git a/MapForm.cs b/MapForm.cs new file mode 100644 index 0000000..bd5845d --- /dev/null +++ b/MapForm.cs @@ -0,0 +1,1206 @@ +using SlimDX; +using SlimDX.Direct3D9; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class MapForm : Form + { + + Vector3 TargetViewCenter = new Vector3(0.0f); + Vector3 CurrentViewCenter = new Vector3(0.0f); + float TargetZoom = 1.0f; + float CurrentZoom = 1.0f; + + + volatile bool LoadingImages = false; + List Images; + MapImage CurrentMap = null; + + List Icons; + MapIcon MarkerIcon = null; + MapIcon LocatorIcon = null; + MapMarker LocatorMarker = null; + MapMarker GrabbedMarker = null; + MapMarker SelectedMarker = null; + MapMarker MousedMarker = null; + List Markers = new List(); + List RenderMarkers = new List(); + + bool Resizing = false; + bool MouseButtonDown = false; + Point MouseDownPoint; + Point MouseLastPoint; + + volatile bool NeedsUpdate = false; + + Direct3D d3d = null; + Device device = null; + Sprite sprite = null; + + Stopwatch FrameTimer = new Stopwatch(); + + Size OldSize; + + public MapForm() + { + InitializeComponent(); + + + Icons = new List(); + AddIcon("Google Marker", "icon_google_marker_64x64.png", 64, 64, 11.0f, 40.0f, 1.0f); + AddIcon("Glokon Marker", "icon_glokon_normal_32x32.png", 32, 32, 11.0f, 32.0f, 1.0f); + AddIcon("Glokon Debug", "icon_glokon_debug_32x32.png", 32, 32, 11.5f, 32.0f, 1.0f); + MarkerIcon = Icons[1]; + LocatorIcon = Icons[2]; + foreach (MapIcon icon in Icons) + { + MarkerStyleComboBox.Items.Add(icon); + LocatorStyleComboBox.Items.Add(icon); + } + MarkerStyleComboBox.SelectedItem = MarkerIcon; + LocatorStyleComboBox.SelectedItem = LocatorIcon; + LocatorMarker = new MapMarker(); + LocatorMarker.Icon = LocatorIcon; + LocatorMarker.IsMovable = true; + + + ////for google map calibration... + //var game_1_x = 1972.606; //var map_1_lng = -60.8258056640625; + //var game_1_y = 3817.044; //var map_1_lat = 72.06379257078102; + //var game_2_x = -1154.11; //var map_2_lng = -72.1417236328125; + //var game_2_y = -2715.203; //var map_2_lat = 48.41572128171852; + + ////reference point: + //501.4398, 5603.9600, 795.9738, 0x4CC3BAFC, cs1_10_redeye + + //origin in 8192x8192 textures is at approx: + //3755.2, 5525.5 + + float ox = 3755.2f; + float oy = 5525.5f; + float uptx = 1.517952f; //this seems pretty close... + float upty = -1.517952f; + + Images = new List(); + AddImage("Satellite", "gtav_satellite_8192x8192.jpg", 8192, 8192, ox, oy, uptx, upty); + AddImage("Roads", "gtav_roadmap_8192x8192.jpg", 8192, 8192, ox, oy, uptx, upty); + AddImage("Atlas", "gtav_atlas_8192x8192.jpg", 8192, 8192, ox, oy, uptx, upty); + foreach (MapImage mi in Images) + { + MapComboBox.Items.Add(mi); + } + + InitializeDevice(); + + if (Images.Count > 0) + { + MapImage mi = Images[0]; + MapComboBox.SelectedItem = mi; + TargetViewCenter = mi.Origin; + CurrentViewCenter = mi.Origin; + } + + this.MouseWheel += MapForm_MouseMove; + + FrameTimer.Restart(); + SlimDX.Windows.MessagePump.Run(this, new SlimDX.Windows.MainLoop(SlimDX_Render)); + } + + private void MapForm_FormClosing(object sender, FormClosingEventArgs e) + { + DisposeDevice(); + + if (d3d != null) + { + d3d.Dispose(); + d3d = null; + } + } + + + + public void InitializeDevice() + { + if (WindowState == FormWindowState.Minimized) return; + + PresentParameters presentParams = new PresentParameters + { + BackBufferWidth = ClientSize.Width, + BackBufferHeight = ClientSize.Height, + DeviceWindowHandle = Handle, + PresentFlags = PresentFlags.None, + Multisample = MultisampleType.None, + BackBufferCount = 0, + PresentationInterval = PresentInterval.One, // VSYNC ON + SwapEffect = SwapEffect.Discard, + BackBufferFormat = Format.X8R8G8B8, + Windowed = true, + EnableAutoDepthStencil = false, + }; + + if (d3d == null) + { + d3d = new Direct3D(); + } + + device = new Device(d3d, 0, DeviceType.Hardware, Handle, CreateFlags.HardwareVertexProcessing, presentParams); + device.Viewport = new Viewport(0, 0, ClientSize.Width, ClientSize.Height); + + sprite = new Sprite(device); + + if (Icons != null) + { + foreach (MapIcon icon in Icons) + { + LoadIconTexture(icon); + } + } + + if ((CurrentMap != null) && (CurrentMap.Tex == null)) + { + LoadImageTexture(CurrentMap); + } + } + + public void DisposeDevice() + { + if (device == null) return; + + if (Icons != null) + { + foreach (MapIcon icon in Icons) + { + if (icon.Tex != null) + { + icon.Tex.Dispose(); + icon.Tex = null; + } + } + } + + foreach (MapImage img in Images) + { + if (img.Tex != null) + { + img.Tex.Dispose(); + img.Tex = null; + } + } + + if ((CurrentMap != null) && (CurrentMap.Tex != null)) + { + CurrentMap.Tex.Dispose(); + CurrentMap.Tex = null; + } + + sprite.Dispose(); + sprite = null; + + device.Dispose(); + device = null; + } + + private void HandleWindowResize() + { + DisposeDevice(); + InitializeDevice(); //this really shouldn't be necessary! + + + //sprite.Dispose(); + //sprite = null; + + //device.Reset(); + + //sprite = new Sprite(device); + } + + + private void MapForm_ResizeBegin(object sender, EventArgs e) + { + OldSize = Size; + Resizing = true; + } + private void MapForm_ResizeEnd(object sender, EventArgs e) + { + Resizing = false; + if ((OldSize != Size) && (!LoadingImages)) + { + HandleWindowResize(); + } + } + private void MapForm_SizeChanged(object sender, EventArgs e) + { + + } + private void MapForm_ClientSizeChanged(object sender, EventArgs e) + { + if ((!Resizing) && (!LoadingImages)) + { + HandleWindowResize(); + } + } + + + private void MapForm_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + MouseButtonDown = true; + } + MouseDownPoint = e.Location; + MouseLastPoint = MouseDownPoint; + + if (MouseButtonDown) + { + if (MousedMarker != null) + { + if (MousedMarker.IsMovable) + { + GrabbedMarker = MousedMarker; + } + else + { + SelectedMarker = MousedMarker; + SelectionNameTextBox.Text = SelectedMarker.Name; + SelectionPositionTextBox.Text = SelectedMarker.Get3DWorldPosString(); + UpdateSelectionPanel(); + SelectionPanel.Visible = true; + } + } + else + { + GrabbedMarker = null; + //SelectedMarker = null; + //SelectionPanel.Visible = false; + } + } + } + private void MapForm_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + MouseButtonDown = false; + + GrabbedMarker = null; + + if ((e.Location == MouseDownPoint) && (MousedMarker == null)) + { + //was clicked. but not on a marker... deselect and hide the panel + + SelectedMarker = null; + SelectionPanel.Visible = false; + } + } + } + private void MapForm_MouseMove(object sender, MouseEventArgs e) + { + if (e.Delta != 0) + { + float zoomfac = 1.0f + 0.1f*((float)ZoomSpeedUpDown.Value); + float oldzoom = TargetZoom; + float newzoom = oldzoom * (e.Delta > 0 ? zoomfac : 1.0f / zoomfac); + + if (newzoom < 1e-2f) newzoom = 1e-2f; + if (newzoom > 1e4f) newzoom = 1e4f; + + //figure out the new target center based on current mouse pos + float w = ClientSize.Width; + float h = ClientSize.Height; + float mx = MouseLastPoint.X - w * 0.5f; + float my = MouseLastPoint.Y - h * 0.5f; + + Vector3 mpold = new Vector3(mx, my, 0.0f) / oldzoom; + Vector3 mpnew = new Vector3(mx, my, 0.0f) / newzoom; + Vector3 mpdelt = mpnew - mpold; + + TargetViewCenter -= mpdelt; + TargetZoom = newzoom; + + + NeedsUpdate = true; + } + if (MouseButtonDown) + { + float dx = (e.X - MouseLastPoint.X) / CurrentZoom; + float dy = (e.Y - MouseLastPoint.Y) / CurrentZoom; + + if (GrabbedMarker == null) + { + //pan the view. + TargetViewCenter.X -= dx; + TargetViewCenter.Y -= dy; + NeedsUpdate = true; + } + else + { + //move the grabbed marker... + float uptx = (CurrentMap != null) ? CurrentMap.UnitsPerTexelX : 1.0f; + float upty = (CurrentMap != null) ? CurrentMap.UnitsPerTexelY : 1.0f; + Vector3 wpos = GrabbedMarker.WorldPos; + wpos.X += dx*uptx; + wpos.Y += dy*upty; + GrabbedMarker.WorldPos = wpos; + UpdateMarkerTexturePos(GrabbedMarker); + + if (GrabbedMarker == LocatorMarker) + { + LocateTextBox.Text = LocatorMarker.ToString(); + WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString(); + TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString(); + } + + } + } + + + if (NeedsUpdate) + { + //limit to the texture. + float tvcmaxx = 8192.0f; + float tvcminx = 0.0f; + float tvcmaxy = 8192.0f; + float tvcminy = 0.0f; + if (!((TargetViewCenter.X > tvcmaxx) && (TargetViewCenter.X < tvcminx))) + { + if (TargetViewCenter.X > tvcmaxx) TargetViewCenter.X = tvcmaxx; + if (TargetViewCenter.X < tvcminx) TargetViewCenter.X = tvcminx; + } + if (!((TargetViewCenter.Y > tvcmaxy) && (TargetViewCenter.Y < tvcminy))) + { + if (TargetViewCenter.Y > tvcmaxy) TargetViewCenter.Y = tvcmaxy; + if (TargetViewCenter.Y < tvcminy) TargetViewCenter.Y = tvcminy; + } + } + + + MouseLastPoint = e.Location; + + MousedMarker = FindMousedMarker(); + + if (MousedMarker != null) + { + if (MousedMarker.IsMovable) + { + Cursor = Cursors.SizeAll; + } + else + { + Cursor = Cursors.Hand; + } + } + else + { + Cursor = Cursors.Default; + } + } + + + + + + private void SlimDX_Render() + { + if (device == null) + { + return; + } + if (LoadingImages) + { + return; + } + + + device.Clear(ClearFlags.Target, new Color4(BackColor), 1.0f, 0); + device.BeginScene(); + device.SetRenderState(RenderState.AlphaBlendEnable, true); + device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha); + device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha); + if (NeedsUpdate) + { + } + + if ((CurrentMap != null) && (CurrentMap.Tex != null)) + { + float smooth = 1.0f - (((float)SmoothingUpDown.Value)*0.9f); + float elapsed = (float)Math.Min(FrameTimer.Elapsed.TotalSeconds, 0.1); + CurrentZoom = CurrentZoom + (TargetZoom - CurrentZoom) * smooth; + CurrentViewCenter = CurrentViewCenter + (TargetViewCenter - CurrentViewCenter) * smooth; + + float w = ClientSize.Width; + float h = ClientSize.Height; + + + Matrix scale = Matrix.Scaling(CurrentZoom, CurrentZoom, 0.0f); + Matrix trans = Matrix.Translation(-CurrentViewCenter); + Matrix offset = Matrix.Translation(w * 0.5f, h * 0.5f, 0.0f); + Matrix matrix = Matrix.Multiply(Matrix.Multiply(trans, scale), offset); + + sprite.Begin(SpriteFlags.None); + sprite.Transform = matrix; + sprite.Draw(CurrentMap.Tex, Color.White); + sprite.End(); + + + sprite.Begin(SpriteFlags.None); + sprite.Transform = Matrix.Identity; + + + + //sort by Y to make markers look correct + RenderMarkers.Clear(); + RenderMarkers.AddRange(Markers); + RenderMarkers.Sort((m1, m2) => m1.TexturePos.Y.CompareTo(m2.TexturePos.Y)); + + + + //draw all the markers + foreach (MapMarker m in RenderMarkers) + { + if ((m.Icon != null) && (m.Icon.Tex != null)) + { + UpdateMarkerScreenPos(m); + + sprite.Transform = GetMarkerRenderMatrix(m); + sprite.Draw(m.Icon.Tex, Color.White); + } + } + + //draw the locator marker + MapIcon locic = LocatorMarker.Icon; + if ((ShowLocatorCheckBox.Checked) && (locic != null) && (locic.Tex != null)) + { + UpdateMarkerScreenPos(LocatorMarker); + + sprite.Transform = GetMarkerRenderMatrix(LocatorMarker); + sprite.Draw(locic.Tex, Color.White); + } + + + sprite.End(); + + } + + device.EndScene(); + device.Present(); + + + + if (SelectedMarker != null) + { + UpdateSelectionPanel(); + } + + + FrameTimer.Restart(); + } + + private void UpdateSelectionPanel() + { + + + int ox = -90; + int oy = -76; + + int px = (int)Math.Round(SelectedMarker.ScreenPos.X, MidpointRounding.AwayFromZero) + ox; + int py = (int)Math.Round(SelectedMarker.ScreenPos.Y, MidpointRounding.AwayFromZero) + oy; + + int sx = SelectionPanel.Width; + int sy = SelectionPanel.Height; + + SelectionPanel.SetBounds(px, py, sx, sy); + + } + + + + private void MapComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + MapImage mi = MapComboBox.SelectedItem as MapImage; + if ((mi != null) && (mi != CurrentMap) && (device != null)) + { + SetIsLoading(true); + if ((CurrentMap != null) && (CurrentMap.Tex != null)) + { + CurrentMap.Tex.Dispose(); + CurrentMap.Tex = null; + } + + if (mi.Tex == null) + { + LoadImageTexture(mi); + } + else + { + SetIsLoading(false); + } + + CurrentMap = mi; + NeedsUpdate = true; + + if (CurrentMap != null) + { + TextureNameLabel.Text = CurrentMap.Name; + TextureFileLabel.Text = CurrentMap.Filepath; + TextureOriginTextBox.Text = string.Format("{0}, {1}", CurrentMap.Origin.X, CurrentMap.Origin.Y); + UnitsPerTexelXTextBox.Text = CurrentMap.UnitsPerTexelX.ToString(); + UnitsPerTexelYTextBox.Text = CurrentMap.UnitsPerTexelY.ToString(); + if (LocatorMarker != null) + { + UpdateMarkerTexturePos(LocatorMarker); + WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString(); + TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString(); + } + } + else + { + TextureNameLabel.Text = "(No texture)"; + TextureFileLabel.Text = "(No texture)"; + } + } + } + + + private void MainPanelShowButton_Click(object sender, EventArgs e) + { + MainPanel.Visible = true; + MainPanelShowButton.Visible = false; + } + private void MainPanelHideButton_Click(object sender, EventArgs e) + { + MainPanel.Visible = false; + MainPanelShowButton.Visible = true; + } + + private void MarkerStyleComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + MapIcon icon = MarkerStyleComboBox.SelectedItem as MapIcon; + if (icon != MarkerIcon) + { + MarkerIcon = icon; + + foreach (MapMarker m in Markers) + { + m.Icon = icon; + } + } + } + private void LocatorStyleComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + MapIcon icon = LocatorStyleComboBox.SelectedItem as MapIcon; + if (icon != LocatorIcon) + { + LocatorIcon = icon; + LocatorMarker.Icon = icon; + } + } + + + + private void LocateTextBox_TextChanged(object sender, EventArgs e) + { + if (GrabbedMarker == LocatorMarker) return; //don't try to update the marker if it's being dragged + if (LocatorMarker == null) return; //this shouldn't happen, but anyway + + LocatorMarker.Parse(LocateTextBox.Text); + + UpdateMarkerTexturePos(LocatorMarker); + } + private void GoToButton_Click(object sender, EventArgs e) + { + GoToMarker(LocatorMarker); + } + + + private void AddMarkersButton_Click(object sender, EventArgs e) + { + string[] lines = MultiFindTextBox.Text.Split('\n'); + foreach (string line in lines) + { + AddMarker(line); + } + } + + private void ClearMarkersButton_Click(object sender, EventArgs e) + { + Markers.Clear(); + MarkersListView.Items.Clear(); + } + private void ResetMarkersButton_Click(object sender, EventArgs e) + { + Markers.Clear(); + MarkersListView.Items.Clear(); + AddDefaultMarkers(); + } + + + + private void SetOriginButton_Click(object sender, EventArgs e) + { + if (CurrentMap == null) return; + + TextureOriginTextBox.Text = TextureCoordTextBox.Text; + + string[] comps = TextureOriginTextBox.Text.Split(','); + if (comps.Length > 1) + { + Vector3 origin = new Vector3(0.0f); + float.TryParse(comps[0].Trim(), out origin.X); + float.TryParse(comps[1].Trim(), out origin.Y); + CurrentMap.Origin = origin; + + RecalculateAllMarkers(); + + LocatorMarker.WorldPos = new Vector3(0.0f);//force to the world origin + LocatorMarker.TexturePos = origin; + GrabbedMarker = LocatorMarker; //don't force the marker update when updating textbox.. + LocateTextBox.Text = "0, 0, 0"; + GrabbedMarker = null; + WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString(); + TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString(); + } + + } + private void SetCoordButton_Click(object sender, EventArgs e) + { + if (CurrentMap == null) return; + + string[] comps = WorldCoordTextBox.Text.Split(','); + if (comps.Length > 1) + { + Vector3 coord = new Vector3(0.0f); + float.TryParse(comps[0].Trim(), out coord.X); + float.TryParse(comps[1].Trim(), out coord.Y); + + //assume the entered coord is the world coord for the locator's tex coord. + //find the appropriate scaling factor to make it so. + + float tdx = LocatorMarker.TexturePos.X - CurrentMap.Origin.X; //texel dist from origin + float tdy = LocatorMarker.TexturePos.Y - CurrentMap.Origin.Y; + float tdl = (float)Math.Sqrt(tdx * tdx + tdy * tdy); + + float wcl = (float)Math.Sqrt(coord.X * coord.X + coord.Y * coord.Y); + + float upt = wcl / tdl; + float uptx = upt * Math.Sign(tdx * coord.X); + float upty = upt * Math.Sign(tdy * coord.Y); + + CurrentMap.UnitsPerTexelX = uptx; + CurrentMap.UnitsPerTexelY = upty; + + RecalculateAllMarkers(); + + LocatorMarker.WorldPos = coord; + GrabbedMarker = LocatorMarker; //don't force the marker update when updating textbox.. + LocateTextBox.Text = LocatorMarker.ToString(); + GrabbedMarker = null; + WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString(); + TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString(); + UnitsPerTexelXTextBox.Text = uptx.ToString(); + UnitsPerTexelYTextBox.Text = upty.ToString(); + } + + } + + private void CalibrateButton_Click(object sender, EventArgs e) + { + MessageBox.Show("Not yet implemented..."); + } + + private void CopyMarkersButton_Click(object sender, EventArgs e) + { + MessageBox.Show("Still need to build this function."); + } + + + + private void RecalculateAllMarkers() + { + //updates marker world coords based off current tex coord + + if (LocatorMarker != null) + { + LocatorMarker.WorldPos = GetWorldCoordFromTextureCoord(LocatorMarker.TexturePos); + } + + foreach (MapMarker marker in Markers) + { + marker.WorldPos = GetWorldCoordFromTextureCoord(marker.TexturePos); + } + + } + + + private Vector3 GetTextureCoordFromWorldCoord(Vector3 world) + { + if (CurrentMap != null) + { + float tx = world.X / CurrentMap.UnitsPerTexelX; + float ty = world.Y / CurrentMap.UnitsPerTexelY; + return CurrentMap.Origin + new Vector3(tx, ty, 1.0f); + } + else + { + return new Vector3(0.0f); + } + } + private Vector3 GetWorldCoordFromTextureCoord(Vector3 coord) + { + if (CurrentMap != null) + { + Vector3 tv = (coord - CurrentMap.Origin); + tv.X *= CurrentMap.UnitsPerTexelX; + tv.Y *= CurrentMap.UnitsPerTexelY; + return tv; + } + else + { + return new Vector3(0.0f); + } + } + + private Vector3 GetTextureCoordFromScreenCoord(Vector3 screen) + { + return new Vector3(0.0f); + } + private Vector3 GetScreenCoordFromTextureCoord(Vector3 coord) + { + float w = ClientSize.Width; + float h = ClientSize.Height; + + Vector3 centerdisttx = coord - CurrentViewCenter; + Vector3 centerdistpx = centerdisttx * CurrentZoom; + Vector3 screenpos = centerdistpx + new Vector3(w*0.5f, h*0.5f, 0.0f); + screenpos.Z = 0.0f; + + return screenpos; + } + + private Vector3 GetWorldCoordFromScreenCoord(Vector3 screen) + { + return GetWorldCoordFromTextureCoord(GetTextureCoordFromScreenCoord(screen)); + } + private Vector3 GetScreenCoordFromWorldCoord(Vector3 world) + { + return GetScreenCoordFromTextureCoord(GetTextureCoordFromWorldCoord(world)); + } + + private void UpdateMarkerTexturePos(MapMarker marker) + { + marker.TexturePos = GetTextureCoordFromWorldCoord(marker.WorldPos); + } + private void UpdateMarkerScreenPos(MapMarker marker) + { + marker.ScreenPos = GetScreenCoordFromTextureCoord(marker.TexturePos); + } + private void UpdateMarkerTexAndScreenPos(MapMarker marker) + { + marker.TexturePos = GetTextureCoordFromWorldCoord(marker.WorldPos); + marker.ScreenPos = GetScreenCoordFromTextureCoord(marker.TexturePos); + } + + private Matrix GetMarkerRenderMatrix(MapMarker marker) + { + float sx = 1.0f, sy = 1.0f; + MapIcon ic = marker.Icon; + int icw = ic.TexWidth; + int ich = ic.TexHeight; + if (icw > ich) //shrink square vertically + { + sy = ((float)ich) / ((float)icw); + } + else //shrink square horizontally + { + sx = ((float)icw) / ((float)ich); + } + + sx *= ic.Scale; + sy *= ic.Scale; + + + float px = marker.ScreenPos.X - ic.Center.X * ic.Scale; + float py = marker.ScreenPos.Y - ic.Center.Y*ic.Scale; + + px = (float)Math.Round(px, MidpointRounding.AwayFromZero); //snap to pixels... + py = (float)Math.Round(py, MidpointRounding.AwayFromZero); + + + Matrix scale = Matrix.Scaling(sx, sy, 0.0f); + Matrix trans = Matrix.Translation(px, py, 0.0f); + + return Matrix.Multiply(scale, trans); + } + + private MapMarker FindMousedMarker() + { + + float mx = MouseLastPoint.X; + float my = MouseLastPoint.Y; + + if (ShowLocatorCheckBox.Checked) + { + if (IsMapMarkerUnderPoint(LocatorMarker, mx, my)) + { + return LocatorMarker; + } + } + + //search backwards through the render markers (front to back) + for (int i = RenderMarkers.Count - 1; i >= 0; i--) + { + MapMarker m = RenderMarkers[i]; + if (IsMapMarkerUnderPoint(m, mx, my)) + { + return m; + } + } + + return null; + } + private bool IsMapMarkerUnderPoint(MapMarker marker, float x, float y) + { + float dx = x - marker.ScreenPos.X; + float dy = y - marker.ScreenPos.Y; + float mcx = marker.Icon.Center.X; + float mcy = marker.Icon.Center.Y; + bool bx = ((dx >= -mcx) && (dx <= mcx)); + bool by = ((dy <= 0.0f) && (dy >= -mcy)); + return (bx && by); + } + + + private void GoToMarker(MapMarker m) + { + //adjust the target to account for the main panel... + Vector3 view = m.TexturePos; + view.X += ((float)(MainPanel.Width + 4) * 0.5f) / CurrentZoom; + + TargetViewCenter = view; + } + + + private void AddMarker(string markerstr) + { + MapMarker m = new MapMarker(); + m.Parse(markerstr.Trim()); + m.Icon = MarkerIcon; + + UpdateMarkerTexturePos(m); + + Markers.Add(m); + + //////sort by Y + ////Markers.Sort((m1, m2) => m1.TexturePos.Y.CompareTo(m2.TexturePos.Y)); + + ListViewItem lvi = new ListViewItem(new string[] { m.Name, m.WorldPos.X.ToString(), m.WorldPos.Y.ToString(), m.WorldPos.Z.ToString() }); + lvi.Tag = m; + MarkersListView.Items.Add(lvi); + } + private void AddDefaultMarkers() + { + + AddMarker("1972.606, 3817.044, 0.0, Trevor Bed"); + AddMarker("94.5723, -1290.082, 0.0, Strip Club Bed"); + AddMarker("-1151.746, -1518.136, 0.0, Trevor City Bed"); + AddMarker("-2052.0, 3237.0, 0.0, Zancudo UFO"); + AddMarker("2490.0, 3777.0, 0.0, Hippy UFO"); + AddMarker("760.4618, 7392.8032, -126.0774, Sea UFO"); + AddMarker("501.4398, 5603.96, 0.0, RedEye"); + AddMarker("-1154.11, -2715.203, 0.0, Flight School"); + AddMarker("-1370.625, 56.1227, 0.0, Golf"); + AddMarker("-1109.213, 4914.744, 0.0, Altruist Cult"); + AddMarker("-1633.087, 4736.784, 0.0, Deal Gone Wrong"); + AddMarker("51.3909, 5957.7568, 209.614, cs1_10_clue_moon02"); + AddMarker("400.7087, 5714.5645, 605.0978, cs1_10_clue_rain01"); + AddMarker("703.442, 6329.8936, 76.4973, cs1_10_clue_rain02"); + AddMarker("228.7844, 5370.585, 577.2613, cs1_10_clue_moon01"); + AddMarker("366.4871, 5518.0742, 704.3185, cs1_10_clue_mountain01"); + + + } + + + private MapIcon AddIcon(string name, string filename, int texw, int texh, float centerx, float centery, float scale) + { + string filepath = "maps\\" + filename; + try + { + MapIcon mi = new MapIcon(name, filepath, texw, texh, centerx, centery, scale); + Icons.Add(mi); + return mi; + } + catch (Exception ex) + { + MessageBox.Show("Could not load map icon " + filepath + " for " + name + "!\n\n" + ex.ToString()); + } + return null; + } + private MapImage AddImage(string name, string filename, int texw, int texh, float origx, float origy, float uppx, float uppy) + { + string filepath = "maps\\" + filename; + try + { + MapImage mi = new MapImage(name, filepath, texw, texh, origx, origy, uppx, uppy); + Images.Add(mi); + return mi; + } + catch (Exception ex) + { + MessageBox.Show("Could not load map image " + filepath + " for " + name + " map!\n\n" + ex.ToString()); + } + return null; + } + + private void LoadImageTexture(MapImage mi) + { + SetIsLoading(true); + + Task.Run(() => + { + try + { + if (device != null) + { + mi.Tex = Texture.FromFile(device, mi.Filepath); + } + } + catch (Exception ex) + { + MessageBox.Show("Could not load map image " + mi.Filepath + " for " + mi.Name + " map!\n\n" + ex.ToString()); + } + + LoadCurrentImageComplete(); + }); + } + private void LoadIconTexture(MapIcon mi) + { + try + { + if (device != null) + { + mi.Tex = Texture.FromFile(device, mi.Filepath); + } + } + catch (Exception ex) + { + MessageBox.Show("Could not load map icon " + mi.Filepath + " for " + mi.Name + "!\n\n" + ex.ToString()); + } + } + + private void LoadCurrentImageComplete() + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { LoadCurrentImageComplete(); })); + } + else + { + SetIsLoading(false); + } + } + catch { } + } + private void LoadImagesComplete() + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { LoadImagesComplete(); })); + } + else + { + if (Images.Count > 0) + { + foreach (MapImage mi in Images) + { + MapComboBox.Items.Add(mi); + } + CurrentMap = Images[0]; + MapComboBox.SelectedItem = CurrentMap; + } + SetIsLoading(false); + } + } + catch { } + } + private void SetIsLoading(bool loading) + { + LoadingImages = loading; + LoadingLabel.Visible = loading; + MapComboBox.Enabled = !loading; + } + + private void GoToSelectedMarkerButton_Click(object sender, EventArgs e) + { + if (MarkersListView.SelectedItems.Count == 1) + { + MapMarker m = MarkersListView.SelectedItems[0].Tag as MapMarker; + if (m != null) + { + GoToMarker(m); + } + } + } + + private void MarkersListView_DoubleClick(object sender, EventArgs e) + { + //go to the marker.. + if (MarkersListView.SelectedItems.Count == 1) + { + MapMarker m = MarkersListView.SelectedItems[0].Tag as MapMarker; + if (m != null) + { + GoToMarker(m); + } + } + } + } + + + public class MapImage + { + public string Name { get; set; } + public string Filepath { get; set; } + public Texture Tex { get; set; } + public Vector3 Origin { get; set; } //in image pixels + public float UnitsPerTexelX { get; set; } //world units per image pixel + public float UnitsPerTexelY { get; set; } //world units per image pixel + public int TexWidth { get; set; } + public int TexHeight { get; set; } + + public MapImage(string name, string filepath, int texw, int texh, float origx, float origy, float uppx, float uppy) + { + Name = name; + Filepath = filepath; + TexWidth = texw; + TexHeight = texh; + Origin = new Vector3(origx, origy, 0.0f); + UnitsPerTexelX = uppx; + UnitsPerTexelY = uppy; + + if (!File.Exists(filepath)) + { + throw new Exception("File not found."); + } + } + + public override string ToString() + { + return Name; + } + + } + + public class MapIcon + { + public string Name { get; set; } + public string Filepath { get; set; } + public Texture Tex { get; set; } + public Vector3 Center { get; set; } //in image pixels + public float Scale { get; set; } //screen pixels per icon pixel + public int TexWidth { get; set; } + public int TexHeight { get; set; } + + public MapIcon(string name, string filepath, int texw, int texh, float centerx, float centery, float scale) + { + Name = name; + Filepath = filepath; + TexWidth = texw; + TexHeight = texh; + Center = new Vector3(centerx, centery, 0.0f); + Scale = scale; + + if (!File.Exists(filepath)) + { + throw new Exception("File not found."); + } + } + + public override string ToString() + { + return Name; + } + } + + public class MapMarker + { + public MapIcon Icon { get; set; } + public Vector3 WorldPos { get; set; } //actual world pos + public Vector3 TexturePos { get; set; } //position in the current texture (temp) + public Vector3 ScreenPos { get; set; } //position on screen (updated per frame if needed) + public string Name { get; set; } + public List Properties { get; set; } //additional data + public bool IsMovable { get; set; } + + public void Parse(string s) + { + Vector3 p = new Vector3(0.0f); + string[] ss = s.Split(','); + if (ss.Length > 1) + { + float.TryParse(ss[0].Trim(), out p.X); + float.TryParse(ss[1].Trim(), out p.Y); + } + if (ss.Length > 2) + { + float.TryParse(ss[2].Trim(), out p.Z); + } + if (ss.Length > 3) + { + Name = ss[3].Trim(); + } + else + { + Name = string.Empty; + } + for (int i = 4; i < ss.Length; i++) + { + if (Properties == null) Properties = new List(); + Properties.Add(ss[i].Trim()); + } + WorldPos = p; + } + + public override string ToString() + { + string cstr = string.Format("{0}, {1}, {2}", WorldPos.X, WorldPos.Y, WorldPos.Z); + if (!string.IsNullOrEmpty(Name)) + { + cstr += ", " + Name; + if (Properties != null) + { + foreach (string prop in Properties) + { + cstr += ", " + prop; + } + } + } + return cstr; + } + + public string Get2DWorldPosString() + { + return string.Format("{0}, {1}", WorldPos.X, WorldPos.Y); + } + public string Get3DWorldPosString() + { + return string.Format("{0}, {1}, {2}", WorldPos.X, WorldPos.Y, WorldPos.Z); + } + + public string Get2DTexturePosString() + { + return string.Format("{0}, {1}", TexturePos.X, TexturePos.Y); + } + + } + +} diff --git a/MapForm.resx b/MapForm.resx new file mode 100644 index 0000000..c45a600 --- /dev/null +++ b/MapForm.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + To use the calibrator, first position the locator marker where the exact world center should be, and click Set origin. +Then choose a known coordinate and move the locator marker there. +Enter the known coordinate's world x, y position into the World coord text box and press the Set coord button to calculate the Units per texel X and Y. + + +Alternatively, enter calibration points below (format: xw, yw, xt, yt): + +The aim of the map calibration is to find the most accurate texture origin and units per texel. +The texture origin is the coordinates (in pixels) of where the world's origin (0,0,0) is in the texture. +Units per texel is how big each pixel in the texture is, when measured in world units. + + \ No newline at end of file diff --git a/Materials.txt b/Materials.txt new file mode 100644 index 0000000..cf51616 --- /dev/null +++ b/Materials.txt @@ -0,0 +1,215 @@ +# CodeWalker Collision Material Colours File +# Material Name ABGR (hex) + +DEFAULT FFCCCCCC +CONCRETE FFDDDDDD +CONCRETE_POTHOLE FFDDDDDD +CONCRETE_DUSTY FFDDDDDD +TARMAC FF333333 +TARMAC_PAINTED FF333355 +TARMAC_POTHOLE FF303030 +RUMBLE_STRIP FF444444 +BREEZE_BLOCK FF555555 +ROCK FF228899 +ROCK_MOSSY FF22CC88 +STONE FFAAAAAA +COBBLESTONE FFAAAAAA +BRICK FF332299 +MARBLE FF666699 +PAVING_SLAB FFCCCCCC +SANDSTONE_SOLID FF48EFEF +SANDSTONE_BRITTLE FF47ECEC +SAND_LOOSE FF46F0F0 +SAND_COMPACT FF44EEEE +SAND_WET FF22CCCC +SAND_TRACK FF40E0E0 +SAND_UNDERWATER FF30D0D0 +SAND_DRY_DEEP FF46F0F0 +SAND_WET_DEEP FF22CCCC +ICE FFEEDDCC +ICE_TARMAC FFBBAFAF +SNOW_LOOSE FFFFFCFC +SNOW_COMPACT FFFFF0F0 +SNOW_DEEP FFFFFAFA +SNOW_TARMAC FFFAF0F0 +GRAVEL_SMALL FF99CCDD +GRAVEL_LARGE FF9BDFDF +GRAVEL_DEEP FF95D9D9 +GRAVEL_TRAIN_TRACK FF9A9A9A +DIRT_TRACK FF36479C +MUD_HARD FF334499 +MUD_POTHOLE FF27388D +MUD_SOFT FF223388 +MUD_UNDERWATER FF1F3085 +MUD_DEEP FF1D2883 +MARSH FF20DD80 +MARSH_DEEP FF1CD97C +SOIL FF112266 +CLAY_HARD FF334477 +CLAY_SOFT FF304174 +GRASS_LONG FF0FA81F +GRASS FF11AA11 +GRASS_SHORT FF22AA22 +HAY FF40F5F5 +BUSHES FF009900 +TWIGS FF00CC44 +LEAVES FF22CC22 +WOODCHIPS FF33AACC +TREE_BARK FF1199BB +METAL_SOLID_SMALL FFDDDDDD +METAL_SOLID_MEDIUM FFDDDDDD +METAL_SOLID_LARGE FFDDDDDD +METAL_HOLLOW_SMALL FFDDDDDD +METAL_HOLLOW_MEDIUM FFDDDDDD +METAL_HOLLOW_LARGE FFDDDDDD +METAL_CHAINLINK_SMALL FFDDDDDD +METAL_CHAINLINK_LARGE FFDDDDDD +METAL_CORRUGATED_IRON FFDDDDDD +METAL_GRILLE FFDDDDDD +METAL_RAILING FFDDDDDD +METAL_DUCT FFDDDDDD +METAL_GARAGE_DOOR FFDDDDDD +METAL_MANHOLE FFDDDDDD +WOOD_SOLID_SMALL FF117799 +WOOD_SOLID_MEDIUM FF117799 +WOOD_SOLID_LARGE FF117799 +WOOD_SOLID_POLISHED FF117799 +WOOD_FLOOR_DUSTY FF117799 +WOOD_HOLLOW_SMALL FF117799 +WOOD_HOLLOW_MEDIUM FF117799 +WOOD_HOLLOW_LARGE FF117799 +WOOD_CHIPBOARD FF117799 +WOOD_OLD_CREAKY FF117799 +WOOD_HIGH_DENSITY FF117799 +WOOD_LATTICE FF117799 +CERAMIC FFEEEEEE +ROOF_TILE FF111177 +ROOF_FELT FF666666 +FIBREGLASS FF99BBDD +TARPAULIN FFEE4411 +PLASTIC FFEE5522 +PLASTIC_HOLLOW FFEE5522 +PLASTIC_HIGH_DENSITY FFEE5533 +PLASTIC_CLEAR FFFE6543 +PLASTIC_HOLLOW_CLEAR FFFE6543 +PLASTIC_HIGH_DENSITY_CLEAR FFFE5543 +FIBREGLASS_HOLLOW FF9ABCDE +RUBBER FF111111 +RUBBER_HOLLOW FF111111 +LINOLEUM FFAAAAAA +LAMINATE FFBBBBBB +CARPET_SOLID FFDDDDDD +CARPET_SOLID_DUSTY FFDEDEDE +CARPET_FLOORBOARD FFD0D0D0 +CLOTH FFEEEEEE +PLASTER_SOLID FFEEEEEE +PLASTER_BRITTLE FFEEEEEE +CARDBOARD_SHEET FF11AACC +CARDBOARD_BOX FF11AACC +PAPER FFF4F4F4 +FOAM FFEFEFEF +FEATHER_PILLOW FFEEEEEE +POLYSTYRENE FFFFFFFF +LEATHER FF111122 +TVSCREEN FF111111 +SLATTED_BLINDS FFCCCCCC +GLASS_SHOOT_THROUGH 77EECCCC +GLASS_BULLETPROOF 77EFCDCD +GLASS_OPAQUE DDEECCCC +PERSPEX 66EEDDDD +CAR_METAL FFDDDDDD +CAR_PLASTIC FFEE5522 +CAR_SOFTTOP FF333333 +CAR_SOFTTOP_CLEAR 55DDDDDD +CAR_GLASS_WEAK 77EECCCC +CAR_GLASS_MEDIUM 77EECCCC +CAR_GLASS_STRONG 77EECCCC +CAR_GLASS_BULLETPROOF 77EECCCC +CAR_GLASS_OPAQUE 77EECCCC +WATER 77EECCAA +BLOOD FF0000CC +OIL EE112233 +PETROL 77CCDDEE +FRESH_MEAT FFCCDDEE +DRIED_MEAT FFDDEEFF +EMISSIVE_GLASS EEEEDDDD +EMISSIVE_PLASTIC FFEE7744 +VFX_METAL_ELECTRIFIED FFFFEEEE +VFX_METAL_WATER_TOWER FFCCCCCC +VFX_METAL_STEAM FFBBBBBB +VFX_METAL_FLAME FFBBBBFF +PHYS_NO_FRICTION FF00DD00 +PHYS_GOLF_BALL FFFFFFFF +PHYS_TENNIS_BALL FFCCFFCC +PHYS_CASTER FF050505 +PHYS_CASTER_RUSTY FF050535 +PHYS_CAR_VOID FF000000 +PHYS_PED_CAPSULE FFDDDDDD +PHYS_ELECTRIC_FENCE FFFFDDCC +PHYS_ELECTRIC_METAL FFFFEEDD +PHYS_BARBED_WIRE FFCCCCDC +PHYS_POOLTABLE_SURFACE FF116611 +PHYS_POOLTABLE_CUSHION FF156815 +PHYS_POOLTABLE_BALL FFCCCCCC +BUTTOCKS FFFFFFFF +THIGH_LEFT FFFFFFFF +SHIN_LEFT FFFFFFFF +FOOT_LEFT FFFFFFFF +THIGH_RIGHT FFFFFFFF +SHIN_RIGHT FFFFFFFF +FOOT_RIGHT FFFFFFFF +SPINE0 FFFFFFFF +SPINE1 FFFFFFFF +SPINE2 FFFFFFFF +SPINE3 FFFFFFFF +CLAVICLE_LEFT FFFFFFFF +UPPER_ARM_LEFT FFFFFFFF +LOWER_ARM_LEFT FFFFFFFF +HAND_LEFT FFFFFFFF +CLAVICLE_RIGHT FFFFFFFF +UPPER_ARM_RIGHT FFFFFFFF +LOWER_ARM_RIGHT FFFFFFFF +HAND_RIGHT FFFFFFFF +NECK FFFFFFFF +HEAD FFFFFFFF +ANIMAL_DEFAULT FFFFFFFF +CAR_ENGINE FFFFFFFF +PUDDLE CCFFDDDD +CONCRETE_PAVEMENT FFDEDEDE +BRICK_PAVEMENT FF332299 +PHYS_DYNAMIC_COVER_BOUND FFFFFFFF +VFX_WOOD_BEER_BARREL FF117799 +WOOD_HIGH_FRICTION FF117799 +ROCK_NOINST FF228899 +BUSHES_NOINST FF009900 +METAL_SOLID_ROAD_SURFACE FF444455 +TEMP_01 FFFFFFFF +TEMP_02 FFFFFFFF +TEMP_03 FFFFFFFF +TEMP_04 FFFFFFFF +TEMP_05 FFFFFFFF +TEMP_06 FFFFFFFF +TEMP_07 FFFFFFFF +TEMP_08 FFFFFFFF +TEMP_09 FFFFFFFF +TEMP_10 FFFFFFFF +TEMP_11 FFFFFFFF +TEMP_12 FFFFFFFF +TEMP_13 FFFFFFFF +TEMP_14 FFFFFFFF +TEMP_15 FFFFFFFF +TEMP_16 FFFFFFFF +TEMP_17 FFFFFFFF +TEMP_18 FFFFFFFF +TEMP_19 FFFFFFFF +TEMP_20 FFFFFFFF +TEMP_21 FFFFFFFF +TEMP_22 FFFFFFFF +TEMP_23 FFFFFFFF +TEMP_24 FFFFFFFF +TEMP_25 FFFFFFFF +TEMP_26 FFFFFFFF +TEMP_27 FFFFFFFF +TEMP_28 FFFFFFFF +TEMP_29 FFFFFFFF +TEMP_30 FFFFFFFF diff --git a/Notice.txt b/Notice.txt new file mode 100644 index 0000000..a41bc0c --- /dev/null +++ b/Notice.txt @@ -0,0 +1,35 @@ + + Copyright(c) 2017 dexyfex + + + + +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + + + + + + + + diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..a67449c --- /dev/null +++ b/Program.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main(string[] args) + { + + bool menumode = false; + bool explorermode = false; + if ((args != null) && (args.Length > 0)) + { + foreach (string arg in args) + { + if (arg.ToLower() == "menu") + { + menumode = true; + } + if (arg.ToLower() == "explorer") + { + explorermode = true; + } + } + } + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + +#if !DEBUG + try + { +#endif + if (menumode) + { + Application.Run(new MainForm()); + } + else if (explorermode) + { + Application.Run(new ExploreForm()); + } + else + { + Application.Run(new WorldForm()); + } +#if !DEBUG + } + catch (Exception ex) + { + MessageBox.Show("An unexpected error was encountered!\n" + ex.ToString()); + //this can happen if folder wasn't chosen, or in some other catastrophic error. meh. + } +#endif + } + } +} diff --git a/Project/ProjectFile.cs b/Project/ProjectFile.cs new file mode 100644 index 0000000..a88046d --- /dev/null +++ b/Project/ProjectFile.cs @@ -0,0 +1,604 @@ +using CodeWalker.GameFiles; +using CodeWalker.World; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.Project +{ + public class ProjectFile + { + //fields stored in file + public string Name { get; set; } //friendly name for this project + public int Version { get; set; } + public List YmapFilenames { get; set; } = new List(); + public List YndFilenames { get; set; } = new List(); + public List YnvFilenames { get; set; } = new List(); + public List TrainsFilenames { get; set; } = new List(); + public List ScenarioFilenames { get; set; } = new List(); + + //fields not stored + public string Filename { get; set; } //filename without path + public string Filepath { get; set; } //full path of the current file + public bool HasChanged { get; set; } //flag for use by the UI + + public List YmapFiles { get; set; } = new List(); + public List YndFiles { get; set; } = new List(); + public List YnvFiles { get; set; } = new List(); + public List TrainsFiles { get; set; } = new List(); + public List ScenarioFiles { get; set; } = new List(); + + + + public void Save() + { + XmlDocument doc = new XmlDocument(); + var projelem = doc.CreateElement("CodeWalkerProject"); + doc.AppendChild(projelem); + + Xml.AddChildWithInnerText(doc, projelem, "Name", Name); + Xml.AddChildWithAttribute(doc, projelem, "Version", "value", Version.ToString()); + + var ymapselem = Xml.AddChild(doc, projelem, "YmapFilenames"); + foreach (string ymapfilename in YmapFilenames) + { + Xml.AddChildWithInnerText(doc, ymapselem, "Item", ymapfilename); + } + + var yndselem = Xml.AddChild(doc, projelem, "YndFilenames"); + foreach (string yndfilename in YndFilenames) + { + Xml.AddChildWithInnerText(doc, yndselem, "Item", yndfilename); + } + + var ynvselem = Xml.AddChild(doc, projelem, "YnvFilenames"); + foreach (string ynvfilename in YnvFilenames) + { + Xml.AddChildWithInnerText(doc, ynvselem, "Item", ynvfilename); + } + + var trainselem = Xml.AddChild(doc, projelem, "TrainsFilenames"); + foreach (string trainsfile in TrainsFilenames) + { + Xml.AddChildWithInnerText(doc, trainselem, "Item", trainsfile); + } + + var scenarioselem = Xml.AddChild(doc, projelem, "ScenarioFilenames"); + foreach (string scenariofilename in ScenarioFilenames) + { + Xml.AddChildWithInnerText(doc, scenarioselem, "Item", scenariofilename); + } + + doc.Save(Filepath); + } + + public void Load(string filepath) + { + FileInfo fi = new FileInfo(filepath); + Filename = fi.Name; + Filepath = filepath; + + XmlDocument doc = new XmlDocument(); + doc.Load(filepath); + + var projelem = doc.DocumentElement; + + Name = Xml.GetChildInnerText(projelem, "Name"); + Version = Xml.GetChildIntAttribute(projelem, "Version", "value"); + + YmapFilenames.Clear(); + YmapFiles.Clear(); + var ymapselem = Xml.GetChild(projelem, "YmapFilenames"); + if (ymapselem != null) + { + foreach (var node in ymapselem.SelectNodes("Item")) + { + XmlElement ymapel = node as XmlElement; + if (ymapel != null) + { + AddYmapFile(ymapel.InnerText); + } + } + } + + + + YndFilenames.Clear(); + YndFiles.Clear(); + var yndselem = Xml.GetChild(projelem, "YndFilenames"); + if (yndselem != null) + { + foreach (var node in yndselem.SelectNodes("Item")) + { + XmlElement yndel = node as XmlElement; + if (yndel != null) + { + AddYndFile(yndel.InnerText); + } + } + } + + + + YnvFilenames.Clear(); + YnvFiles.Clear(); + var ynvselem = Xml.GetChild(projelem, "YnvFilenames"); + if (ynvselem != null) + { + foreach (var node in ynvselem.SelectNodes("Item")) + { + XmlElement ynvel = node as XmlElement; + if (ynvel != null) + { + AddYnvFile(ynvel.InnerText); + } + } + } + + + TrainsFilenames.Clear(); + TrainsFiles.Clear(); + var trainsselem = Xml.GetChild(projelem, "TrainsFilenames"); + if (trainsselem != null) + { + foreach (var node in trainsselem.SelectNodes("Item")) + { + XmlElement trainel = node as XmlElement; + if (trainel != null) + { + AddTrainsFile(trainel.InnerText); + } + } + } + + + + ScenarioFilenames.Clear(); + ScenarioFiles.Clear(); + var scenarioselem = Xml.GetChild(projelem, "ScenarioFilenames"); + if (scenarioselem != null) + { + foreach (var node in scenarioselem.SelectNodes("Item")) + { + XmlElement scenarioel = node as XmlElement; + if (scenarioel != null) + { + AddScenarioFile(scenarioel.InnerText); + } + } + } + + + } + + + public void UpdateFilenames(string oldprojpath) + { + for (int i = 0; i < YmapFilenames.Count; i++) + { + YmapFilenames[i] = GetUpdatedFilePath(YmapFilenames[i], oldprojpath); + } + for (int i = 0; i < YndFilenames.Count; i++) + { + YndFilenames[i] = GetUpdatedFilePath(YndFilenames[i], oldprojpath); + } + for (int i = 0; i < YnvFilenames.Count; i++) + { + YnvFilenames[i] = GetUpdatedFilePath(YnvFilenames[i], oldprojpath); + } + for (int i = 0; i < TrainsFilenames.Count; i++) + { + TrainsFilenames[i] = GetUpdatedFilePath(TrainsFilenames[i], oldprojpath); + } + for (int i = 0; i < ScenarioFilenames.Count; i++) + { + ScenarioFilenames[i] = GetUpdatedFilePath(ScenarioFilenames[i], oldprojpath); + } + } + + public string GetUpdatedFilePath(string oldpath, string oldprojpath) + { + string fullpath = GetFullFilePath(oldpath, oldprojpath); + string newpath = GetRelativePath(fullpath); + return newpath; + } + public string GetRelativePath(string filepath) + { + if (filepath == null) return string.Empty; + if (Filepath == null) return filepath; + + Uri fromUri; + if (!Uri.TryCreate(Filepath, UriKind.RelativeOrAbsolute, out fromUri)) + { + return filepath; + } + + Uri toUri; + if (!Uri.TryCreate(filepath, UriKind.RelativeOrAbsolute, out toUri)) + { + return filepath; + } + if (!toUri.IsAbsoluteUri) + { + return filepath;//already relative... + } + + //Uri fromUri = new Uri(Filepath); + //Uri toUri = new Uri(filepath); + if (fromUri.Scheme != toUri.Scheme) + { + return filepath.ToLower(); + } + Uri relativeUri = fromUri.MakeRelativeUri(toUri); + string relativePath = Uri.UnescapeDataString(relativeUri.ToString()); + if (string.Equals(toUri.Scheme, Uri.UriSchemeFile, StringComparison.OrdinalIgnoreCase)) + { + relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + return relativePath.ToLower(); + } + public string GetFullFilePath(string relpath) + { + if (string.IsNullOrEmpty(Filepath)) return relpath; + string projfldr = new FileInfo(Filepath).DirectoryName + "\\"; + string cpath = Path.Combine(projfldr, relpath); + string apath = Path.GetFullPath(cpath); + return apath; + } + public string GetFullFilePath(string relpath, string basepath) + { + if (string.IsNullOrEmpty(basepath)) return relpath; + string basefldr = new FileInfo(basepath).DirectoryName + "\\"; + string cpath = Path.Combine(basefldr, relpath); + string apath = Path.GetFullPath(cpath); + return apath; + } + + + + public YmapFile AddYmapFile(string filename) + { + YmapFile ymap = new YmapFile(); + ymap.RpfFileEntry = new RpfResourceFileEntry(); + ymap.RpfFileEntry.Name = new FileInfo(filename).Name; + ymap.FilePath = GetFullFilePath(filename); + ymap.Name = ymap.RpfFileEntry.Name; + JenkIndex.Ensure(ymap.Name); + JenkIndex.Ensure(Path.GetFileNameWithoutExtension(ymap.Name)); + JenkIndex.Ensure(filename); + if (!AddYmapFile(ymap)) return null; + return ymap; + } + public bool AddYmapFile(YmapFile ymap) + { + string relpath = GetRelativePath(ymap.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = ymap.Name; + if (YmapFilenames.Contains(relpath)) return false; + YmapFilenames.Add(relpath); + YmapFiles.Add(ymap); + return true; + } + public void RemoveYmapFile(YmapFile ymap) + { + if (ymap == null) return; + var relpath = GetRelativePath(ymap.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = ymap.Name; + YmapFiles.Remove(ymap); + YmapFilenames.Remove(relpath); + HasChanged = true; + } + public bool ContainsYmap(string filename) + { + bool found = false; + filename = filename.ToLower(); + foreach (var ymapfn in YmapFilenames) + { + if (ymapfn == filename) + { + found = true; + break; + } + } + return found; + } + public bool ContainsYmap(YmapFile ymap) + { + foreach (var f in YmapFiles) + { + if (f == ymap) return true; + } + return false; + } + public bool RenameYmap(string oldfilename, string newfilename) + { + oldfilename = oldfilename.ToLower(); + newfilename = newfilename.ToLower(); + for (int i = 0; i < YmapFilenames.Count; i++) + { + if (YmapFilenames[i] == oldfilename) + { + YmapFilenames[i] = newfilename; + HasChanged = true; + return true; + } + } + return false; + } + + + public YndFile AddYndFile(string filename) + { + YndFile ynd = new YndFile(); + ynd.RpfFileEntry = new RpfResourceFileEntry(); + ynd.RpfFileEntry.Name = new FileInfo(filename).Name; + ynd.FilePath = GetFullFilePath(filename); + ynd.Name = ynd.RpfFileEntry.Name; + if (!AddYndFile(ynd)) return null; + return ynd; + } + public bool AddYndFile(YndFile ynd) + { + string relpath = GetRelativePath(ynd.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = ynd.Name; + if (YndFilenames.Contains(relpath)) return false; + YndFilenames.Add(relpath); + YndFiles.Add(ynd); + return true; + } + public void RemoveYndFile(YndFile ynd) + { + if (ynd == null) return; + var relpath = GetRelativePath(ynd.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = ynd.Name; + YndFiles.Remove(ynd); + YndFilenames.Remove(relpath); + HasChanged = true; + } + public bool ContainsYnd(string filename) + { + bool found = false; + filename = filename.ToLower(); + foreach (var yndfn in YndFilenames) + { + if (yndfn == filename) + { + found = true; + break; + } + } + return found; + } + public bool ContainsYnd(YndFile ynd) + { + foreach (var f in YndFiles) + { + if (f == ynd) return true; + } + return false; + } + public bool RenameYnd(string oldfilename, string newfilename) + { + oldfilename = oldfilename.ToLower(); + newfilename = newfilename.ToLower(); + for (int i = 0; i < YndFilenames.Count; i++) + { + if (YndFilenames[i] == oldfilename) + { + YndFilenames[i] = newfilename; + HasChanged = true; + return true; + } + } + return false; + } + + + public YnvFile AddYnvFile(string filename) + { + YnvFile ynv = new YnvFile(); + ynv.RpfFileEntry = new RpfResourceFileEntry(); + ynv.RpfFileEntry.Name = new FileInfo(filename).Name; + ynv.FilePath = GetFullFilePath(filename); + ynv.Name = ynv.RpfFileEntry.Name; + if (!AddYnvFile(ynv)) return null; + return ynv; + } + public bool AddYnvFile(YnvFile ynv) + { + string relpath = GetRelativePath(ynv.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = ynv.Name; + if (YnvFilenames.Contains(relpath)) return false; + YnvFilenames.Add(relpath); + YnvFiles.Add(ynv); + return true; + } + public void RemoveYnvFile(YnvFile ynv) + { + if (ynv == null) return; + var relpath = GetRelativePath(ynv.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = ynv.Name; + YnvFiles.Remove(ynv); + YnvFilenames.Remove(relpath); + HasChanged = true; + } + public bool ContainsYnv(string filename) + { + bool found = false; + filename = filename.ToLower(); + foreach (var ynvfn in YnvFilenames) + { + if (ynvfn == filename) + { + found = true; + break; + } + } + return found; + } + public bool ContainsYnv(YnvFile ynv) + { + foreach (var f in YnvFiles) + { + if (f == ynv) return true; + } + return false; + } + public bool RenameYnv(string oldfilename, string newfilename) + { + oldfilename = oldfilename.ToLower(); + newfilename = newfilename.ToLower(); + for (int i = 0; i < YnvFilenames.Count; i++) + { + if (YnvFilenames[i] == oldfilename) + { + YnvFilenames[i] = newfilename; + HasChanged = true; + return true; + } + } + return false; + } + + + public TrainTrack AddTrainsFile(string filename) + { + TrainTrack track = new TrainTrack(); + track.RpfFileEntry = new RpfResourceFileEntry(); + track.RpfFileEntry.Name = new FileInfo(filename).Name; + track.FilePath = GetFullFilePath(filename); + track.Name = track.RpfFileEntry.Name; + if (!AddTrainsFile(track)) return null; + return track; + } + public bool AddTrainsFile(TrainTrack track) + { + string relpath = GetRelativePath(track.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = track.Name; + if (TrainsFilenames.Contains(relpath)) return false; + TrainsFilenames.Add(relpath); + TrainsFiles.Add(track); + return true; + } + public void RemoveTrainsFile(TrainTrack track) + { + if (track == null) return; + var relpath = GetRelativePath(track.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = track.Name; + TrainsFiles.Remove(track); + TrainsFilenames.Remove(relpath); + HasChanged = true; + } + public bool ContainsTrainTrack(string filename) + { + bool found = false; + filename = filename.ToLower(); + foreach (var trainsfn in TrainsFilenames) + { + if (trainsfn == filename) + { + found = true; + break; + } + } + return found; + } + public bool ContainsTrainTrack(TrainTrack track) + { + foreach (var f in TrainsFiles) + { + if (f == track) return true; + } + return false; + } + public bool RenameTrainTrack(string oldfilename, string newfilename) + { + oldfilename = oldfilename.ToLower(); + newfilename = newfilename.ToLower(); + for (int i = 0; i < TrainsFilenames.Count; i++) + { + if (TrainsFilenames[i] == oldfilename) + { + TrainsFilenames[i] = newfilename; + HasChanged = true; + return true; + } + } + return false; + } + + + public YmtFile AddScenarioFile(string filename) + { + YmtFile scenario = new YmtFile(); + scenario.RpfFileEntry = new RpfResourceFileEntry(); + scenario.RpfFileEntry.Name = new FileInfo(filename).Name; + scenario.FilePath = GetFullFilePath(filename); + scenario.Name = scenario.RpfFileEntry.Name; + scenario.ContentType = YmtFileContentType.ScenarioPointRegion; + scenario.FileFormat = YmtFileFormat.RSC; + if (!AddScenarioFile(scenario)) return null; + return scenario; + } + public bool AddScenarioFile(YmtFile ymt) + { + string relpath = GetRelativePath(ymt.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = ymt.Name; + if (ScenarioFilenames.Contains(relpath)) return false; + ScenarioFilenames.Add(relpath); + ScenarioFiles.Add(ymt); + return true; + } + public void RemoveScenarioFile(YmtFile ymt) + { + if (ymt == null) return; + var relpath = GetRelativePath(ymt.FilePath); + if (string.IsNullOrEmpty(relpath)) relpath = ymt.Name; + ScenarioFiles.Remove(ymt); + ScenarioFilenames.Remove(relpath); + HasChanged = true; + } + public bool ContainsScenario(string filename) + { + bool found = false; + filename = filename.ToLower(); + foreach (var scenariofn in ScenarioFilenames) + { + if (scenariofn == filename) + { + found = true; + break; + } + } + return found; + } + public bool ContainsScenario(YmtFile ymt) + { + foreach (var f in ScenarioFiles) + { + if (f == ymt) return true; + } + return false; + } + public bool RenameScenario(string oldfilename, string newfilename) + { + oldfilename = oldfilename.ToLower(); + newfilename = newfilename.ToLower(); + for (int i = 0; i < ScenarioFilenames.Count; i++) + { + if (ScenarioFilenames[i] == oldfilename) + { + ScenarioFilenames[i] = newfilename; + HasChanged = true; + return true; + } + } + return false; + } + + + } +} diff --git a/Project/UndoStep.cs b/Project/UndoStep.cs new file mode 100644 index 0000000..a67c8c6 --- /dev/null +++ b/Project/UndoStep.cs @@ -0,0 +1,604 @@ +using CodeWalker.GameFiles; +using CodeWalker.World; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.Project +{ + public abstract class UndoStep + { + + //revert the object to the state marked at the start of this step + public abstract void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel); + + //revert the object to the state marked at the end of this step + public abstract void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel); + + } + + + public class EntityPositionUndoStep : UndoStep + { + public YmapEntityDef Entity { get; set; } + public Vector3 StartPosition { get; set; } + public Vector3 EndPosition { get; set; } + + public EntityPositionUndoStep(YmapEntityDef ent, Vector3 startpos) + { + Entity = ent; + StartPosition = startpos; + EndPosition = ent?.WidgetPosition ?? Vector3.Zero; + } + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Vector3 p) + { + Entity?.SetPositionFromWidget(p); + + if (Entity != sel.EntityDef) wf.SelectEntity(Entity); + wf.SetWidgetPosition(Entity.WidgetPosition); + if ((Entity != null) && (pf != null)) + { + pf.OnWorldEntityModified(Entity); + } + } + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartPosition); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndPosition); + } + + public override string ToString() + { + return (Entity?._CEntityDef.archetypeName.ToString() ?? "") + ": Position"; + } + } + + public class EntityRotationUndoStep : UndoStep + { + public YmapEntityDef Entity { get; set; } + public Quaternion StartRotation { get; set; } + public Quaternion EndRotation { get; set; } + + public EntityRotationUndoStep(YmapEntityDef ent, Quaternion startrot) + { + Entity = ent; + StartRotation = startrot; + EndRotation = ent?.WidgetOrientation ?? Quaternion.Identity; + } + + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Quaternion q) + { + Entity?.SetOrientationFromWidget(q); + + if (Entity != sel.EntityDef) wf.SelectEntity(Entity); + wf.SetWidgetRotation(q); + if ((Entity != null) && (pf != null)) + { + pf.OnWorldEntityModified(Entity); + } + } + + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartRotation); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndRotation); + } + + public override string ToString() + { + return (Entity?._CEntityDef.archetypeName.ToString() ?? "") + ": Rotation"; + } + } + + public class EntityScaleUndoStep : UndoStep + { + public YmapEntityDef Entity { get; set; } + public Vector3 StartScale { get; set; } + public Vector3 EndScale { get; set; } + + public EntityScaleUndoStep(YmapEntityDef ent, Vector3 startscale) + { + Entity = ent; + StartScale = startscale; + EndScale = ent?.Scale ?? Vector3.One; + } + + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Vector3 s) + { + Entity?.SetScale(s); + + if (Entity != sel.EntityDef) wf.SelectEntity(Entity); + wf.SetWidgetScale(s); + if ((Entity != null) && (pf != null)) + { + pf.OnWorldEntityModified(Entity); + } + } + + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartScale); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndScale); + } + + public override string ToString() + { + return (Entity?._CEntityDef.archetypeName.ToString() ?? "") + ": Scale"; + } + } + + + public class EntityPivotPositionUndoStep : UndoStep + { + public YmapEntityDef Entity { get; set; } + public Vector3 StartPosition { get; set; } + public Vector3 EndPosition { get; set; } + + public EntityPivotPositionUndoStep(YmapEntityDef ent, Vector3 startpos) + { + Entity = ent; + StartPosition = startpos; + EndPosition = ent?.WidgetPosition ?? Vector3.Zero; + } + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Vector3 p) + { + Entity?.SetPivotPositionFromWidget(p); + + if (Entity != sel.EntityDef) wf.SelectEntity(Entity); + wf.SetWidgetPosition(p); + if ((Entity != null) && (pf != null)) + { + pf.OnWorldEntityModified(Entity); + } + } + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartPosition); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndPosition); + } + + public override string ToString() + { + return (Entity?._CEntityDef.archetypeName.ToString() ?? "") + ": Pivot Position"; + } + } + + public class EntityPivotRotationUndoStep : UndoStep + { + public YmapEntityDef Entity { get; set; } + public Quaternion StartRotation { get; set; } + public Quaternion EndRotation { get; set; } + + public EntityPivotRotationUndoStep(YmapEntityDef ent, Quaternion startrot) + { + Entity = ent; + StartRotation = startrot; + EndRotation = ent?.WidgetOrientation ?? Quaternion.Identity; + } + + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Quaternion q) + { + Entity?.SetPivotOrientationFromWidget(q); + + if (Entity != sel.EntityDef) wf.SelectEntity(Entity); + wf.SetWidgetRotation(q); + if ((Entity != null) && (pf != null)) + { + pf.OnWorldEntityModified(Entity); + } + } + + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartRotation); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndRotation); + } + + public override string ToString() + { + return (Entity?._CEntityDef.archetypeName.ToString() ?? "") + ": Pivot Rotation"; + } + } + + + + public class CarGenPositionUndoStep : UndoStep + { + public YmapCarGen CarGen { get; set; } + public Vector3 StartPosition { get; set; } + public Vector3 EndPosition { get; set; } + + public CarGenPositionUndoStep(YmapCarGen cargen, Vector3 startpos) + { + CarGen = cargen; + StartPosition = startpos; + EndPosition = cargen?.Position ?? Vector3.Zero; + } + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Vector3 p) + { + CarGen?.SetPosition(p); + + if (CarGen != sel.CarGenerator) wf.SelectCarGen(CarGen); + wf.SetWidgetPosition(p); + if ((CarGen != null) && (pf != null)) + { + pf.OnWorldCarGenModified(CarGen); + } + } + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartPosition); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndPosition); + } + + public override string ToString() + { + return "CarGen " + (CarGen?._CCarGen.carModel.ToString() ?? "") + ": Position"; + } + } + + public class CarGenRotationUndoStep : UndoStep + { + public YmapCarGen CarGen { get; set; } + public Quaternion StartRotation { get; set; } + public Quaternion EndRotation { get; set; } + + public CarGenRotationUndoStep(YmapCarGen cargen, Quaternion startrot) + { + CarGen = cargen; + StartRotation = startrot; + EndRotation = cargen?.Orientation ?? Quaternion.Identity; + } + + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Quaternion q) + { + CarGen?.SetOrientation(q); + + if (CarGen != sel.CarGenerator) wf.SelectCarGen(CarGen); + wf.SetWidgetRotation(q); + if ((CarGen != null) && (pf != null)) + { + pf.OnWorldCarGenModified(CarGen); + } + } + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartRotation); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndRotation); + } + + public override string ToString() + { + return "CarGen " + (CarGen?._CCarGen.carModel.ToString() ?? "") + ": Rotation"; + } + } + + public class CarGenScaleUndoStep : UndoStep + { + public YmapCarGen CarGen { get; set; } + public Vector3 StartScale { get; set; } + public Vector3 EndScale { get; set; } + + public CarGenScaleUndoStep(YmapCarGen cargen, Vector3 startscale) + { + CarGen = cargen; + StartScale = startscale; + EndScale = new Vector3(cargen?._CCarGen.perpendicularLength ?? 1.0f); + } + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Vector3 s) + { + CarGen?.SetScale(s); + + if (CarGen != sel.CarGenerator) wf.SelectCarGen(CarGen); + wf.SetWidgetScale(s); + if ((CarGen != null) && (pf != null)) + { + pf.OnWorldCarGenModified(CarGen); + } + } + + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartScale); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndScale); + } + + public override string ToString() + { + return "CarGen " + (CarGen?._CCarGen.carModel.ToString() ?? "") + ": Scale"; + } + } + + + + public class PathNodePositionUndoStep : UndoStep + { + public YndNode PathNode { get; set; } + public Vector3 StartPosition { get; set; } + public Vector3 EndPosition { get; set; } + + public PathNodePositionUndoStep(YndNode pathnode, Vector3 startpos, WorldForm wf, ProjectForm pf) + { + PathNode = pathnode; + StartPosition = startpos; + EndPosition = pathnode?.Position ?? Vector3.Zero; + + UpdateGraphics(wf, pf); //forces the update of the path graphics when it's moved... + } + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Vector3 p) + { + PathNode?.SetPosition(p); + + if (PathNode != sel.PathNode) + { + if (sel.PathLink != null) + { + wf.SelectPathLink(sel.PathLink); + } + else + { + wf.SelectPathNode(PathNode); + } + } + wf.SetWidgetPosition(p); + + + UpdateGraphics(wf, pf); + } + + private void UpdateGraphics(WorldForm wf, ProjectForm pf) + { + if (PathNode != null) + { + //Ynd graphics needs to be updated..... + wf.UpdatePathNodeGraphics(PathNode, false); + if (pf != null) //make sure to update the project form UI.. + { + pf.OnWorldPathNodeModified(PathNode, null); + } + } + } + + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartPosition); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndPosition); + } + + public override string ToString() + { + return "PathNode " + (PathNode?._RawData.ToString() ?? "") + ": Position"; + } + } + + + public class TrainTrackNodePositionUndoStep : UndoStep + { + public TrainTrackNode Node { get; set; } + public Vector3 StartPosition { get; set; } + public Vector3 EndPosition { get; set; } + + public TrainTrackNodePositionUndoStep(TrainTrackNode node, Vector3 startpos, WorldForm wf, ProjectForm pf) + { + Node = node; + StartPosition = startpos; + EndPosition = node?.Position ?? Vector3.Zero; + + UpdateGraphics(wf, pf); //forces the update of the path graphics when it's moved... + } + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Vector3 p) + { + Node?.SetPosition(p); + + if (Node != sel.TrainTrackNode) + { + wf.SelectTrainTrackNode(Node); + } + wf.SetWidgetPosition(p); + + + UpdateGraphics(wf, pf); + } + + private void UpdateGraphics(WorldForm wf, ProjectForm pf) + { + if (Node != null) + { + //Ynd graphics needs to be updated..... + wf.UpdateTrainTrackNodeGraphics(Node, false); + if (pf != null) //make sure to update the project form UI.. + { + pf.OnWorldTrainNodeModified(Node); + } + } + } + + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartPosition); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndPosition); + } + + public override string ToString() + { + return "TrainTrackNode " + (Node?.ToString() ?? "") + ": Position"; + } + } + + + + + public class ScenarioNodePositionUndoStep : UndoStep + { + public ScenarioNode ScenarioNode { get; set; } + public Vector3 StartPosition { get; set; } + public Vector3 EndPosition { get; set; } + + public ScenarioNodePositionUndoStep(ScenarioNode node, Vector3 startpos, WorldForm wf, ProjectForm pf) + { + ScenarioNode = node; + StartPosition = startpos; + EndPosition = node?.Position ?? Vector3.Zero; + + UpdateGraphics(wf, pf); //forces the update of the path graphics when it's moved... + } + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Vector3 p) + { + ScenarioNode?.SetPosition(p); + + if (ScenarioNode != sel.ScenarioNode) wf.SelectScenarioNode(ScenarioNode); + wf.SetWidgetPosition(p); + + UpdateGraphics(wf, pf); + } + + private void UpdateGraphics(WorldForm wf, ProjectForm pf) + { + if (ScenarioNode != null) + { + //Ymt graphics needs to be updated..... + wf.UpdateScenarioGraphics(ScenarioNode.Ymt, false); + if (pf != null) //make sure to update the project form UI.. + { + pf.OnWorldScenarioNodeModified(ScenarioNode); + } + } + } + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartPosition); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndPosition); + } + + public override string ToString() + { + return ScenarioNode.ToString() + ": Position"; + } + } + + public class ScenarioNodeRotationUndoStep : UndoStep + { + public ScenarioNode ScenarioNode { get; set; } + public Quaternion StartRotation { get; set; } + public Quaternion EndRotation { get; set; } + + public ScenarioNodeRotationUndoStep(ScenarioNode node, Quaternion startrot, WorldForm wf, ProjectForm pf) + { + ScenarioNode = node; + StartRotation = startrot; + EndRotation = node?.Orientation ?? Quaternion.Identity; + + //UpdateGraphics(wf, pf); + } + + + private void Update(WorldForm wf, ProjectForm pf, ref MapSelection sel, Quaternion q) + { + ScenarioNode?.SetOrientation(q); + + if (ScenarioNode != sel.ScenarioNode) wf.SelectScenarioNode(ScenarioNode); + wf.SetWidgetRotation(q); + + //UpdateGraphics(wf, pf); + } + + private void UpdateGraphics(WorldForm wf, ProjectForm pf) + { + ////this function shouldn't actually be needed for rotating... + //if (ScenarioNode != null) + //{ + // //Ymt graphics needs to be updated..... + // wf.UpdateScenarioGraphics(ScenarioNode.Ymt, false); + // if (pf != null) //make sure to update the project form UI.. + // { + // pf.OnWorldScenarioNodeModified(ScenarioNode); + // } + //} + } + + public override void Undo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, StartRotation); + } + + public override void Redo(WorldForm wf, ProjectForm pf, ref MapSelection sel) + { + Update(wf, pf, ref sel, EndRotation); + } + + public override string ToString() + { + return ScenarioNode.ToString() + ": Rotation"; + } + } + +} diff --git a/ProjectForm.Designer.cs b/ProjectForm.Designer.cs new file mode 100644 index 0000000..2ea1907 --- /dev/null +++ b/ProjectForm.Designer.cs @@ -0,0 +1,8652 @@ +namespace CodeWalker +{ + partial class ProjectForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProjectForm)); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.ProjectTreeView = new System.Windows.Forms.TreeView(); + this.MainTabControl = new System.Windows.Forms.TabControl(); + this.ProjectTabPage = new System.Windows.Forms.TabPage(); + this.ProjectPanel = new System.Windows.Forms.Panel(); + this.ProjectHideMapCheckBox = new System.Windows.Forms.CheckBox(); + this.ProjectShowEntitiesCheckBox = new System.Windows.Forms.CheckBox(); + this.label1 = new System.Windows.Forms.Label(); + this.ProjectVersionLabel = new System.Windows.Forms.Label(); + this.ProjectNameTextBox = new System.Windows.Forms.TextBox(); + this.YmapTabPage = new System.Windows.Forms.TabPage(); + this.YmapTabControl = new System.Windows.Forms.TabControl(); + this.YmapYmapTabPage = new System.Windows.Forms.TabPage(); + this.YmapPanel = new System.Windows.Forms.Panel(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.YmapCFlagsGrassCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsCriticalCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsDistLightsCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsLODLightsCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsPhysicsCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsOcclusionCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsInteriorCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsSLODCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsSLOD2CheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsLODCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapCFlagsHDCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapContentFlagsTextBox = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.YmapCalculateFlagsButton = new System.Windows.Forms.Button(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.YmapFlagsLODCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapFlagsScriptedCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapFlagsTextBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.label12 = new System.Windows.Forms.Label(); + this.YmapPhysicsDictionariesTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.YmapProjectPathTextBox = new System.Windows.Forms.TextBox(); + this.label30 = new System.Windows.Forms.Label(); + this.YmapFileLocationTextBox = new System.Windows.Forms.TextBox(); + this.label29 = new System.Windows.Forms.Label(); + this.YmapCalculateExtentsButton = new System.Windows.Forms.Button(); + this.YmapStreamingExtentsMaxTextBox = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.YmapStreamingExtentsMinTextBox = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); + this.YmapEntitiesExtentsMaxTextBox = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.YmapEntitiesExtentsMinTextBox = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.YmapParentHashLabel = new System.Windows.Forms.Label(); + this.YmapNameHashLabel = new System.Windows.Forms.Label(); + this.YmapParentTextBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.YmapNameTextBox = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.YmapEntityTabPage = new System.Windows.Forms.TabPage(); + this.EntityPanel = new System.Windows.Forms.Panel(); + this.EntityTabControl = new System.Windows.Forms.TabControl(); + this.EntityGeneralTabPage = new System.Windows.Forms.TabPage(); + this.label13 = new System.Windows.Forms.Label(); + this.label28 = new System.Windows.Forms.Label(); + this.EntityDeleteButton = new System.Windows.Forms.Button(); + this.EntityTintValueTextBox = new System.Windows.Forms.TextBox(); + this.EntityAddToProjectButton = new System.Windows.Forms.Button(); + this.label27 = new System.Windows.Forms.Label(); + this.label16 = new System.Windows.Forms.Label(); + this.EntityArtificialAOTextBox = new System.Windows.Forms.TextBox(); + this.EntityPositionTextBox = new System.Windows.Forms.TextBox(); + this.label26 = new System.Windows.Forms.Label(); + this.EntityNormalizeRotationButton = new System.Windows.Forms.Button(); + this.EntityAOMultiplierTextBox = new System.Windows.Forms.TextBox(); + this.EntityGuidTextBox = new System.Windows.Forms.TextBox(); + this.EntityPriorityLevelComboBox = new System.Windows.Forms.ComboBox(); + this.label24 = new System.Windows.Forms.Label(); + this.EntityGoToButton = new System.Windows.Forms.Button(); + this.label17 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.EntityRotationTextBox = new System.Windows.Forms.TextBox(); + this.EntityFlagsTextBox = new System.Windows.Forms.TextBox(); + this.label18 = new System.Windows.Forms.Label(); + this.EntityLodLevelComboBox = new System.Windows.Forms.ComboBox(); + this.label14 = new System.Windows.Forms.Label(); + this.label23 = new System.Windows.Forms.Label(); + this.EntityScaleXYTextBox = new System.Windows.Forms.TextBox(); + this.label22 = new System.Windows.Forms.Label(); + this.EntityArchetypeHashLabel = new System.Windows.Forms.Label(); + this.EntityChildLodDistTextBox = new System.Windows.Forms.TextBox(); + this.label19 = new System.Windows.Forms.Label(); + this.label21 = new System.Windows.Forms.Label(); + this.EntityScaleZTextBox = new System.Windows.Forms.TextBox(); + this.EntityLodDistTextBox = new System.Windows.Forms.TextBox(); + this.EntityArchetypeTextBox = new System.Windows.Forms.TextBox(); + this.EntityLodTabPage = new System.Windows.Forms.TabPage(); + this.label20 = new System.Windows.Forms.Label(); + this.EntityParentIndexTextBox = new System.Windows.Forms.TextBox(); + this.EntityNumChildrenTextBox = new System.Windows.Forms.TextBox(); + this.label25 = new System.Windows.Forms.Label(); + this.EntityExtensionsTabPage = new System.Windows.Forms.TabPage(); + this.EntityPivotTabPage = new System.Windows.Forms.TabPage(); + this.label95 = new System.Windows.Forms.Label(); + this.EntityPivotEditCheckBox = new System.Windows.Forms.CheckBox(); + this.label93 = new System.Windows.Forms.Label(); + this.EntityPivotPositionTextBox = new System.Windows.Forms.TextBox(); + this.EntityPivotRotationNormalizeButton = new System.Windows.Forms.Button(); + this.label94 = new System.Windows.Forms.Label(); + this.EntityPivotRotationTextBox = new System.Windows.Forms.TextBox(); + this.YmapCarGenTabPage = new System.Windows.Forms.TabPage(); + this.CarGenPanel = new System.Windows.Forms.Panel(); + this.CarDeleteButton = new System.Windows.Forms.Button(); + this.CarAddToProjectButton = new System.Windows.Forms.Button(); + this.label44 = new System.Windows.Forms.Label(); + this.CarLiveryTextBox = new System.Windows.Forms.TextBox(); + this.label43 = new System.Windows.Forms.Label(); + this.CarBodyColorRemap4TextBox = new System.Windows.Forms.TextBox(); + this.label42 = new System.Windows.Forms.Label(); + this.CarBodyColorRemap3TextBox = new System.Windows.Forms.TextBox(); + this.label41 = new System.Windows.Forms.Label(); + this.CarBodyColorRemap2TextBox = new System.Windows.Forms.TextBox(); + this.CarPopGroupTextBox = new System.Windows.Forms.TextBox(); + this.label39 = new System.Windows.Forms.Label(); + this.CarPopGroupHashLabel = new System.Windows.Forms.Label(); + this.label38 = new System.Windows.Forms.Label(); + this.CarBodyColorRemap1TextBox = new System.Windows.Forms.TextBox(); + this.label37 = new System.Windows.Forms.Label(); + this.CarFlagsTextBox = new System.Windows.Forms.TextBox(); + this.CarPerpendicularLengthTextBox = new System.Windows.Forms.TextBox(); + this.label36 = new System.Windows.Forms.Label(); + this.CarOrientYTextBox = new System.Windows.Forms.TextBox(); + this.label34 = new System.Windows.Forms.Label(); + this.CarOrientXTextBox = new System.Windows.Forms.TextBox(); + this.label35 = new System.Windows.Forms.Label(); + this.CarModelTextBox = new System.Windows.Forms.TextBox(); + this.label32 = new System.Windows.Forms.Label(); + this.CarModelHashLabel = new System.Windows.Forms.Label(); + this.CarGoToButton = new System.Windows.Forms.Button(); + this.CarPositionTextBox = new System.Windows.Forms.TextBox(); + this.label31 = new System.Windows.Forms.Label(); + this.YndTabPage = new System.Windows.Forms.TabPage(); + this.YndTabControl = new System.Windows.Forms.TabControl(); + this.YndYndTabPage = new System.Windows.Forms.TabPage(); + this.YndPanel = new System.Windows.Forms.Panel(); + this.label88 = new System.Windows.Forms.Label(); + this.YndAreaIDYUpDown = new System.Windows.Forms.NumericUpDown(); + this.label87 = new System.Windows.Forms.Label(); + this.YndAreaIDXUpDown = new System.Windows.Forms.NumericUpDown(); + this.label48 = new System.Windows.Forms.Label(); + this.YndProjectPathTextBox = new System.Windows.Forms.TextBox(); + this.label46 = new System.Windows.Forms.Label(); + this.YndFilePathTextBox = new System.Windows.Forms.TextBox(); + this.label47 = new System.Windows.Forms.Label(); + this.YndTotalNodesLabel = new System.Windows.Forms.Label(); + this.YndPedNodesUpDown = new System.Windows.Forms.NumericUpDown(); + this.label45 = new System.Windows.Forms.Label(); + this.YndVehicleNodesUpDown = new System.Windows.Forms.NumericUpDown(); + this.label40 = new System.Windows.Forms.Label(); + this.YndAreaIDInfoLabel = new System.Windows.Forms.Label(); + this.label33 = new System.Windows.Forms.Label(); + this.YndRpfPathTextBox = new System.Windows.Forms.TextBox(); + this.YndNodeTabPage = new System.Windows.Forms.TabPage(); + this.YndNodePanel = new System.Windows.Forms.Panel(); + this.PathNodeTabControl = new System.Windows.Forms.TabControl(); + this.PathNodePropertiesTabPage = new System.Windows.Forms.TabPage(); + this.PathNodeFlags5GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeFlags52CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags53CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags51CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags5UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeFlags4GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeFlags45CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags46CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags47CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags48CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags42UpDown = new System.Windows.Forms.NumericUpDown(); + this.label71 = new System.Windows.Forms.Label(); + this.PathNodeFlags41CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags4UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeFlags4Label = new System.Windows.Forms.Label(); + this.PathNodeFlags3GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeFlags32UpDown = new System.Windows.Forms.NumericUpDown(); + this.label70 = new System.Windows.Forms.Label(); + this.PathNodeFlags31CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags3UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeFlags3Label = new System.Windows.Forms.Label(); + this.PathNodeFlags2GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeFlags21CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags28CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags22CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags27CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags23CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags26CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags24CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags25CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags2UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeFlags2Label = new System.Windows.Forms.Label(); + this.PathNodeFlags1GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeFlags11CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags18CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags12CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags17CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags13CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags16CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags14CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags15CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags1UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeFlags1Label = new System.Windows.Forms.Label(); + this.PathNodeFlags0GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeFlags01CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags08CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags02CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags07CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags03CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags06CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags04CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags05CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeFlags0UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeFlags0Label = new System.Windows.Forms.Label(); + this.PathNodeDeleteButton = new System.Windows.Forms.Button(); + this.PathNodeAreaIDUpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeAddToProjectButton = new System.Windows.Forms.Button(); + this.label49 = new System.Windows.Forms.Label(); + this.label50 = new System.Windows.Forms.Label(); + this.label68 = new System.Windows.Forms.Label(); + this.PathNodeNodeIDUpDown = new System.Windows.Forms.NumericUpDown(); + this.label52 = new System.Windows.Forms.Label(); + this.PathNodeStreetHashTextBox = new System.Windows.Forms.TextBox(); + this.PathNodeGoToButton = new System.Windows.Forms.Button(); + this.PathNodeStreetNameLabel = new System.Windows.Forms.Label(); + this.PathNodePositionTextBox = new System.Windows.Forms.TextBox(); + this.label55 = new System.Windows.Forms.Label(); + this.PathNodeLinksTabPage = new System.Windows.Forms.TabPage(); + this.splitContainer2 = new System.Windows.Forms.SplitContainer(); + this.PathNodeRemoveLinkButton = new System.Windows.Forms.Button(); + this.PathNodeAddLinkButton = new System.Windows.Forms.Button(); + this.PathNodeLinksListBox = new System.Windows.Forms.ListBox(); + this.PathNodeLinkCountLabel = new System.Windows.Forms.Label(); + this.PathNodeLinkPanel = new System.Windows.Forms.Panel(); + this.PathLinkFlags2GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeLinkFlags21CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeLinkFlags22CheckBox = new System.Windows.Forms.CheckBox(); + this.label53 = new System.Windows.Forms.Label(); + this.PathNodeLinkFwdLanesUpDown = new System.Windows.Forms.NumericUpDown(); + this.label56 = new System.Windows.Forms.Label(); + this.PathNodeLinkBackLanesUpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeLinkFlags2UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeLinkFlags2Label = new System.Windows.Forms.Label(); + this.PathLinkFlags1GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeLinkOffsetSizeUpDown = new System.Windows.Forms.NumericUpDown(); + this.label61 = new System.Windows.Forms.Label(); + this.PathNodeLinkFlags11CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeLinkFlags18CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeLinkFlags12CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeLinkFlags13CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeLinkFlags14CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeLinkFlags1UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeLinkFlags1Label = new System.Windows.Forms.Label(); + this.PathLinkFlags0GroupBox = new System.Windows.Forms.GroupBox(); + this.PathNodeLinkFlags04UpDown = new System.Windows.Forms.NumericUpDown(); + this.label60 = new System.Windows.Forms.Label(); + this.PathNodeLinkFlags03UpDown = new System.Windows.Forms.NumericUpDown(); + this.label58 = new System.Windows.Forms.Label(); + this.PathNodeLinkFlags01CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeLinkFlags02CheckBox = new System.Windows.Forms.CheckBox(); + this.PathNodeLinkFlags0UpDown = new System.Windows.Forms.NumericUpDown(); + this.PathNodeLinkFlags0Label = new System.Windows.Forms.Label(); + this.PathNodeLinkageStatusLabel = new System.Windows.Forms.Label(); + this.PathNodeLinkLengthUpDown = new System.Windows.Forms.NumericUpDown(); + this.label57 = new System.Windows.Forms.Label(); + this.PathNodeLinkNodeIDUpDown = new System.Windows.Forms.NumericUpDown(); + this.label51 = new System.Windows.Forms.Label(); + this.PathNodeLinkAreaIDUpDown = new System.Windows.Forms.NumericUpDown(); + this.label54 = new System.Windows.Forms.Label(); + this.PathNodeJunctionTabPage = new System.Windows.Forms.TabPage(); + this.label78 = new System.Windows.Forms.Label(); + this.PathNodeJunctionPanel = new System.Windows.Forms.Panel(); + this.PathNodeJunctionPosYUpDown = new System.Windows.Forms.NumericUpDown(); + this.label59 = new System.Windows.Forms.Label(); + this.PathNodeJunctionPosXUpDown = new System.Windows.Forms.NumericUpDown(); + this.label69 = new System.Windows.Forms.Label(); + this.PathNodeJunctionHeightmapBytesTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.PathNodeJunctionHeightmapDimYUpDown = new System.Windows.Forms.NumericUpDown(); + this.label77 = new System.Windows.Forms.Label(); + this.PathNodeJunctionHeightmapDimXUpDown = new System.Windows.Forms.NumericUpDown(); + this.label76 = new System.Windows.Forms.Label(); + this.PathNodeJunctionMinZUpDown = new System.Windows.Forms.NumericUpDown(); + this.label67 = new System.Windows.Forms.Label(); + this.PathNodeJunctionMaxZUpDown = new System.Windows.Forms.NumericUpDown(); + this.label65 = new System.Windows.Forms.Label(); + this.PathNodeJunctionEnableCheckBox = new System.Windows.Forms.CheckBox(); + this.YnvTabPage = new System.Windows.Forms.TabPage(); + this.YnvTabControl = new System.Windows.Forms.TabControl(); + this.YnvYnvTabPage = new System.Windows.Forms.TabPage(); + this.YnvPanel = new System.Windows.Forms.Panel(); + this.YnvAABBSizeTextBox = new System.Windows.Forms.TextBox(); + this.label91 = new System.Windows.Forms.Label(); + this.label89 = new System.Windows.Forms.Label(); + this.YnvAreaIDYUpDown = new System.Windows.Forms.NumericUpDown(); + this.label90 = new System.Windows.Forms.Label(); + this.YnvAreaIDXUpDown = new System.Windows.Forms.NumericUpDown(); + this.YnvAreaIDInfoLabel = new System.Windows.Forms.Label(); + this.label92 = new System.Windows.Forms.Label(); + this.YnvPolyTabPage = new System.Windows.Forms.TabPage(); + this.YnvPolygonPanel = new System.Windows.Forms.Panel(); + this.YnvPortalTabPage = new System.Windows.Forms.TabPage(); + this.YnvPortalPanel = new System.Windows.Forms.Panel(); + this.TrainsTabPage = new System.Windows.Forms.TabPage(); + this.TrainsTabControl = new System.Windows.Forms.TabControl(); + this.TrainTrackTabPage = new System.Windows.Forms.TabPage(); + this.TrainTrackFilePanel = new System.Windows.Forms.Panel(); + this.TrainTrackInfoLabel = new System.Windows.Forms.Label(); + this.label86 = new System.Windows.Forms.Label(); + this.TrainTrackBrakingDistTextBox = new System.Windows.Forms.TextBox(); + this.label85 = new System.Windows.Forms.Label(); + this.TrainTrackSpeedTextBox = new System.Windows.Forms.TextBox(); + this.TrainTrackMPStopsAtStationsCheckBox = new System.Windows.Forms.CheckBox(); + this.TrainTrackStopsAtStationsCheckBox = new System.Windows.Forms.CheckBox(); + this.TrainTrackIsPingPongCheckBox = new System.Windows.Forms.CheckBox(); + this.label84 = new System.Windows.Forms.Label(); + this.TrainTrackConfigNameTextBox = new System.Windows.Forms.TextBox(); + this.label83 = new System.Windows.Forms.Label(); + this.TrainTrackFilenameTextBox = new System.Windows.Forms.TextBox(); + this.label74 = new System.Windows.Forms.Label(); + this.TrainTrackProjectPathTextBox = new System.Windows.Forms.TextBox(); + this.label79 = new System.Windows.Forms.Label(); + this.TrainTrackFilePathTextBox = new System.Windows.Forms.TextBox(); + this.label80 = new System.Windows.Forms.Label(); + this.TrainTrackRpfPathTextBox = new System.Windows.Forms.TextBox(); + this.TrainNodeTabPage = new System.Windows.Forms.TabPage(); + this.TrainNodePanel = new System.Windows.Forms.Panel(); + this.TrainNodeTypeComboBox = new System.Windows.Forms.ComboBox(); + this.label82 = new System.Windows.Forms.Label(); + this.TrainNodeDeleteButton = new System.Windows.Forms.Button(); + this.TrainNodeAddToProjectButton = new System.Windows.Forms.Button(); + this.TrainNodeGoToButton = new System.Windows.Forms.Button(); + this.TrainNodePositionTextBox = new System.Windows.Forms.TextBox(); + this.label81 = new System.Windows.Forms.Label(); + this.ScenarioTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioTabControl = new System.Windows.Forms.TabControl(); + this.ScenarioYmtTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioYmtPanel = new System.Windows.Forms.Panel(); + this.ScenarioYmtExtentsMaxTextBox = new System.Windows.Forms.TextBox(); + this.label103 = new System.Windows.Forms.Label(); + this.ScenarioYmtExtentsMinTextBox = new System.Windows.Forms.TextBox(); + this.label150 = new System.Windows.Forms.Label(); + this.ScenarioYmtGridInfoLabel = new System.Windows.Forms.Label(); + this.ScenarioYmtGridScaleTextBox = new System.Windows.Forms.TextBox(); + this.label96 = new System.Windows.Forms.Label(); + this.ScenarioYmtProjectPathTextBox = new System.Windows.Forms.TextBox(); + this.label66 = new System.Windows.Forms.Label(); + this.ScenarioYmtFileLocationTextBox = new System.Windows.Forms.TextBox(); + this.label72 = new System.Windows.Forms.Label(); + this.ScenarioYmtGridMaxTextBox = new System.Windows.Forms.TextBox(); + this.label73 = new System.Windows.Forms.Label(); + this.ScenarioYmtGridMinTextBox = new System.Windows.Forms.TextBox(); + this.label75 = new System.Windows.Forms.Label(); + this.ScenarioYmtVersionTextBox = new System.Windows.Forms.TextBox(); + this.label64 = new System.Windows.Forms.Label(); + this.ScenarioYmtNameTextBox = new System.Windows.Forms.TextBox(); + this.label63 = new System.Windows.Forms.Label(); + this.ScenarioPointTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioPointOuterPanel = new System.Windows.Forms.Panel(); + this.ScenarioPointCheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioPointPanel = new System.Windows.Forms.Panel(); + this.ScenarioPointImapHashLabel = new System.Windows.Forms.Label(); + this.ScenarioPointImapTextBox = new System.Windows.Forms.TextBox(); + this.label110 = new System.Windows.Forms.Label(); + this.ScenarioPointGroupHashLabel = new System.Windows.Forms.Label(); + this.ScenarioPointGroupTextBox = new System.Windows.Forms.TextBox(); + this.label156 = new System.Windows.Forms.Label(); + this.ScenarioPointInteriorHashLabel = new System.Windows.Forms.Label(); + this.ScenarioPointFlagsCheckedListBox = new System.Windows.Forms.CheckedListBox(); + this.label111 = new System.Windows.Forms.Label(); + this.ScenarioPointDirectionTextBox = new System.Windows.Forms.TextBox(); + this.label97 = new System.Windows.Forms.Label(); + this.ScenarioPointFlagsValueUpDown = new System.Windows.Forms.NumericUpDown(); + this.label109 = new System.Windows.Forms.Label(); + this.ScenarioPointGoToButton = new System.Windows.Forms.Button(); + this.ScenarioPointWaitTimeUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioPointPositionTextBox = new System.Windows.Forms.TextBox(); + this.label62 = new System.Windows.Forms.Label(); + this.label108 = new System.Windows.Forms.Label(); + this.ScenarioPointRadiusUpDown = new System.Windows.Forms.NumericUpDown(); + this.label107 = new System.Windows.Forms.Label(); + this.ScenarioPointSpOnlyFlagUpDown = new System.Windows.Forms.NumericUpDown(); + this.label106 = new System.Windows.Forms.Label(); + this.ScenarioPointProbabilityUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioPointInteriorTextBox = new System.Windows.Forms.TextBox(); + this.label102 = new System.Windows.Forms.Label(); + this.label101 = new System.Windows.Forms.Label(); + this.ScenarioPointTimeEndUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioPointTimeStartUpDown = new System.Windows.Forms.NumericUpDown(); + this.label100 = new System.Windows.Forms.Label(); + this.ScenarioPointModelSetComboBox = new System.Windows.Forms.ComboBox(); + this.label99 = new System.Windows.Forms.Label(); + this.ScenarioPointTypeComboBox = new System.Windows.Forms.ComboBox(); + this.label98 = new System.Windows.Forms.Label(); + this.ScenarioPointDeleteButton = new System.Windows.Forms.Button(); + this.ScenarioPointAddToProjectButton = new System.Windows.Forms.Button(); + this.ScenarioEntityTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioEntityDeleteButton = new System.Windows.Forms.Button(); + this.ScenarioEntityPanel = new System.Windows.Forms.Panel(); + this.ScenarioEntityInfoLabel = new System.Windows.Forms.Label(); + this.label114 = new System.Windows.Forms.Label(); + this.ScenarioEntityUnk2UpDown = new System.Windows.Forms.NumericUpDown(); + this.label113 = new System.Windows.Forms.Label(); + this.ScenarioEntityUnk1UpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioEntityTypeHashLabel = new System.Windows.Forms.Label(); + this.ScenarioEntityTypeTextBox = new System.Windows.Forms.TextBox(); + this.label112 = new System.Windows.Forms.Label(); + this.ScenarioEntityGoToButton = new System.Windows.Forms.Button(); + this.ScenarioEntityPositionTextBox = new System.Windows.Forms.TextBox(); + this.label104 = new System.Windows.Forms.Label(); + this.ScenarioEntityAddToProjectButton = new System.Windows.Forms.Button(); + this.ScenarioEntityCheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioEntityPointTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioEntityPointDeleteButton = new System.Windows.Forms.Button(); + this.ScenarioEntityPointAddToProjectButton = new System.Windows.Forms.Button(); + this.ScenarioEntityPointCheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioEntityPointPanel = new System.Windows.Forms.Panel(); + this.ScenarioEntityPointNameHashLabel = new System.Windows.Forms.Label(); + this.ScenarioEntityPointNameTextBox = new System.Windows.Forms.TextBox(); + this.ScenarioEntityPointFlagsCheckedListBox = new System.Windows.Forms.CheckedListBox(); + this.label135 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointFlagsUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioEntityPointShortRangeCheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioEntityPointExtendedRangeCheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioEntityPointHighPriCheckBox = new System.Windows.Forms.CheckBox(); + this.label133 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointEndUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioEntityPointStartUpDown = new System.Windows.Forms.NumericUpDown(); + this.label134 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointRadiusTextBox = new System.Windows.Forms.TextBox(); + this.label132 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointTimeTillPedLeavesTextBox = new System.Windows.Forms.TextBox(); + this.label131 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointProbabilityTextBox = new System.Windows.Forms.TextBox(); + this.label130 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointAvailableInMpSpComboBox = new System.Windows.Forms.ComboBox(); + this.label129 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointRequiredImapHashLabel = new System.Windows.Forms.Label(); + this.ScenarioEntityPointRequiredImapTextBox = new System.Windows.Forms.TextBox(); + this.label128 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointInteriorHashLabel = new System.Windows.Forms.Label(); + this.ScenarioEntityPointInteriorTextBox = new System.Windows.Forms.TextBox(); + this.label126 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointGroupHashLabel = new System.Windows.Forms.Label(); + this.ScenarioEntityPointGroupTextBox = new System.Windows.Forms.TextBox(); + this.label124 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointPedTypeHashLabel = new System.Windows.Forms.Label(); + this.ScenarioEntityPointPedTypeTextBox = new System.Windows.Forms.TextBox(); + this.label122 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointSpawnTypeHashLabel = new System.Windows.Forms.Label(); + this.ScenarioEntityPointSpawnTypeTextBox = new System.Windows.Forms.TextBox(); + this.label120 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointRotationTextBox = new System.Windows.Forms.TextBox(); + this.label118 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointGoToButton = new System.Windows.Forms.Button(); + this.ScenarioEntityPointPositionTextBox = new System.Windows.Forms.TextBox(); + this.label117 = new System.Windows.Forms.Label(); + this.label116 = new System.Windows.Forms.Label(); + this.ScenarioChainTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioChainDeleteButton = new System.Windows.Forms.Button(); + this.ScenarioChainAddToProjectButton = new System.Windows.Forms.Button(); + this.splitContainer3 = new System.Windows.Forms.SplitContainer(); + this.ScenarioChainMoveEdgeDownButton = new System.Windows.Forms.Button(); + this.ScenarioChainMoveEdgeUpButton = new System.Windows.Forms.Button(); + this.label138 = new System.Windows.Forms.Label(); + this.ScenarioChainUnk1UpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioChainRemoveEdgeButton = new System.Windows.Forms.Button(); + this.ScenarioChainAddEdgeButton = new System.Windows.Forms.Button(); + this.ScenarioChainEdgesListBox = new System.Windows.Forms.ListBox(); + this.ScenarioChainEdgeCountLabel = new System.Windows.Forms.Label(); + this.ScenarioChainEdgePanel = new System.Windows.Forms.Panel(); + this.ScenarioChainEdgeNavSpeedComboBox = new System.Windows.Forms.ComboBox(); + this.label137 = new System.Windows.Forms.Label(); + this.ScenarioChainEdgeNavModeComboBox = new System.Windows.Forms.ComboBox(); + this.label136 = new System.Windows.Forms.Label(); + this.ScenarioChainEdgeActionComboBox = new System.Windows.Forms.ComboBox(); + this.label127 = new System.Windows.Forms.Label(); + this.ScenarioChainEdgeNodeIndexToUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioChainEdgeNodeIndexFromUpDown = new System.Windows.Forms.NumericUpDown(); + this.label125 = new System.Windows.Forms.Label(); + this.label121 = new System.Windows.Forms.Label(); + this.ScenarioChainNodeTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioChainNodePanel = new System.Windows.Forms.Panel(); + this.ScenarioChainNodeTypeComboBox = new System.Windows.Forms.ComboBox(); + this.ScenarioChainNodeIndexTextBox = new System.Windows.Forms.TextBox(); + this.label115 = new System.Windows.Forms.Label(); + this.ScenarioChainNodeLastCheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioChainNodeFirstCheckBox = new System.Windows.Forms.CheckBox(); + this.label123 = new System.Windows.Forms.Label(); + this.ScenarioChainNodeUnk1HashLabel = new System.Windows.Forms.Label(); + this.ScenarioChainNodeUnk1TextBox = new System.Windows.Forms.TextBox(); + this.label119 = new System.Windows.Forms.Label(); + this.ScenarioChainNodeGoToButton = new System.Windows.Forms.Button(); + this.ScenarioChainNodePositionTextBox = new System.Windows.Forms.TextBox(); + this.label105 = new System.Windows.Forms.Label(); + this.ScenarioChainNodeDeleteButton = new System.Windows.Forms.Button(); + this.ScenarioChainNodeCheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioChainNodeAddToProjectButton = new System.Windows.Forms.Button(); + this.ScenarioClusterTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioClusterDeleteButton = new System.Windows.Forms.Button(); + this.ScenarioClusterAddToProjectButton = new System.Windows.Forms.Button(); + this.ScenarioClusterCheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioClusterPanel = new System.Windows.Forms.Panel(); + this.ScenarioClusterRadiusTextBox = new System.Windows.Forms.TextBox(); + this.label157 = new System.Windows.Forms.Label(); + this.ScenarioClusterUnk2CheckBox = new System.Windows.Forms.CheckBox(); + this.ScenarioClusterUnk1TextBox = new System.Windows.Forms.TextBox(); + this.label140 = new System.Windows.Forms.Label(); + this.ScenarioClusterGoToButton = new System.Windows.Forms.Button(); + this.ScenarioClusterCenterTextBox = new System.Windows.Forms.TextBox(); + this.label139 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointTabPage = new System.Windows.Forms.TabPage(); + this.ScenarioClusterPointDeleteButton = new System.Windows.Forms.Button(); + this.ScenarioClusterPointAddToProjectButton = new System.Windows.Forms.Button(); + this.ScenarioClusterPointPanel = new System.Windows.Forms.Panel(); + this.ScenarioClusterPointImapHashLabel = new System.Windows.Forms.Label(); + this.ScenarioClusterPointImapTextBox = new System.Windows.Forms.TextBox(); + this.label143 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointGroupHashLabel = new System.Windows.Forms.Label(); + this.ScenarioClusterPointGroupTextBox = new System.Windows.Forms.TextBox(); + this.label141 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointInteriorHashLabel = new System.Windows.Forms.Label(); + this.ScenarioClusterPointFlagsCheckedListBox = new System.Windows.Forms.CheckedListBox(); + this.label142 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointDirectionTextBox = new System.Windows.Forms.TextBox(); + this.label144 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointFlagsUpDown = new System.Windows.Forms.NumericUpDown(); + this.label145 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointGoToButton = new System.Windows.Forms.Button(); + this.ScenarioClusterPointWaitTimeUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioClusterPointPositionTextBox = new System.Windows.Forms.TextBox(); + this.label146 = new System.Windows.Forms.Label(); + this.label147 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointRadiusUpDown = new System.Windows.Forms.NumericUpDown(); + this.label148 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointAnimalFlagUpDown = new System.Windows.Forms.NumericUpDown(); + this.label149 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointProbabilityUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioClusterPointInteriorTextBox = new System.Windows.Forms.TextBox(); + this.label151 = new System.Windows.Forms.Label(); + this.label152 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointTimeEndUpDown = new System.Windows.Forms.NumericUpDown(); + this.ScenarioClusterPointTimeStartUpDown = new System.Windows.Forms.NumericUpDown(); + this.label153 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointModelSetComboBox = new System.Windows.Forms.ComboBox(); + this.label154 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointTypeComboBox = new System.Windows.Forms.ComboBox(); + this.label155 = new System.Windows.Forms.Label(); + this.ScenarioClusterPointCheckBox = new System.Windows.Forms.CheckBox(); + this.TopMenuStrip = new CodeWalker.WinForms.MenuStripFix(); + this.FileMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewYmapMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewYndMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewYnvMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewTrainsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileNewScenarioMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenYmapMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenYndMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenYnvMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenTrainsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileOpenScenarioMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.FileCloseProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.FileSaveProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveProjectAsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveItemMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FileSaveItemAsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YmapMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YmapNameMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.YmapNewEntityMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YmapNewCarGenMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); + this.YmapAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YmapRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YndMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YndNameMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.YndNewNodeMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.YndAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YndRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YnvMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YnvNameMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); + this.YnvNewPolygonMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator(); + this.YnvAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.YnvRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.TrainsMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.TrainsNameMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); + this.TrainsNewNodeMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); + this.TrainsAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.TrainsRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ScenarioMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ScenarioNameMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator(); + this.ScenarioNewPointMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ScenarioNewPointFromSelectedMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ScenarioNewEntityOverrideMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ScenarioNewChainMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ScenarioNewClusterMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator(); + this.ScenarioAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ScenarioRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog(); + this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.ScenarioClusterPointsListBox = new System.Windows.Forms.ListBox(); + this.label158 = new System.Windows.Forms.Label(); + this.ScenarioClusterAddPointButton = new System.Windows.Forms.Button(); + this.label159 = new System.Windows.Forms.Label(); + this.label160 = new System.Windows.Forms.Label(); + this.ScenarioEntityAddPointButton = new System.Windows.Forms.Button(); + this.label161 = new System.Windows.Forms.Label(); + this.ScenarioEntityPointsListBox = new System.Windows.Forms.ListBox(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.MainTabControl.SuspendLayout(); + this.ProjectTabPage.SuspendLayout(); + this.ProjectPanel.SuspendLayout(); + this.YmapTabPage.SuspendLayout(); + this.YmapTabControl.SuspendLayout(); + this.YmapYmapTabPage.SuspendLayout(); + this.YmapPanel.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.YmapEntityTabPage.SuspendLayout(); + this.EntityPanel.SuspendLayout(); + this.EntityTabControl.SuspendLayout(); + this.EntityGeneralTabPage.SuspendLayout(); + this.EntityLodTabPage.SuspendLayout(); + this.EntityPivotTabPage.SuspendLayout(); + this.YmapCarGenTabPage.SuspendLayout(); + this.CarGenPanel.SuspendLayout(); + this.YndTabPage.SuspendLayout(); + this.YndTabControl.SuspendLayout(); + this.YndYndTabPage.SuspendLayout(); + this.YndPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.YndAreaIDYUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.YndAreaIDXUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.YndPedNodesUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.YndVehicleNodesUpDown)).BeginInit(); + this.YndNodeTabPage.SuspendLayout(); + this.YndNodePanel.SuspendLayout(); + this.PathNodeTabControl.SuspendLayout(); + this.PathNodePropertiesTabPage.SuspendLayout(); + this.PathNodeFlags5GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags5UpDown)).BeginInit(); + this.PathNodeFlags4GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags42UpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags4UpDown)).BeginInit(); + this.PathNodeFlags3GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags32UpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags3UpDown)).BeginInit(); + this.PathNodeFlags2GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags2UpDown)).BeginInit(); + this.PathNodeFlags1GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags1UpDown)).BeginInit(); + this.PathNodeFlags0GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags0UpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeAreaIDUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeNodeIDUpDown)).BeginInit(); + this.PathNodeLinksTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); + this.splitContainer2.Panel1.SuspendLayout(); + this.splitContainer2.Panel2.SuspendLayout(); + this.splitContainer2.SuspendLayout(); + this.PathNodeLinkPanel.SuspendLayout(); + this.PathLinkFlags2GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFwdLanesUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkBackLanesUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags2UpDown)).BeginInit(); + this.PathLinkFlags1GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkOffsetSizeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags1UpDown)).BeginInit(); + this.PathLinkFlags0GroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags04UpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags03UpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags0UpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkLengthUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkNodeIDUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkAreaIDUpDown)).BeginInit(); + this.PathNodeJunctionTabPage.SuspendLayout(); + this.PathNodeJunctionPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionPosYUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionPosXUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionHeightmapDimYUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionHeightmapDimXUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionMinZUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionMaxZUpDown)).BeginInit(); + this.YnvTabPage.SuspendLayout(); + this.YnvTabControl.SuspendLayout(); + this.YnvYnvTabPage.SuspendLayout(); + this.YnvPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.YnvAreaIDYUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.YnvAreaIDXUpDown)).BeginInit(); + this.YnvPolyTabPage.SuspendLayout(); + this.YnvPortalTabPage.SuspendLayout(); + this.TrainsTabPage.SuspendLayout(); + this.TrainsTabControl.SuspendLayout(); + this.TrainTrackTabPage.SuspendLayout(); + this.TrainTrackFilePanel.SuspendLayout(); + this.TrainNodeTabPage.SuspendLayout(); + this.TrainNodePanel.SuspendLayout(); + this.ScenarioTabPage.SuspendLayout(); + this.ScenarioTabControl.SuspendLayout(); + this.ScenarioYmtTabPage.SuspendLayout(); + this.ScenarioYmtPanel.SuspendLayout(); + this.ScenarioPointTabPage.SuspendLayout(); + this.ScenarioPointOuterPanel.SuspendLayout(); + this.ScenarioPointPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointFlagsValueUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointWaitTimeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointRadiusUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointSpOnlyFlagUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointProbabilityUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointTimeEndUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointTimeStartUpDown)).BeginInit(); + this.ScenarioEntityTabPage.SuspendLayout(); + this.ScenarioEntityPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityUnk2UpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityUnk1UpDown)).BeginInit(); + this.ScenarioEntityPointTabPage.SuspendLayout(); + this.ScenarioEntityPointPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityPointFlagsUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityPointEndUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityPointStartUpDown)).BeginInit(); + this.ScenarioChainTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); + this.splitContainer3.Panel1.SuspendLayout(); + this.splitContainer3.Panel2.SuspendLayout(); + this.splitContainer3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioChainUnk1UpDown)).BeginInit(); + this.ScenarioChainEdgePanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioChainEdgeNodeIndexToUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioChainEdgeNodeIndexFromUpDown)).BeginInit(); + this.ScenarioChainNodeTabPage.SuspendLayout(); + this.ScenarioChainNodePanel.SuspendLayout(); + this.ScenarioClusterTabPage.SuspendLayout(); + this.ScenarioClusterPanel.SuspendLayout(); + this.ScenarioClusterPointTabPage.SuspendLayout(); + this.ScenarioClusterPointPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointFlagsUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointWaitTimeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointRadiusUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointAnimalFlagUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointProbabilityUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointTimeEndUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointTimeStartUpDown)).BeginInit(); + this.TopMenuStrip.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer1.Location = new System.Drawing.Point(0, 27); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.ProjectTreeView); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.MainTabControl); + this.splitContainer1.Size = new System.Drawing.Size(776, 504); + this.splitContainer1.SplitterDistance = 237; + this.splitContainer1.TabIndex = 0; + // + // ProjectTreeView + // + this.ProjectTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ProjectTreeView.FullRowSelect = true; + this.ProjectTreeView.HideSelection = false; + this.ProjectTreeView.Location = new System.Drawing.Point(3, 3); + this.ProjectTreeView.Name = "ProjectTreeView"; + this.ProjectTreeView.ShowRootLines = false; + this.ProjectTreeView.Size = new System.Drawing.Size(231, 498); + this.ProjectTreeView.TabIndex = 1; + this.ProjectTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.ProjectTreeView_AfterSelect); + // + // MainTabControl + // + this.MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTabControl.Controls.Add(this.ProjectTabPage); + this.MainTabControl.Controls.Add(this.YmapTabPage); + this.MainTabControl.Controls.Add(this.YndTabPage); + this.MainTabControl.Controls.Add(this.YnvTabPage); + this.MainTabControl.Controls.Add(this.TrainsTabPage); + this.MainTabControl.Controls.Add(this.ScenarioTabPage); + this.MainTabControl.Location = new System.Drawing.Point(3, 3); + this.MainTabControl.Name = "MainTabControl"; + this.MainTabControl.SelectedIndex = 0; + this.MainTabControl.Size = new System.Drawing.Size(529, 498); + this.MainTabControl.TabIndex = 2; + // + // ProjectTabPage + // + this.ProjectTabPage.Controls.Add(this.ProjectPanel); + this.ProjectTabPage.Location = new System.Drawing.Point(4, 22); + this.ProjectTabPage.Name = "ProjectTabPage"; + this.ProjectTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ProjectTabPage.Size = new System.Drawing.Size(521, 472); + this.ProjectTabPage.TabIndex = 0; + this.ProjectTabPage.Text = "Project"; + this.ProjectTabPage.UseVisualStyleBackColor = true; + // + // ProjectPanel + // + this.ProjectPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ProjectPanel.Controls.Add(this.ProjectHideMapCheckBox); + this.ProjectPanel.Controls.Add(this.ProjectShowEntitiesCheckBox); + this.ProjectPanel.Controls.Add(this.label1); + this.ProjectPanel.Controls.Add(this.ProjectVersionLabel); + this.ProjectPanel.Controls.Add(this.ProjectNameTextBox); + this.ProjectPanel.Enabled = false; + this.ProjectPanel.Location = new System.Drawing.Point(0, 0); + this.ProjectPanel.Name = "ProjectPanel"; + this.ProjectPanel.Size = new System.Drawing.Size(521, 472); + this.ProjectPanel.TabIndex = 3; + // + // ProjectHideMapCheckBox + // + this.ProjectHideMapCheckBox.AutoSize = true; + this.ProjectHideMapCheckBox.Location = new System.Drawing.Point(69, 116); + this.ProjectHideMapCheckBox.Name = "ProjectHideMapCheckBox"; + this.ProjectHideMapCheckBox.Size = new System.Drawing.Size(103, 17); + this.ProjectHideMapCheckBox.TabIndex = 25; + this.ProjectHideMapCheckBox.Text = "Hide GTAV map"; + this.ProjectHideMapCheckBox.UseVisualStyleBackColor = true; + this.ProjectHideMapCheckBox.CheckedChanged += new System.EventHandler(this.ProjectHideMapCheckBox_CheckedChanged); + // + // ProjectShowEntitiesCheckBox + // + this.ProjectShowEntitiesCheckBox.AutoSize = true; + this.ProjectShowEntitiesCheckBox.Checked = true; + this.ProjectShowEntitiesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.ProjectShowEntitiesCheckBox.Location = new System.Drawing.Point(69, 93); + this.ProjectShowEntitiesCheckBox.Name = "ProjectShowEntitiesCheckBox"; + this.ProjectShowEntitiesCheckBox.Size = new System.Drawing.Size(156, 17); + this.ProjectShowEntitiesCheckBox.TabIndex = 24; + this.ProjectShowEntitiesCheckBox.Text = "Show entities in World view"; + this.ProjectShowEntitiesCheckBox.UseVisualStyleBackColor = true; + this.ProjectShowEntitiesCheckBox.CheckedChanged += new System.EventHandler(this.ProjectShowEntitiesCheckBox_CheckedChanged); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(6, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Name:"; + // + // ProjectVersionLabel + // + this.ProjectVersionLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ProjectVersionLabel.AutoSize = true; + this.ProjectVersionLabel.Location = new System.Drawing.Point(359, 12); + this.ProjectVersionLabel.Name = "ProjectVersionLabel"; + this.ProjectVersionLabel.Size = new System.Drawing.Size(51, 13); + this.ProjectVersionLabel.TabIndex = 2; + this.ProjectVersionLabel.Text = "Version: -"; + // + // ProjectNameTextBox + // + this.ProjectNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ProjectNameTextBox.Location = new System.Drawing.Point(69, 9); + this.ProjectNameTextBox.Name = "ProjectNameTextBox"; + this.ProjectNameTextBox.Size = new System.Drawing.Size(262, 20); + this.ProjectNameTextBox.TabIndex = 1; + this.ProjectNameTextBox.TextChanged += new System.EventHandler(this.ProjectNameTextBox_TextChanged); + // + // YmapTabPage + // + this.YmapTabPage.Controls.Add(this.YmapTabControl); + this.YmapTabPage.Location = new System.Drawing.Point(4, 22); + this.YmapTabPage.Name = "YmapTabPage"; + this.YmapTabPage.Padding = new System.Windows.Forms.Padding(3); + this.YmapTabPage.Size = new System.Drawing.Size(521, 472); + this.YmapTabPage.TabIndex = 1; + this.YmapTabPage.Text = "Map"; + this.YmapTabPage.UseVisualStyleBackColor = true; + // + // YmapTabControl + // + this.YmapTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapTabControl.Controls.Add(this.YmapYmapTabPage); + this.YmapTabControl.Controls.Add(this.YmapEntityTabPage); + this.YmapTabControl.Controls.Add(this.YmapCarGenTabPage); + this.YmapTabControl.Location = new System.Drawing.Point(0, 3); + this.YmapTabControl.Name = "YmapTabControl"; + this.YmapTabControl.SelectedIndex = 0; + this.YmapTabControl.Size = new System.Drawing.Size(518, 469); + this.YmapTabControl.TabIndex = 0; + // + // YmapYmapTabPage + // + this.YmapYmapTabPage.Controls.Add(this.YmapPanel); + this.YmapYmapTabPage.Location = new System.Drawing.Point(4, 22); + this.YmapYmapTabPage.Name = "YmapYmapTabPage"; + this.YmapYmapTabPage.Padding = new System.Windows.Forms.Padding(3); + this.YmapYmapTabPage.Size = new System.Drawing.Size(510, 443); + this.YmapYmapTabPage.TabIndex = 0; + this.YmapYmapTabPage.Text = "Ymap"; + this.YmapYmapTabPage.UseVisualStyleBackColor = true; + // + // YmapPanel + // + this.YmapPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapPanel.Controls.Add(this.tabControl1); + this.YmapPanel.Controls.Add(this.YmapProjectPathTextBox); + this.YmapPanel.Controls.Add(this.label30); + this.YmapPanel.Controls.Add(this.YmapFileLocationTextBox); + this.YmapPanel.Controls.Add(this.label29); + this.YmapPanel.Controls.Add(this.YmapCalculateExtentsButton); + this.YmapPanel.Controls.Add(this.YmapStreamingExtentsMaxTextBox); + this.YmapPanel.Controls.Add(this.label10); + this.YmapPanel.Controls.Add(this.YmapStreamingExtentsMinTextBox); + this.YmapPanel.Controls.Add(this.label11); + this.YmapPanel.Controls.Add(this.YmapEntitiesExtentsMaxTextBox); + this.YmapPanel.Controls.Add(this.label9); + this.YmapPanel.Controls.Add(this.YmapEntitiesExtentsMinTextBox); + this.YmapPanel.Controls.Add(this.label8); + this.YmapPanel.Controls.Add(this.YmapParentHashLabel); + this.YmapPanel.Controls.Add(this.YmapNameHashLabel); + this.YmapPanel.Controls.Add(this.YmapParentTextBox); + this.YmapPanel.Controls.Add(this.label4); + this.YmapPanel.Controls.Add(this.label5); + this.YmapPanel.Controls.Add(this.YmapNameTextBox); + this.YmapPanel.Controls.Add(this.label3); + this.YmapPanel.Controls.Add(this.label2); + this.YmapPanel.Enabled = false; + this.YmapPanel.Location = new System.Drawing.Point(0, 0); + this.YmapPanel.Name = "YmapPanel"; + this.YmapPanel.Size = new System.Drawing.Size(510, 443); + this.YmapPanel.TabIndex = 5; + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Location = new System.Drawing.Point(3, 61); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(504, 203); + this.tabControl1.TabIndex = 41; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.groupBox1); + this.tabPage1.Controls.Add(this.YmapCalculateFlagsButton); + this.tabPage1.Controls.Add(this.groupBox2); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(496, 177); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Flags"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.YmapCFlagsGrassCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsCriticalCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsDistLightsCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsLODLightsCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsPhysicsCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsOcclusionCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsInteriorCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsSLODCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsSLOD2CheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsLODCheckBox); + this.groupBox1.Controls.Add(this.YmapCFlagsHDCheckBox); + this.groupBox1.Controls.Add(this.YmapContentFlagsTextBox); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Location = new System.Drawing.Point(6, 6); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(259, 166); + this.groupBox1.TabIndex = 13; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Content Flags"; + // + // YmapCFlagsGrassCheckBox + // + this.YmapCFlagsGrassCheckBox.AutoSize = true; + this.YmapCFlagsGrassCheckBox.Location = new System.Drawing.Point(138, 113); + this.YmapCFlagsGrassCheckBox.Name = "YmapCFlagsGrassCheckBox"; + this.YmapCFlagsGrassCheckBox.Size = new System.Drawing.Size(86, 17); + this.YmapCFlagsGrassCheckBox.TabIndex = 10; + this.YmapCFlagsGrassCheckBox.Text = "Grass (1024)"; + this.YmapCFlagsGrassCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsGrassCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsGrassCheckBox_CheckedChanged); + // + // YmapCFlagsCriticalCheckBox + // + this.YmapCFlagsCriticalCheckBox.AutoSize = true; + this.YmapCFlagsCriticalCheckBox.Location = new System.Drawing.Point(6, 113); + this.YmapCFlagsCriticalCheckBox.Name = "YmapCFlagsCriticalCheckBox"; + this.YmapCFlagsCriticalCheckBox.Size = new System.Drawing.Size(84, 17); + this.YmapCFlagsCriticalCheckBox.TabIndex = 9; + this.YmapCFlagsCriticalCheckBox.Text = "Critical (512)"; + this.YmapCFlagsCriticalCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsCriticalCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsCriticalCheckBox_CheckedChanged); + // + // YmapCFlagsDistLightsCheckBox + // + this.YmapCFlagsDistLightsCheckBox.AutoSize = true; + this.YmapCFlagsDistLightsCheckBox.Location = new System.Drawing.Point(138, 90); + this.YmapCFlagsDistLightsCheckBox.Name = "YmapCFlagsDistLightsCheckBox"; + this.YmapCFlagsDistLightsCheckBox.Size = new System.Drawing.Size(117, 17); + this.YmapCFlagsDistLightsCheckBox.TabIndex = 8; + this.YmapCFlagsDistLightsCheckBox.Text = "Distant Lights (256)"; + this.YmapCFlagsDistLightsCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsDistLightsCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsDistLightsCheckBox_CheckedChanged); + // + // YmapCFlagsLODLightsCheckBox + // + this.YmapCFlagsLODLightsCheckBox.AutoSize = true; + this.YmapCFlagsLODLightsCheckBox.Location = new System.Drawing.Point(6, 90); + this.YmapCFlagsLODLightsCheckBox.Name = "YmapCFlagsLODLightsCheckBox"; + this.YmapCFlagsLODLightsCheckBox.Size = new System.Drawing.Size(106, 17); + this.YmapCFlagsLODLightsCheckBox.TabIndex = 7; + this.YmapCFlagsLODLightsCheckBox.Text = "LOD Lights (128)"; + this.YmapCFlagsLODLightsCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsLODLightsCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsLODLightsCheckBox_CheckedChanged); + // + // YmapCFlagsPhysicsCheckBox + // + this.YmapCFlagsPhysicsCheckBox.AutoSize = true; + this.YmapCFlagsPhysicsCheckBox.Location = new System.Drawing.Point(138, 67); + this.YmapCFlagsPhysicsCheckBox.Name = "YmapCFlagsPhysicsCheckBox"; + this.YmapCFlagsPhysicsCheckBox.Size = new System.Drawing.Size(83, 17); + this.YmapCFlagsPhysicsCheckBox.TabIndex = 6; + this.YmapCFlagsPhysicsCheckBox.Text = "Physics (64)"; + this.YmapCFlagsPhysicsCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsPhysicsCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsPhysicsCheckBox_CheckedChanged); + // + // YmapCFlagsOcclusionCheckBox + // + this.YmapCFlagsOcclusionCheckBox.AutoSize = true; + this.YmapCFlagsOcclusionCheckBox.Location = new System.Drawing.Point(6, 67); + this.YmapCFlagsOcclusionCheckBox.Name = "YmapCFlagsOcclusionCheckBox"; + this.YmapCFlagsOcclusionCheckBox.Size = new System.Drawing.Size(94, 17); + this.YmapCFlagsOcclusionCheckBox.TabIndex = 5; + this.YmapCFlagsOcclusionCheckBox.Text = "Occlusion (32)"; + this.YmapCFlagsOcclusionCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsOcclusionCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsOcclusionCheckBox_CheckedChanged); + // + // YmapCFlagsInteriorCheckBox + // + this.YmapCFlagsInteriorCheckBox.AutoSize = true; + this.YmapCFlagsInteriorCheckBox.Location = new System.Drawing.Point(6, 44); + this.YmapCFlagsInteriorCheckBox.Name = "YmapCFlagsInteriorCheckBox"; + this.YmapCFlagsInteriorCheckBox.Size = new System.Drawing.Size(73, 17); + this.YmapCFlagsInteriorCheckBox.TabIndex = 4; + this.YmapCFlagsInteriorCheckBox.Text = "Interior (8)"; + this.YmapCFlagsInteriorCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsInteriorCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsInteriorCheckBox_CheckedChanged); + // + // YmapCFlagsSLODCheckBox + // + this.YmapCFlagsSLODCheckBox.AutoSize = true; + this.YmapCFlagsSLODCheckBox.Location = new System.Drawing.Point(138, 44); + this.YmapCFlagsSLODCheckBox.Name = "YmapCFlagsSLODCheckBox"; + this.YmapCFlagsSLODCheckBox.Size = new System.Drawing.Size(76, 17); + this.YmapCFlagsSLODCheckBox.TabIndex = 3; + this.YmapCFlagsSLODCheckBox.Text = "SLOD (16)"; + this.YmapCFlagsSLODCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsSLODCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsSLODCheckBox_CheckedChanged); + // + // YmapCFlagsSLOD2CheckBox + // + this.YmapCFlagsSLOD2CheckBox.AutoSize = true; + this.YmapCFlagsSLOD2CheckBox.Location = new System.Drawing.Point(138, 21); + this.YmapCFlagsSLOD2CheckBox.Name = "YmapCFlagsSLOD2CheckBox"; + this.YmapCFlagsSLOD2CheckBox.Size = new System.Drawing.Size(82, 17); + this.YmapCFlagsSLOD2CheckBox.TabIndex = 2; + this.YmapCFlagsSLOD2CheckBox.Text = "SLOD2+ (4)"; + this.YmapCFlagsSLOD2CheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsSLOD2CheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsSLOD2CheckBox_CheckedChanged); + // + // YmapCFlagsLODCheckBox + // + this.YmapCFlagsLODCheckBox.AutoSize = true; + this.YmapCFlagsLODCheckBox.Location = new System.Drawing.Point(69, 21); + this.YmapCFlagsLODCheckBox.Name = "YmapCFlagsLODCheckBox"; + this.YmapCFlagsLODCheckBox.Size = new System.Drawing.Size(63, 17); + this.YmapCFlagsLODCheckBox.TabIndex = 1; + this.YmapCFlagsLODCheckBox.Text = "LOD (2)"; + this.YmapCFlagsLODCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsLODCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsLODCheckBox_CheckedChanged); + // + // YmapCFlagsHDCheckBox + // + this.YmapCFlagsHDCheckBox.AutoSize = true; + this.YmapCFlagsHDCheckBox.Location = new System.Drawing.Point(6, 21); + this.YmapCFlagsHDCheckBox.Name = "YmapCFlagsHDCheckBox"; + this.YmapCFlagsHDCheckBox.Size = new System.Drawing.Size(57, 17); + this.YmapCFlagsHDCheckBox.TabIndex = 0; + this.YmapCFlagsHDCheckBox.Text = "HD (1)"; + this.YmapCFlagsHDCheckBox.UseVisualStyleBackColor = true; + this.YmapCFlagsHDCheckBox.CheckedChanged += new System.EventHandler(this.YmapCFlagsHDCheckBox_CheckedChanged); + // + // YmapContentFlagsTextBox + // + this.YmapContentFlagsTextBox.Location = new System.Drawing.Point(69, 140); + this.YmapContentFlagsTextBox.Name = "YmapContentFlagsTextBox"; + this.YmapContentFlagsTextBox.Size = new System.Drawing.Size(130, 20); + this.YmapContentFlagsTextBox.TabIndex = 13; + this.YmapContentFlagsTextBox.TextChanged += new System.EventHandler(this.YmapContentFlagsTextBox_TextChanged); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(26, 143); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(37, 13); + this.label7.TabIndex = 12; + this.label7.Text = "Value:"; + // + // YmapCalculateFlagsButton + // + this.YmapCalculateFlagsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.YmapCalculateFlagsButton.Location = new System.Drawing.Point(385, 144); + this.YmapCalculateFlagsButton.Name = "YmapCalculateFlagsButton"; + this.YmapCalculateFlagsButton.Size = new System.Drawing.Size(106, 23); + this.YmapCalculateFlagsButton.TabIndex = 40; + this.YmapCalculateFlagsButton.Text = "Calculate all flags"; + this.YmapCalculateFlagsButton.UseVisualStyleBackColor = true; + this.YmapCalculateFlagsButton.Click += new System.EventHandler(this.YmapCalculateFlagsButton_Click); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.YmapFlagsLODCheckBox); + this.groupBox2.Controls.Add(this.YmapFlagsScriptedCheckBox); + this.groupBox2.Controls.Add(this.YmapFlagsTextBox); + this.groupBox2.Controls.Add(this.label6); + this.groupBox2.Location = new System.Drawing.Point(271, 6); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(219, 74); + this.groupBox2.TabIndex = 14; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Flags"; + // + // YmapFlagsLODCheckBox + // + this.YmapFlagsLODCheckBox.AutoSize = true; + this.YmapFlagsLODCheckBox.Location = new System.Drawing.Point(92, 21); + this.YmapFlagsLODCheckBox.Name = "YmapFlagsLODCheckBox"; + this.YmapFlagsLODCheckBox.Size = new System.Drawing.Size(63, 17); + this.YmapFlagsLODCheckBox.TabIndex = 13; + this.YmapFlagsLODCheckBox.Text = "LOD (2)"; + this.YmapFlagsLODCheckBox.UseVisualStyleBackColor = true; + this.YmapFlagsLODCheckBox.CheckedChanged += new System.EventHandler(this.YmapFlagsLODCheckBox_CheckedChanged); + // + // YmapFlagsScriptedCheckBox + // + this.YmapFlagsScriptedCheckBox.AutoSize = true; + this.YmapFlagsScriptedCheckBox.Location = new System.Drawing.Point(6, 21); + this.YmapFlagsScriptedCheckBox.Name = "YmapFlagsScriptedCheckBox"; + this.YmapFlagsScriptedCheckBox.Size = new System.Drawing.Size(80, 17); + this.YmapFlagsScriptedCheckBox.TabIndex = 12; + this.YmapFlagsScriptedCheckBox.Text = "Scripted (1)"; + this.YmapFlagsScriptedCheckBox.UseVisualStyleBackColor = true; + this.YmapFlagsScriptedCheckBox.CheckedChanged += new System.EventHandler(this.YmapFlagsScriptedCheckBox_CheckedChanged); + // + // YmapFlagsTextBox + // + this.YmapFlagsTextBox.Location = new System.Drawing.Point(78, 48); + this.YmapFlagsTextBox.Name = "YmapFlagsTextBox"; + this.YmapFlagsTextBox.Size = new System.Drawing.Size(130, 20); + this.YmapFlagsTextBox.TabIndex = 11; + this.YmapFlagsTextBox.TextChanged += new System.EventHandler(this.YmapFlagsTextBox_TextChanged); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(35, 51); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(37, 13); + this.label6.TabIndex = 10; + this.label6.Text = "Value:"; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.label12); + this.tabPage2.Controls.Add(this.YmapPhysicsDictionariesTextBox); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(496, 177); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Physics Dictionaries"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(3, 9); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(75, 13); + this.label12.TabIndex = 52; + this.label12.Text = "Name hashes:"; + // + // YmapPhysicsDictionariesTextBox + // + this.YmapPhysicsDictionariesTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapPhysicsDictionariesTextBox.Location = new System.Drawing.Point(84, 6); + this.YmapPhysicsDictionariesTextBox.Multiline = true; + this.YmapPhysicsDictionariesTextBox.Name = "YmapPhysicsDictionariesTextBox"; + this.YmapPhysicsDictionariesTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.YmapPhysicsDictionariesTextBox.Size = new System.Drawing.Size(248, 165); + this.YmapPhysicsDictionariesTextBox.TabIndex = 51; + this.YmapPhysicsDictionariesTextBox.WordWrap = false; + this.YmapPhysicsDictionariesTextBox.TextChanged += new System.EventHandler(this.YmapPhysicsDictionariesTextBox_TextChanged); + // + // YmapProjectPathTextBox + // + this.YmapProjectPathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapProjectPathTextBox.Location = new System.Drawing.Point(84, 417); + this.YmapProjectPathTextBox.Name = "YmapProjectPathTextBox"; + this.YmapProjectPathTextBox.ReadOnly = true; + this.YmapProjectPathTextBox.Size = new System.Drawing.Size(414, 20); + this.YmapProjectPathTextBox.TabIndex = 37; + // + // label30 + // + this.label30.AutoSize = true; + this.label30.Location = new System.Drawing.Point(6, 420); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(67, 13); + this.label30.TabIndex = 36; + this.label30.Text = "Project path:"; + // + // YmapFileLocationTextBox + // + this.YmapFileLocationTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapFileLocationTextBox.Location = new System.Drawing.Point(84, 391); + this.YmapFileLocationTextBox.Name = "YmapFileLocationTextBox"; + this.YmapFileLocationTextBox.ReadOnly = true; + this.YmapFileLocationTextBox.Size = new System.Drawing.Size(414, 20); + this.YmapFileLocationTextBox.TabIndex = 35; + // + // label29 + // + this.label29.AutoSize = true; + this.label29.Location = new System.Drawing.Point(6, 394); + this.label29.Name = "label29"; + this.label29.Size = new System.Drawing.Size(66, 13); + this.label29.TabIndex = 34; + this.label29.Text = "File location:"; + // + // YmapCalculateExtentsButton + // + this.YmapCalculateExtentsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.YmapCalculateExtentsButton.Location = new System.Drawing.Point(392, 350); + this.YmapCalculateExtentsButton.Name = "YmapCalculateExtentsButton"; + this.YmapCalculateExtentsButton.Size = new System.Drawing.Size(106, 23); + this.YmapCalculateExtentsButton.TabIndex = 25; + this.YmapCalculateExtentsButton.Text = "Calculate extents"; + this.YmapCalculateExtentsButton.UseVisualStyleBackColor = true; + this.YmapCalculateExtentsButton.Click += new System.EventHandler(this.YmapCalculateExtentsButton_Click); + // + // YmapStreamingExtentsMaxTextBox + // + this.YmapStreamingExtentsMaxTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapStreamingExtentsMaxTextBox.Location = new System.Drawing.Point(127, 352); + this.YmapStreamingExtentsMaxTextBox.Name = "YmapStreamingExtentsMaxTextBox"; + this.YmapStreamingExtentsMaxTextBox.Size = new System.Drawing.Size(259, 20); + this.YmapStreamingExtentsMaxTextBox.TabIndex = 21; + this.YmapStreamingExtentsMaxTextBox.TextChanged += new System.EventHandler(this.YmapStreamingExtentsMaxTextBox_TextChanged); + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(6, 355); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(118, 13); + this.label10.TabIndex = 20; + this.label10.Text = "Streaming Extents Max:"; + // + // YmapStreamingExtentsMinTextBox + // + this.YmapStreamingExtentsMinTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapStreamingExtentsMinTextBox.Location = new System.Drawing.Point(127, 326); + this.YmapStreamingExtentsMinTextBox.Name = "YmapStreamingExtentsMinTextBox"; + this.YmapStreamingExtentsMinTextBox.Size = new System.Drawing.Size(259, 20); + this.YmapStreamingExtentsMinTextBox.TabIndex = 19; + this.YmapStreamingExtentsMinTextBox.TextChanged += new System.EventHandler(this.YmapStreamingExtentsMinTextBox_TextChanged); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(6, 329); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(115, 13); + this.label11.TabIndex = 18; + this.label11.Text = "Streaming Extents Min:"; + // + // YmapEntitiesExtentsMaxTextBox + // + this.YmapEntitiesExtentsMaxTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapEntitiesExtentsMaxTextBox.Location = new System.Drawing.Point(127, 300); + this.YmapEntitiesExtentsMaxTextBox.Name = "YmapEntitiesExtentsMaxTextBox"; + this.YmapEntitiesExtentsMaxTextBox.Size = new System.Drawing.Size(259, 20); + this.YmapEntitiesExtentsMaxTextBox.TabIndex = 17; + this.YmapEntitiesExtentsMaxTextBox.TextChanged += new System.EventHandler(this.YmapEntitiesExtentsMaxTextBox_TextChanged); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(6, 303); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(105, 13); + this.label9.TabIndex = 16; + this.label9.Text = "Entities Extents Max:"; + // + // YmapEntitiesExtentsMinTextBox + // + this.YmapEntitiesExtentsMinTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapEntitiesExtentsMinTextBox.Location = new System.Drawing.Point(127, 274); + this.YmapEntitiesExtentsMinTextBox.Name = "YmapEntitiesExtentsMinTextBox"; + this.YmapEntitiesExtentsMinTextBox.Size = new System.Drawing.Size(259, 20); + this.YmapEntitiesExtentsMinTextBox.TabIndex = 15; + this.YmapEntitiesExtentsMinTextBox.TextChanged += new System.EventHandler(this.YmapEntitiesExtentsMinTextBox_TextChanged); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(6, 277); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(102, 13); + this.label8.TabIndex = 14; + this.label8.Text = "Entities Extents Min:"; + // + // YmapParentHashLabel + // + this.YmapParentHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.YmapParentHashLabel.AutoSize = true; + this.YmapParentHashLabel.Location = new System.Drawing.Point(350, 38); + this.YmapParentHashLabel.Name = "YmapParentHashLabel"; + this.YmapParentHashLabel.Size = new System.Drawing.Size(44, 13); + this.YmapParentHashLabel.TabIndex = 9; + this.YmapParentHashLabel.Text = "Hash: 0"; + // + // YmapNameHashLabel + // + this.YmapNameHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.YmapNameHashLabel.AutoSize = true; + this.YmapNameHashLabel.Location = new System.Drawing.Point(350, 12); + this.YmapNameHashLabel.Name = "YmapNameHashLabel"; + this.YmapNameHashLabel.Size = new System.Drawing.Size(44, 13); + this.YmapNameHashLabel.TabIndex = 8; + this.YmapNameHashLabel.Text = "Hash: 0"; + // + // YmapParentTextBox + // + this.YmapParentTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapParentTextBox.Location = new System.Drawing.Point(84, 35); + this.YmapParentTextBox.Name = "YmapParentTextBox"; + this.YmapParentTextBox.Size = new System.Drawing.Size(216, 20); + this.YmapParentTextBox.TabIndex = 6; + this.YmapParentTextBox.TextChanged += new System.EventHandler(this.YmapParentTextBox_TextChanged); + // + // label4 + // + this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(299, 38); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(35, 13); + this.label4.TabIndex = 7; + this.label4.Text = ".ymap"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(6, 38); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(41, 13); + this.label5.TabIndex = 5; + this.label5.Text = "Parent:"; + // + // YmapNameTextBox + // + this.YmapNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapNameTextBox.Location = new System.Drawing.Point(84, 9); + this.YmapNameTextBox.Name = "YmapNameTextBox"; + this.YmapNameTextBox.Size = new System.Drawing.Size(216, 20); + this.YmapNameTextBox.TabIndex = 3; + this.YmapNameTextBox.TextChanged += new System.EventHandler(this.YmapNameTextBox_TextChanged); + // + // label3 + // + this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(299, 12); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(35, 13); + this.label3.TabIndex = 4; + this.label3.Text = ".ymap"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(6, 12); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(38, 13); + this.label2.TabIndex = 2; + this.label2.Text = "Name:"; + // + // YmapEntityTabPage + // + this.YmapEntityTabPage.Controls.Add(this.EntityPanel); + this.YmapEntityTabPage.Location = new System.Drawing.Point(4, 22); + this.YmapEntityTabPage.Name = "YmapEntityTabPage"; + this.YmapEntityTabPage.Padding = new System.Windows.Forms.Padding(3); + this.YmapEntityTabPage.Size = new System.Drawing.Size(510, 443); + this.YmapEntityTabPage.TabIndex = 1; + this.YmapEntityTabPage.Text = "Entity"; + this.YmapEntityTabPage.UseVisualStyleBackColor = true; + // + // EntityPanel + // + this.EntityPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityPanel.Controls.Add(this.EntityTabControl); + this.EntityPanel.Enabled = false; + this.EntityPanel.Location = new System.Drawing.Point(0, 0); + this.EntityPanel.Name = "EntityPanel"; + this.EntityPanel.Size = new System.Drawing.Size(510, 443); + this.EntityPanel.TabIndex = 24; + // + // EntityTabControl + // + this.EntityTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityTabControl.Controls.Add(this.EntityGeneralTabPage); + this.EntityTabControl.Controls.Add(this.EntityLodTabPage); + this.EntityTabControl.Controls.Add(this.EntityExtensionsTabPage); + this.EntityTabControl.Controls.Add(this.EntityPivotTabPage); + this.EntityTabControl.Location = new System.Drawing.Point(0, 3); + this.EntityTabControl.Name = "EntityTabControl"; + this.EntityTabControl.SelectedIndex = 0; + this.EntityTabControl.Size = new System.Drawing.Size(507, 440); + this.EntityTabControl.TabIndex = 44; + // + // EntityGeneralTabPage + // + this.EntityGeneralTabPage.Controls.Add(this.label13); + this.EntityGeneralTabPage.Controls.Add(this.label28); + this.EntityGeneralTabPage.Controls.Add(this.EntityDeleteButton); + this.EntityGeneralTabPage.Controls.Add(this.EntityTintValueTextBox); + this.EntityGeneralTabPage.Controls.Add(this.EntityAddToProjectButton); + this.EntityGeneralTabPage.Controls.Add(this.label27); + this.EntityGeneralTabPage.Controls.Add(this.label16); + this.EntityGeneralTabPage.Controls.Add(this.EntityArtificialAOTextBox); + this.EntityGeneralTabPage.Controls.Add(this.EntityPositionTextBox); + this.EntityGeneralTabPage.Controls.Add(this.label26); + this.EntityGeneralTabPage.Controls.Add(this.EntityNormalizeRotationButton); + this.EntityGeneralTabPage.Controls.Add(this.EntityAOMultiplierTextBox); + this.EntityGeneralTabPage.Controls.Add(this.EntityGuidTextBox); + this.EntityGeneralTabPage.Controls.Add(this.EntityPriorityLevelComboBox); + this.EntityGeneralTabPage.Controls.Add(this.label24); + this.EntityGeneralTabPage.Controls.Add(this.EntityGoToButton); + this.EntityGeneralTabPage.Controls.Add(this.label17); + this.EntityGeneralTabPage.Controls.Add(this.label15); + this.EntityGeneralTabPage.Controls.Add(this.EntityRotationTextBox); + this.EntityGeneralTabPage.Controls.Add(this.EntityFlagsTextBox); + this.EntityGeneralTabPage.Controls.Add(this.label18); + this.EntityGeneralTabPage.Controls.Add(this.EntityLodLevelComboBox); + this.EntityGeneralTabPage.Controls.Add(this.label14); + this.EntityGeneralTabPage.Controls.Add(this.label23); + this.EntityGeneralTabPage.Controls.Add(this.EntityScaleXYTextBox); + this.EntityGeneralTabPage.Controls.Add(this.label22); + this.EntityGeneralTabPage.Controls.Add(this.EntityArchetypeHashLabel); + this.EntityGeneralTabPage.Controls.Add(this.EntityChildLodDistTextBox); + this.EntityGeneralTabPage.Controls.Add(this.label19); + this.EntityGeneralTabPage.Controls.Add(this.label21); + this.EntityGeneralTabPage.Controls.Add(this.EntityScaleZTextBox); + this.EntityGeneralTabPage.Controls.Add(this.EntityLodDistTextBox); + this.EntityGeneralTabPage.Controls.Add(this.EntityArchetypeTextBox); + this.EntityGeneralTabPage.Location = new System.Drawing.Point(4, 22); + this.EntityGeneralTabPage.Name = "EntityGeneralTabPage"; + this.EntityGeneralTabPage.Padding = new System.Windows.Forms.Padding(3); + this.EntityGeneralTabPage.Size = new System.Drawing.Size(499, 414); + this.EntityGeneralTabPage.TabIndex = 0; + this.EntityGeneralTabPage.Text = "General"; + this.EntityGeneralTabPage.UseVisualStyleBackColor = true; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(15, 12); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(58, 13); + this.label13.TabIndex = 9; + this.label13.Text = "Archetype:"; + // + // label28 + // + this.label28.AutoSize = true; + this.label28.Location = new System.Drawing.Point(15, 352); + this.label28.Name = "label28"; + this.label28.Size = new System.Drawing.Size(55, 13); + this.label28.TabIndex = 40; + this.label28.Text = "TintValue:"; + // + // EntityDeleteButton + // + this.EntityDeleteButton.Location = new System.Drawing.Point(194, 385); + this.EntityDeleteButton.Name = "EntityDeleteButton"; + this.EntityDeleteButton.Size = new System.Drawing.Size(95, 23); + this.EntityDeleteButton.TabIndex = 43; + this.EntityDeleteButton.Text = "Delete Entity"; + this.EntityDeleteButton.UseVisualStyleBackColor = true; + this.EntityDeleteButton.Click += new System.EventHandler(this.EntityDeleteButton_Click); + // + // EntityTintValueTextBox + // + this.EntityTintValueTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityTintValueTextBox.Location = new System.Drawing.Point(93, 349); + this.EntityTintValueTextBox.Name = "EntityTintValueTextBox"; + this.EntityTintValueTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityTintValueTextBox.TabIndex = 41; + this.EntityTintValueTextBox.TextChanged += new System.EventHandler(this.EntityTintValueTextBox_TextChanged); + // + // EntityAddToProjectButton + // + this.EntityAddToProjectButton.Location = new System.Drawing.Point(93, 385); + this.EntityAddToProjectButton.Name = "EntityAddToProjectButton"; + this.EntityAddToProjectButton.Size = new System.Drawing.Size(95, 23); + this.EntityAddToProjectButton.TabIndex = 42; + this.EntityAddToProjectButton.Text = "Add to Project"; + this.EntityAddToProjectButton.UseVisualStyleBackColor = true; + this.EntityAddToProjectButton.Click += new System.EventHandler(this.EntityAddToProjectButton_Click); + // + // label27 + // + this.label27.AutoSize = true; + this.label27.Location = new System.Drawing.Point(15, 326); + this.label27.Name = "label27"; + this.label27.Size = new System.Drawing.Size(61, 13); + this.label27.TabIndex = 38; + this.label27.Text = "ArtificialAO:"; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(15, 90); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(47, 13); + this.label16.TabIndex = 16; + this.label16.Text = "Position:"; + // + // EntityArtificialAOTextBox + // + this.EntityArtificialAOTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityArtificialAOTextBox.Location = new System.Drawing.Point(93, 323); + this.EntityArtificialAOTextBox.Name = "EntityArtificialAOTextBox"; + this.EntityArtificialAOTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityArtificialAOTextBox.TabIndex = 39; + this.EntityArtificialAOTextBox.TextChanged += new System.EventHandler(this.EntityArtificialAOTextBox_TextChanged); + // + // EntityPositionTextBox + // + this.EntityPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityPositionTextBox.Location = new System.Drawing.Point(93, 87); + this.EntityPositionTextBox.Name = "EntityPositionTextBox"; + this.EntityPositionTextBox.Size = new System.Drawing.Size(326, 20); + this.EntityPositionTextBox.TabIndex = 17; + this.EntityPositionTextBox.TextChanged += new System.EventHandler(this.EntityPositionTextBox_TextChanged); + // + // label26 + // + this.label26.AutoSize = true; + this.label26.Location = new System.Drawing.Point(15, 300); + this.label26.Name = "label26"; + this.label26.Size = new System.Drawing.Size(66, 13); + this.label26.TabIndex = 36; + this.label26.Text = "AOMultiplier:"; + // + // EntityNormalizeRotationButton + // + this.EntityNormalizeRotationButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.EntityNormalizeRotationButton.Location = new System.Drawing.Point(425, 111); + this.EntityNormalizeRotationButton.Name = "EntityNormalizeRotationButton"; + this.EntityNormalizeRotationButton.Size = new System.Drawing.Size(68, 23); + this.EntityNormalizeRotationButton.TabIndex = 20; + this.EntityNormalizeRotationButton.Text = "Normalize"; + this.EntityNormalizeRotationButton.UseVisualStyleBackColor = true; + this.EntityNormalizeRotationButton.Click += new System.EventHandler(this.EntityNormalizeRotationButton_Click); + // + // EntityAOMultiplierTextBox + // + this.EntityAOMultiplierTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityAOMultiplierTextBox.Location = new System.Drawing.Point(93, 297); + this.EntityAOMultiplierTextBox.Name = "EntityAOMultiplierTextBox"; + this.EntityAOMultiplierTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityAOMultiplierTextBox.TabIndex = 37; + this.EntityAOMultiplierTextBox.TextChanged += new System.EventHandler(this.EntityAOMultiplierTextBox_TextChanged); + // + // EntityGuidTextBox + // + this.EntityGuidTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityGuidTextBox.Location = new System.Drawing.Point(93, 61); + this.EntityGuidTextBox.Name = "EntityGuidTextBox"; + this.EntityGuidTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityGuidTextBox.TabIndex = 15; + this.EntityGuidTextBox.TextChanged += new System.EventHandler(this.EntityGuidTextBox_TextChanged); + // + // EntityPriorityLevelComboBox + // + this.EntityPriorityLevelComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityPriorityLevelComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.EntityPriorityLevelComboBox.FormattingEnabled = true; + this.EntityPriorityLevelComboBox.Location = new System.Drawing.Point(93, 270); + this.EntityPriorityLevelComboBox.Name = "EntityPriorityLevelComboBox"; + this.EntityPriorityLevelComboBox.Size = new System.Drawing.Size(177, 21); + this.EntityPriorityLevelComboBox.TabIndex = 33; + this.EntityPriorityLevelComboBox.SelectedIndexChanged += new System.EventHandler(this.EntityPriorityLevelComboBox_SelectedIndexChanged); + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(15, 273); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(67, 13); + this.label24.TabIndex = 32; + this.label24.Text = "PriorityLevel:"; + // + // EntityGoToButton + // + this.EntityGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.EntityGoToButton.Location = new System.Drawing.Point(425, 85); + this.EntityGoToButton.Name = "EntityGoToButton"; + this.EntityGoToButton.Size = new System.Drawing.Size(68, 23); + this.EntityGoToButton.TabIndex = 18; + this.EntityGoToButton.Text = "Go to"; + this.EntityGoToButton.UseVisualStyleBackColor = true; + this.EntityGoToButton.Click += new System.EventHandler(this.EntityGoToButton_Click); + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(15, 116); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(50, 13); + this.label17.TabIndex = 18; + this.label17.Text = "Rotation:"; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(15, 64); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(37, 13); + this.label15.TabIndex = 14; + this.label15.Text = "GUID:"; + // + // EntityRotationTextBox + // + this.EntityRotationTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityRotationTextBox.Location = new System.Drawing.Point(93, 113); + this.EntityRotationTextBox.Name = "EntityRotationTextBox"; + this.EntityRotationTextBox.Size = new System.Drawing.Size(326, 20); + this.EntityRotationTextBox.TabIndex = 19; + this.EntityRotationTextBox.TextChanged += new System.EventHandler(this.EntityRotationTextBox_TextChanged); + // + // EntityFlagsTextBox + // + this.EntityFlagsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityFlagsTextBox.Location = new System.Drawing.Point(93, 35); + this.EntityFlagsTextBox.Name = "EntityFlagsTextBox"; + this.EntityFlagsTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityFlagsTextBox.TabIndex = 13; + this.EntityFlagsTextBox.TextChanged += new System.EventHandler(this.EntityFlagsTextBox_TextChanged); + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(15, 142); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(51, 13); + this.label18.TabIndex = 20; + this.label18.Text = "ScaleXY:"; + // + // EntityLodLevelComboBox + // + this.EntityLodLevelComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityLodLevelComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.EntityLodLevelComboBox.FormattingEnabled = true; + this.EntityLodLevelComboBox.Location = new System.Drawing.Point(93, 243); + this.EntityLodLevelComboBox.Name = "EntityLodLevelComboBox"; + this.EntityLodLevelComboBox.Size = new System.Drawing.Size(177, 21); + this.EntityLodLevelComboBox.TabIndex = 31; + this.EntityLodLevelComboBox.SelectedIndexChanged += new System.EventHandler(this.EntityLodLevelComboBox_SelectedIndexChanged); + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(15, 38); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(35, 13); + this.label14.TabIndex = 12; + this.label14.Text = "Flags:"; + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(15, 246); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(54, 13); + this.label23.TabIndex = 30; + this.label23.Text = "LodLevel:"; + // + // EntityScaleXYTextBox + // + this.EntityScaleXYTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityScaleXYTextBox.Location = new System.Drawing.Point(93, 139); + this.EntityScaleXYTextBox.Name = "EntityScaleXYTextBox"; + this.EntityScaleXYTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityScaleXYTextBox.TabIndex = 21; + this.EntityScaleXYTextBox.TextChanged += new System.EventHandler(this.EntityScaleXYTextBox_TextChanged); + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(15, 220); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(69, 13); + this.label22.TabIndex = 28; + this.label22.Text = "ChildLodDist:"; + // + // EntityArchetypeHashLabel + // + this.EntityArchetypeHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.EntityArchetypeHashLabel.AutoSize = true; + this.EntityArchetypeHashLabel.Location = new System.Drawing.Point(276, 12); + this.EntityArchetypeHashLabel.Name = "EntityArchetypeHashLabel"; + this.EntityArchetypeHashLabel.Size = new System.Drawing.Size(44, 13); + this.EntityArchetypeHashLabel.TabIndex = 11; + this.EntityArchetypeHashLabel.Text = "Hash: 0"; + // + // EntityChildLodDistTextBox + // + this.EntityChildLodDistTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityChildLodDistTextBox.Location = new System.Drawing.Point(93, 217); + this.EntityChildLodDistTextBox.Name = "EntityChildLodDistTextBox"; + this.EntityChildLodDistTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityChildLodDistTextBox.TabIndex = 29; + this.EntityChildLodDistTextBox.TextChanged += new System.EventHandler(this.EntityChildLodDistTextBox_TextChanged); + // + // label19 + // + this.label19.AutoSize = true; + this.label19.Location = new System.Drawing.Point(15, 168); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(44, 13); + this.label19.TabIndex = 22; + this.label19.Text = "ScaleZ:"; + // + // label21 + // + this.label21.AutoSize = true; + this.label21.Location = new System.Drawing.Point(15, 194); + this.label21.Name = "label21"; + this.label21.Size = new System.Drawing.Size(46, 13); + this.label21.TabIndex = 26; + this.label21.Text = "LodDist:"; + // + // EntityScaleZTextBox + // + this.EntityScaleZTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityScaleZTextBox.Location = new System.Drawing.Point(93, 165); + this.EntityScaleZTextBox.Name = "EntityScaleZTextBox"; + this.EntityScaleZTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityScaleZTextBox.TabIndex = 23; + this.EntityScaleZTextBox.TextChanged += new System.EventHandler(this.EntityScaleZTextBox_TextChanged); + // + // EntityLodDistTextBox + // + this.EntityLodDistTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityLodDistTextBox.Location = new System.Drawing.Point(93, 191); + this.EntityLodDistTextBox.Name = "EntityLodDistTextBox"; + this.EntityLodDistTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityLodDistTextBox.TabIndex = 27; + this.EntityLodDistTextBox.TextChanged += new System.EventHandler(this.EntityLodDistTextBox_TextChanged); + // + // EntityArchetypeTextBox + // + this.EntityArchetypeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityArchetypeTextBox.Location = new System.Drawing.Point(93, 9); + this.EntityArchetypeTextBox.Name = "EntityArchetypeTextBox"; + this.EntityArchetypeTextBox.Size = new System.Drawing.Size(177, 20); + this.EntityArchetypeTextBox.TabIndex = 10; + this.EntityArchetypeTextBox.TextChanged += new System.EventHandler(this.EntityArchetypeTextBox_TextChanged); + // + // EntityLodTabPage + // + this.EntityLodTabPage.Controls.Add(this.label20); + this.EntityLodTabPage.Controls.Add(this.EntityParentIndexTextBox); + this.EntityLodTabPage.Controls.Add(this.EntityNumChildrenTextBox); + this.EntityLodTabPage.Controls.Add(this.label25); + this.EntityLodTabPage.Location = new System.Drawing.Point(4, 22); + this.EntityLodTabPage.Name = "EntityLodTabPage"; + this.EntityLodTabPage.Padding = new System.Windows.Forms.Padding(3); + this.EntityLodTabPage.Size = new System.Drawing.Size(499, 414); + this.EntityLodTabPage.TabIndex = 1; + this.EntityLodTabPage.Text = "LOD Hierarchy"; + this.EntityLodTabPage.UseVisualStyleBackColor = true; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(15, 16); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(67, 13); + this.label20.TabIndex = 24; + this.label20.Text = "ParentIndex:"; + // + // EntityParentIndexTextBox + // + this.EntityParentIndexTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityParentIndexTextBox.Location = new System.Drawing.Point(93, 13); + this.EntityParentIndexTextBox.Name = "EntityParentIndexTextBox"; + this.EntityParentIndexTextBox.Size = new System.Drawing.Size(189, 20); + this.EntityParentIndexTextBox.TabIndex = 25; + this.EntityParentIndexTextBox.TextChanged += new System.EventHandler(this.EntityParentIndexTextBox_TextChanged); + // + // EntityNumChildrenTextBox + // + this.EntityNumChildrenTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityNumChildrenTextBox.Location = new System.Drawing.Point(93, 39); + this.EntityNumChildrenTextBox.Name = "EntityNumChildrenTextBox"; + this.EntityNumChildrenTextBox.Size = new System.Drawing.Size(189, 20); + this.EntityNumChildrenTextBox.TabIndex = 35; + this.EntityNumChildrenTextBox.TextChanged += new System.EventHandler(this.EntityNumChildrenTextBox_TextChanged); + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(15, 42); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(70, 13); + this.label25.TabIndex = 34; + this.label25.Text = "NumChildren:"; + // + // EntityExtensionsTabPage + // + this.EntityExtensionsTabPage.Location = new System.Drawing.Point(4, 22); + this.EntityExtensionsTabPage.Name = "EntityExtensionsTabPage"; + this.EntityExtensionsTabPage.Size = new System.Drawing.Size(499, 414); + this.EntityExtensionsTabPage.TabIndex = 2; + this.EntityExtensionsTabPage.Text = "Extensions"; + this.EntityExtensionsTabPage.UseVisualStyleBackColor = true; + // + // EntityPivotTabPage + // + this.EntityPivotTabPage.Controls.Add(this.label95); + this.EntityPivotTabPage.Controls.Add(this.EntityPivotEditCheckBox); + this.EntityPivotTabPage.Controls.Add(this.label93); + this.EntityPivotTabPage.Controls.Add(this.EntityPivotPositionTextBox); + this.EntityPivotTabPage.Controls.Add(this.EntityPivotRotationNormalizeButton); + this.EntityPivotTabPage.Controls.Add(this.label94); + this.EntityPivotTabPage.Controls.Add(this.EntityPivotRotationTextBox); + this.EntityPivotTabPage.Location = new System.Drawing.Point(4, 22); + this.EntityPivotTabPage.Name = "EntityPivotTabPage"; + this.EntityPivotTabPage.Size = new System.Drawing.Size(499, 414); + this.EntityPivotTabPage.TabIndex = 3; + this.EntityPivotTabPage.Text = "Pivot"; + this.EntityPivotTabPage.UseVisualStyleBackColor = true; + // + // label95 + // + this.label95.Location = new System.Drawing.Point(90, 152); + this.label95.Name = "label95"; + this.label95.Size = new System.Drawing.Size(329, 51); + this.label95.TabIndex = 27; + this.label95.Text = "Note: Custom pivot is not saved. It will be reset if you close the project or res" + + "tart CodeWalker."; + // + // EntityPivotEditCheckBox + // + this.EntityPivotEditCheckBox.AutoSize = true; + this.EntityPivotEditCheckBox.Location = new System.Drawing.Point(93, 32); + this.EntityPivotEditCheckBox.Name = "EntityPivotEditCheckBox"; + this.EntityPivotEditCheckBox.Size = new System.Drawing.Size(137, 17); + this.EntityPivotEditCheckBox.TabIndex = 20; + this.EntityPivotEditCheckBox.Text = "Edit pivot in World view"; + this.EntityPivotEditCheckBox.UseVisualStyleBackColor = true; + this.EntityPivotEditCheckBox.CheckedChanged += new System.EventHandler(this.EntityPivotEditCheckBox_CheckedChanged); + // + // label93 + // + this.label93.AutoSize = true; + this.label93.Location = new System.Drawing.Point(15, 73); + this.label93.Name = "label93"; + this.label93.Size = new System.Drawing.Size(47, 13); + this.label93.TabIndex = 21; + this.label93.Text = "Position:"; + // + // EntityPivotPositionTextBox + // + this.EntityPivotPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityPivotPositionTextBox.Location = new System.Drawing.Point(93, 70); + this.EntityPivotPositionTextBox.Name = "EntityPivotPositionTextBox"; + this.EntityPivotPositionTextBox.Size = new System.Drawing.Size(326, 20); + this.EntityPivotPositionTextBox.TabIndex = 22; + this.EntityPivotPositionTextBox.TextChanged += new System.EventHandler(this.EntityPivotPositionTextBox_TextChanged); + // + // EntityPivotRotationNormalizeButton + // + this.EntityPivotRotationNormalizeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.EntityPivotRotationNormalizeButton.Location = new System.Drawing.Point(425, 94); + this.EntityPivotRotationNormalizeButton.Name = "EntityPivotRotationNormalizeButton"; + this.EntityPivotRotationNormalizeButton.Size = new System.Drawing.Size(68, 23); + this.EntityPivotRotationNormalizeButton.TabIndex = 26; + this.EntityPivotRotationNormalizeButton.Text = "Normalize"; + this.EntityPivotRotationNormalizeButton.UseVisualStyleBackColor = true; + this.EntityPivotRotationNormalizeButton.Click += new System.EventHandler(this.EntityPivotRotationNormalizeButton_Click); + // + // label94 + // + this.label94.AutoSize = true; + this.label94.Location = new System.Drawing.Point(15, 99); + this.label94.Name = "label94"; + this.label94.Size = new System.Drawing.Size(50, 13); + this.label94.TabIndex = 24; + this.label94.Text = "Rotation:"; + // + // EntityPivotRotationTextBox + // + this.EntityPivotRotationTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityPivotRotationTextBox.Location = new System.Drawing.Point(93, 96); + this.EntityPivotRotationTextBox.Name = "EntityPivotRotationTextBox"; + this.EntityPivotRotationTextBox.Size = new System.Drawing.Size(326, 20); + this.EntityPivotRotationTextBox.TabIndex = 25; + this.EntityPivotRotationTextBox.TextChanged += new System.EventHandler(this.EntityPivotRotationTextBox_TextChanged); + // + // YmapCarGenTabPage + // + this.YmapCarGenTabPage.Controls.Add(this.CarGenPanel); + this.YmapCarGenTabPage.Location = new System.Drawing.Point(4, 22); + this.YmapCarGenTabPage.Name = "YmapCarGenTabPage"; + this.YmapCarGenTabPage.Size = new System.Drawing.Size(510, 443); + this.YmapCarGenTabPage.TabIndex = 2; + this.YmapCarGenTabPage.Text = "Car Gen"; + this.YmapCarGenTabPage.UseVisualStyleBackColor = true; + // + // CarGenPanel + // + this.CarGenPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarGenPanel.Controls.Add(this.CarDeleteButton); + this.CarGenPanel.Controls.Add(this.CarAddToProjectButton); + this.CarGenPanel.Controls.Add(this.label44); + this.CarGenPanel.Controls.Add(this.CarLiveryTextBox); + this.CarGenPanel.Controls.Add(this.label43); + this.CarGenPanel.Controls.Add(this.CarBodyColorRemap4TextBox); + this.CarGenPanel.Controls.Add(this.label42); + this.CarGenPanel.Controls.Add(this.CarBodyColorRemap3TextBox); + this.CarGenPanel.Controls.Add(this.label41); + this.CarGenPanel.Controls.Add(this.CarBodyColorRemap2TextBox); + this.CarGenPanel.Controls.Add(this.CarPopGroupTextBox); + this.CarGenPanel.Controls.Add(this.label39); + this.CarGenPanel.Controls.Add(this.CarPopGroupHashLabel); + this.CarGenPanel.Controls.Add(this.label38); + this.CarGenPanel.Controls.Add(this.CarBodyColorRemap1TextBox); + this.CarGenPanel.Controls.Add(this.label37); + this.CarGenPanel.Controls.Add(this.CarFlagsTextBox); + this.CarGenPanel.Controls.Add(this.CarPerpendicularLengthTextBox); + this.CarGenPanel.Controls.Add(this.label36); + this.CarGenPanel.Controls.Add(this.CarOrientYTextBox); + this.CarGenPanel.Controls.Add(this.label34); + this.CarGenPanel.Controls.Add(this.CarOrientXTextBox); + this.CarGenPanel.Controls.Add(this.label35); + this.CarGenPanel.Controls.Add(this.CarModelTextBox); + this.CarGenPanel.Controls.Add(this.label32); + this.CarGenPanel.Controls.Add(this.CarModelHashLabel); + this.CarGenPanel.Controls.Add(this.CarGoToButton); + this.CarGenPanel.Controls.Add(this.CarPositionTextBox); + this.CarGenPanel.Controls.Add(this.label31); + this.CarGenPanel.Enabled = false; + this.CarGenPanel.Location = new System.Drawing.Point(0, 0); + this.CarGenPanel.Name = "CarGenPanel"; + this.CarGenPanel.Size = new System.Drawing.Size(510, 443); + this.CarGenPanel.TabIndex = 0; + // + // CarDeleteButton + // + this.CarDeleteButton.Location = new System.Drawing.Point(221, 347); + this.CarDeleteButton.Name = "CarDeleteButton"; + this.CarDeleteButton.Size = new System.Drawing.Size(95, 23); + this.CarDeleteButton.TabIndex = 71; + this.CarDeleteButton.Text = "Delete CarGen"; + this.CarDeleteButton.UseVisualStyleBackColor = true; + this.CarDeleteButton.Click += new System.EventHandler(this.CarDeleteButton_Click); + // + // CarAddToProjectButton + // + this.CarAddToProjectButton.Location = new System.Drawing.Point(120, 347); + this.CarAddToProjectButton.Name = "CarAddToProjectButton"; + this.CarAddToProjectButton.Size = new System.Drawing.Size(95, 23); + this.CarAddToProjectButton.TabIndex = 70; + this.CarAddToProjectButton.Text = "Add to Project"; + this.CarAddToProjectButton.UseVisualStyleBackColor = true; + this.CarAddToProjectButton.Click += new System.EventHandler(this.CarAddToProjectButton_Click); + // + // label44 + // + this.label44.AutoSize = true; + this.label44.Location = new System.Drawing.Point(6, 298); + this.label44.Name = "label44"; + this.label44.Size = new System.Drawing.Size(38, 13); + this.label44.TabIndex = 68; + this.label44.Text = "Livery:"; + // + // CarLiveryTextBox + // + this.CarLiveryTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarLiveryTextBox.Location = new System.Drawing.Point(120, 295); + this.CarLiveryTextBox.Name = "CarLiveryTextBox"; + this.CarLiveryTextBox.Size = new System.Drawing.Size(231, 20); + this.CarLiveryTextBox.TabIndex = 69; + this.CarLiveryTextBox.TextChanged += new System.EventHandler(this.CarLiveryTextBox_TextChanged); + // + // label43 + // + this.label43.AutoSize = true; + this.label43.Location = new System.Drawing.Point(6, 272); + this.label43.Name = "label43"; + this.label43.Size = new System.Drawing.Size(98, 13); + this.label43.TabIndex = 66; + this.label43.Text = "BodyColorRemap4:"; + // + // CarBodyColorRemap4TextBox + // + this.CarBodyColorRemap4TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarBodyColorRemap4TextBox.Location = new System.Drawing.Point(120, 269); + this.CarBodyColorRemap4TextBox.Name = "CarBodyColorRemap4TextBox"; + this.CarBodyColorRemap4TextBox.Size = new System.Drawing.Size(231, 20); + this.CarBodyColorRemap4TextBox.TabIndex = 67; + this.CarBodyColorRemap4TextBox.TextChanged += new System.EventHandler(this.CarBodyColorRemap4TextBox_TextChanged); + // + // label42 + // + this.label42.AutoSize = true; + this.label42.Location = new System.Drawing.Point(6, 246); + this.label42.Name = "label42"; + this.label42.Size = new System.Drawing.Size(98, 13); + this.label42.TabIndex = 64; + this.label42.Text = "BodyColorRemap3:"; + // + // CarBodyColorRemap3TextBox + // + this.CarBodyColorRemap3TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarBodyColorRemap3TextBox.Location = new System.Drawing.Point(120, 243); + this.CarBodyColorRemap3TextBox.Name = "CarBodyColorRemap3TextBox"; + this.CarBodyColorRemap3TextBox.Size = new System.Drawing.Size(231, 20); + this.CarBodyColorRemap3TextBox.TabIndex = 65; + this.CarBodyColorRemap3TextBox.TextChanged += new System.EventHandler(this.CarBodyColorRemap3TextBox_TextChanged); + // + // label41 + // + this.label41.AutoSize = true; + this.label41.Location = new System.Drawing.Point(6, 220); + this.label41.Name = "label41"; + this.label41.Size = new System.Drawing.Size(98, 13); + this.label41.TabIndex = 62; + this.label41.Text = "BodyColorRemap2:"; + // + // CarBodyColorRemap2TextBox + // + this.CarBodyColorRemap2TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarBodyColorRemap2TextBox.Location = new System.Drawing.Point(120, 217); + this.CarBodyColorRemap2TextBox.Name = "CarBodyColorRemap2TextBox"; + this.CarBodyColorRemap2TextBox.Size = new System.Drawing.Size(231, 20); + this.CarBodyColorRemap2TextBox.TabIndex = 63; + this.CarBodyColorRemap2TextBox.TextChanged += new System.EventHandler(this.CarBodyColorRemap2TextBox_TextChanged); + // + // CarPopGroupTextBox + // + this.CarPopGroupTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarPopGroupTextBox.Location = new System.Drawing.Point(84, 35); + this.CarPopGroupTextBox.Name = "CarPopGroupTextBox"; + this.CarPopGroupTextBox.Size = new System.Drawing.Size(267, 20); + this.CarPopGroupTextBox.TabIndex = 48; + this.CarPopGroupTextBox.TextChanged += new System.EventHandler(this.CarPopGroupTextBox_TextChanged); + // + // label39 + // + this.label39.AutoSize = true; + this.label39.Location = new System.Drawing.Point(6, 38); + this.label39.Name = "label39"; + this.label39.Size = new System.Drawing.Size(58, 13); + this.label39.TabIndex = 59; + this.label39.Text = "PopGroup:"; + // + // CarPopGroupHashLabel + // + this.CarPopGroupHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.CarPopGroupHashLabel.AutoSize = true; + this.CarPopGroupHashLabel.Location = new System.Drawing.Point(357, 38); + this.CarPopGroupHashLabel.Name = "CarPopGroupHashLabel"; + this.CarPopGroupHashLabel.Size = new System.Drawing.Size(44, 13); + this.CarPopGroupHashLabel.TabIndex = 61; + this.CarPopGroupHashLabel.Text = "Hash: 0"; + // + // label38 + // + this.label38.AutoSize = true; + this.label38.Location = new System.Drawing.Point(6, 194); + this.label38.Name = "label38"; + this.label38.Size = new System.Drawing.Size(98, 13); + this.label38.TabIndex = 57; + this.label38.Text = "BodyColorRemap1:"; + // + // CarBodyColorRemap1TextBox + // + this.CarBodyColorRemap1TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarBodyColorRemap1TextBox.Location = new System.Drawing.Point(120, 191); + this.CarBodyColorRemap1TextBox.Name = "CarBodyColorRemap1TextBox"; + this.CarBodyColorRemap1TextBox.Size = new System.Drawing.Size(231, 20); + this.CarBodyColorRemap1TextBox.TabIndex = 58; + this.CarBodyColorRemap1TextBox.TextChanged += new System.EventHandler(this.CarBodyColorRemap1TextBox_TextChanged); + // + // label37 + // + this.label37.AutoSize = true; + this.label37.Location = new System.Drawing.Point(6, 64); + this.label37.Name = "label37"; + this.label37.Size = new System.Drawing.Size(35, 13); + this.label37.TabIndex = 55; + this.label37.Text = "Flags:"; + // + // CarFlagsTextBox + // + this.CarFlagsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarFlagsTextBox.Location = new System.Drawing.Point(84, 61); + this.CarFlagsTextBox.Name = "CarFlagsTextBox"; + this.CarFlagsTextBox.Size = new System.Drawing.Size(267, 20); + this.CarFlagsTextBox.TabIndex = 50; + this.CarFlagsTextBox.TextChanged += new System.EventHandler(this.CarFlagsTextBox_TextChanged); + // + // CarPerpendicularLengthTextBox + // + this.CarPerpendicularLengthTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarPerpendicularLengthTextBox.Location = new System.Drawing.Point(120, 165); + this.CarPerpendicularLengthTextBox.Name = "CarPerpendicularLengthTextBox"; + this.CarPerpendicularLengthTextBox.Size = new System.Drawing.Size(231, 20); + this.CarPerpendicularLengthTextBox.TabIndex = 55; + this.CarPerpendicularLengthTextBox.TextChanged += new System.EventHandler(this.CarPerpendicularLengthTextBox_TextChanged); + // + // label36 + // + this.label36.AutoSize = true; + this.label36.Location = new System.Drawing.Point(6, 168); + this.label36.Name = "label36"; + this.label36.Size = new System.Drawing.Size(108, 13); + this.label36.TabIndex = 53; + this.label36.Text = "PerpendicularLength:"; + // + // CarOrientYTextBox + // + this.CarOrientYTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarOrientYTextBox.Location = new System.Drawing.Point(84, 139); + this.CarOrientYTextBox.Name = "CarOrientYTextBox"; + this.CarOrientYTextBox.Size = new System.Drawing.Size(267, 20); + this.CarOrientYTextBox.TabIndex = 54; + this.CarOrientYTextBox.TextChanged += new System.EventHandler(this.CarOrientYTextBox_TextChanged); + // + // label34 + // + this.label34.AutoSize = true; + this.label34.Location = new System.Drawing.Point(6, 142); + this.label34.Name = "label34"; + this.label34.Size = new System.Drawing.Size(45, 13); + this.label34.TabIndex = 51; + this.label34.Text = "OrientY:"; + // + // CarOrientXTextBox + // + this.CarOrientXTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarOrientXTextBox.Location = new System.Drawing.Point(84, 113); + this.CarOrientXTextBox.Name = "CarOrientXTextBox"; + this.CarOrientXTextBox.Size = new System.Drawing.Size(267, 20); + this.CarOrientXTextBox.TabIndex = 53; + this.CarOrientXTextBox.TextChanged += new System.EventHandler(this.CarOrientXTextBox_TextChanged); + // + // label35 + // + this.label35.AutoSize = true; + this.label35.Location = new System.Drawing.Point(6, 116); + this.label35.Name = "label35"; + this.label35.Size = new System.Drawing.Size(45, 13); + this.label35.TabIndex = 49; + this.label35.Text = "OrientX:"; + // + // CarModelTextBox + // + this.CarModelTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarModelTextBox.Location = new System.Drawing.Point(84, 9); + this.CarModelTextBox.Name = "CarModelTextBox"; + this.CarModelTextBox.Size = new System.Drawing.Size(267, 20); + this.CarModelTextBox.TabIndex = 47; + this.CarModelTextBox.TextChanged += new System.EventHandler(this.CarModelTextBox_TextChanged); + // + // label32 + // + this.label32.AutoSize = true; + this.label32.Location = new System.Drawing.Point(6, 12); + this.label32.Name = "label32"; + this.label32.Size = new System.Drawing.Size(55, 13); + this.label32.TabIndex = 46; + this.label32.Text = "CarModel:"; + // + // CarModelHashLabel + // + this.CarModelHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.CarModelHashLabel.AutoSize = true; + this.CarModelHashLabel.Location = new System.Drawing.Point(357, 12); + this.CarModelHashLabel.Name = "CarModelHashLabel"; + this.CarModelHashLabel.Size = new System.Drawing.Size(44, 13); + this.CarModelHashLabel.TabIndex = 48; + this.CarModelHashLabel.Text = "Hash: 0"; + // + // CarGoToButton + // + this.CarGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.CarGoToButton.Location = new System.Drawing.Point(437, 85); + this.CarGoToButton.Name = "CarGoToButton"; + this.CarGoToButton.Size = new System.Drawing.Size(68, 23); + this.CarGoToButton.TabIndex = 52; + this.CarGoToButton.Text = "Go to"; + this.CarGoToButton.UseVisualStyleBackColor = true; + this.CarGoToButton.Click += new System.EventHandler(this.CarGoToButton_Click); + // + // CarPositionTextBox + // + this.CarPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CarPositionTextBox.Location = new System.Drawing.Point(84, 87); + this.CarPositionTextBox.Name = "CarPositionTextBox"; + this.CarPositionTextBox.Size = new System.Drawing.Size(347, 20); + this.CarPositionTextBox.TabIndex = 51; + this.CarPositionTextBox.TextChanged += new System.EventHandler(this.CarPositionTextBox_TextChanged); + // + // label31 + // + this.label31.AutoSize = true; + this.label31.Location = new System.Drawing.Point(6, 90); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(47, 13); + this.label31.TabIndex = 43; + this.label31.Text = "Position:"; + // + // YndTabPage + // + this.YndTabPage.Controls.Add(this.YndTabControl); + this.YndTabPage.Location = new System.Drawing.Point(4, 22); + this.YndTabPage.Name = "YndTabPage"; + this.YndTabPage.Size = new System.Drawing.Size(521, 472); + this.YndTabPage.TabIndex = 2; + this.YndTabPage.Text = "Traffic"; + this.YndTabPage.UseVisualStyleBackColor = true; + // + // YndTabControl + // + this.YndTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YndTabControl.Controls.Add(this.YndYndTabPage); + this.YndTabControl.Controls.Add(this.YndNodeTabPage); + this.YndTabControl.Location = new System.Drawing.Point(0, 3); + this.YndTabControl.Name = "YndTabControl"; + this.YndTabControl.SelectedIndex = 0; + this.YndTabControl.Size = new System.Drawing.Size(518, 469); + this.YndTabControl.TabIndex = 1; + // + // YndYndTabPage + // + this.YndYndTabPage.Controls.Add(this.YndPanel); + this.YndYndTabPage.Location = new System.Drawing.Point(4, 22); + this.YndYndTabPage.Name = "YndYndTabPage"; + this.YndYndTabPage.Padding = new System.Windows.Forms.Padding(3); + this.YndYndTabPage.Size = new System.Drawing.Size(510, 443); + this.YndYndTabPage.TabIndex = 0; + this.YndYndTabPage.Text = "Ynd"; + this.YndYndTabPage.UseVisualStyleBackColor = true; + // + // YndPanel + // + this.YndPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YndPanel.Controls.Add(this.label88); + this.YndPanel.Controls.Add(this.YndAreaIDYUpDown); + this.YndPanel.Controls.Add(this.label87); + this.YndPanel.Controls.Add(this.YndAreaIDXUpDown); + this.YndPanel.Controls.Add(this.label48); + this.YndPanel.Controls.Add(this.YndProjectPathTextBox); + this.YndPanel.Controls.Add(this.label46); + this.YndPanel.Controls.Add(this.YndFilePathTextBox); + this.YndPanel.Controls.Add(this.label47); + this.YndPanel.Controls.Add(this.YndTotalNodesLabel); + this.YndPanel.Controls.Add(this.YndPedNodesUpDown); + this.YndPanel.Controls.Add(this.label45); + this.YndPanel.Controls.Add(this.YndVehicleNodesUpDown); + this.YndPanel.Controls.Add(this.label40); + this.YndPanel.Controls.Add(this.YndAreaIDInfoLabel); + this.YndPanel.Controls.Add(this.label33); + this.YndPanel.Controls.Add(this.YndRpfPathTextBox); + this.YndPanel.Enabled = false; + this.YndPanel.Location = new System.Drawing.Point(0, 0); + this.YndPanel.Name = "YndPanel"; + this.YndPanel.Size = new System.Drawing.Size(510, 443); + this.YndPanel.TabIndex = 0; + // + // label88 + // + this.label88.AutoSize = true; + this.label88.Location = new System.Drawing.Point(166, 11); + this.label88.Name = "label88"; + this.label88.Size = new System.Drawing.Size(17, 13); + this.label88.TabIndex = 19; + this.label88.Text = "Y:"; + // + // YndAreaIDYUpDown + // + this.YndAreaIDYUpDown.Location = new System.Drawing.Point(189, 9); + this.YndAreaIDYUpDown.Maximum = new decimal(new int[] { + 31, + 0, + 0, + 0}); + this.YndAreaIDYUpDown.Name = "YndAreaIDYUpDown"; + this.YndAreaIDYUpDown.Size = new System.Drawing.Size(48, 20); + this.YndAreaIDYUpDown.TabIndex = 18; + this.YndAreaIDYUpDown.ValueChanged += new System.EventHandler(this.YndAreaIDYUpDown_ValueChanged); + // + // label87 + // + this.label87.AutoSize = true; + this.label87.Location = new System.Drawing.Point(84, 11); + this.label87.Name = "label87"; + this.label87.Size = new System.Drawing.Size(17, 13); + this.label87.TabIndex = 17; + this.label87.Text = "X:"; + // + // YndAreaIDXUpDown + // + this.YndAreaIDXUpDown.Location = new System.Drawing.Point(107, 9); + this.YndAreaIDXUpDown.Maximum = new decimal(new int[] { + 31, + 0, + 0, + 0}); + this.YndAreaIDXUpDown.Name = "YndAreaIDXUpDown"; + this.YndAreaIDXUpDown.Size = new System.Drawing.Size(48, 20); + this.YndAreaIDXUpDown.TabIndex = 16; + this.YndAreaIDXUpDown.ValueChanged += new System.EventHandler(this.YndAreaIDXUpDown_ValueChanged); + // + // label48 + // + this.label48.AutoSize = true; + this.label48.Location = new System.Drawing.Point(6, 207); + this.label48.Name = "label48"; + this.label48.Size = new System.Drawing.Size(68, 13); + this.label48.TabIndex = 15; + this.label48.Text = "Project Path:"; + // + // YndProjectPathTextBox + // + this.YndProjectPathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YndProjectPathTextBox.Location = new System.Drawing.Point(80, 204); + this.YndProjectPathTextBox.Name = "YndProjectPathTextBox"; + this.YndProjectPathTextBox.ReadOnly = true; + this.YndProjectPathTextBox.Size = new System.Drawing.Size(386, 20); + this.YndProjectPathTextBox.TabIndex = 14; + // + // label46 + // + this.label46.AutoSize = true; + this.label46.Location = new System.Drawing.Point(6, 181); + this.label46.Name = "label46"; + this.label46.Size = new System.Drawing.Size(51, 13); + this.label46.TabIndex = 13; + this.label46.Text = "File Path:"; + // + // YndFilePathTextBox + // + this.YndFilePathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YndFilePathTextBox.Location = new System.Drawing.Point(80, 178); + this.YndFilePathTextBox.Name = "YndFilePathTextBox"; + this.YndFilePathTextBox.ReadOnly = true; + this.YndFilePathTextBox.Size = new System.Drawing.Size(386, 20); + this.YndFilePathTextBox.TabIndex = 12; + // + // label47 + // + this.label47.AutoSize = true; + this.label47.Location = new System.Drawing.Point(6, 155); + this.label47.Name = "label47"; + this.label47.Size = new System.Drawing.Size(52, 13); + this.label47.TabIndex = 11; + this.label47.Text = "Rpf Path:"; + // + // YndTotalNodesLabel + // + this.YndTotalNodesLabel.AutoSize = true; + this.YndTotalNodesLabel.Location = new System.Drawing.Point(6, 50); + this.YndTotalNodesLabel.Name = "YndTotalNodesLabel"; + this.YndTotalNodesLabel.Size = new System.Drawing.Size(77, 13); + this.YndTotalNodesLabel.TabIndex = 10; + this.YndTotalNodesLabel.Text = "Total Nodes: 0"; + // + // YndPedNodesUpDown + // + this.YndPedNodesUpDown.Location = new System.Drawing.Point(360, 48); + this.YndPedNodesUpDown.Maximum = new decimal(new int[] { + 0, + 0, + 0, + 0}); + this.YndPedNodesUpDown.Name = "YndPedNodesUpDown"; + this.YndPedNodesUpDown.Size = new System.Drawing.Size(74, 20); + this.YndPedNodesUpDown.TabIndex = 9; + this.YndPedNodesUpDown.ValueChanged += new System.EventHandler(this.YndPedNodesUpDown_ValueChanged); + // + // label45 + // + this.label45.AutoSize = true; + this.label45.Location = new System.Drawing.Point(291, 50); + this.label45.Name = "label45"; + this.label45.Size = new System.Drawing.Size(63, 13); + this.label45.TabIndex = 8; + this.label45.Text = "Ped Nodes:"; + // + // YndVehicleNodesUpDown + // + this.YndVehicleNodesUpDown.Location = new System.Drawing.Point(189, 48); + this.YndVehicleNodesUpDown.Maximum = new decimal(new int[] { + 0, + 0, + 0, + 0}); + this.YndVehicleNodesUpDown.Name = "YndVehicleNodesUpDown"; + this.YndVehicleNodesUpDown.Size = new System.Drawing.Size(74, 20); + this.YndVehicleNodesUpDown.TabIndex = 7; + this.YndVehicleNodesUpDown.ValueChanged += new System.EventHandler(this.YndVehicleNodesUpDown_ValueChanged); + // + // label40 + // + this.label40.AutoSize = true; + this.label40.Location = new System.Drawing.Point(104, 50); + this.label40.Name = "label40"; + this.label40.Size = new System.Drawing.Size(79, 13); + this.label40.TabIndex = 6; + this.label40.Text = "Vehicle Nodes:"; + // + // YndAreaIDInfoLabel + // + this.YndAreaIDInfoLabel.AutoSize = true; + this.YndAreaIDInfoLabel.Location = new System.Drawing.Point(254, 11); + this.YndAreaIDInfoLabel.Name = "YndAreaIDInfoLabel"; + this.YndAreaIDInfoLabel.Size = new System.Drawing.Size(30, 13); + this.YndAreaIDInfoLabel.TabIndex = 5; + this.YndAreaIDInfoLabel.Text = "ID: 0"; + // + // label33 + // + this.label33.AutoSize = true; + this.label33.Location = new System.Drawing.Point(28, 11); + this.label33.Name = "label33"; + this.label33.Size = new System.Drawing.Size(46, 13); + this.label33.TabIndex = 3; + this.label33.Text = "Area ID:"; + // + // YndRpfPathTextBox + // + this.YndRpfPathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YndRpfPathTextBox.Location = new System.Drawing.Point(80, 152); + this.YndRpfPathTextBox.Name = "YndRpfPathTextBox"; + this.YndRpfPathTextBox.ReadOnly = true; + this.YndRpfPathTextBox.Size = new System.Drawing.Size(386, 20); + this.YndRpfPathTextBox.TabIndex = 0; + // + // YndNodeTabPage + // + this.YndNodeTabPage.Controls.Add(this.YndNodePanel); + this.YndNodeTabPage.Location = new System.Drawing.Point(4, 22); + this.YndNodeTabPage.Name = "YndNodeTabPage"; + this.YndNodeTabPage.Padding = new System.Windows.Forms.Padding(3); + this.YndNodeTabPage.Size = new System.Drawing.Size(510, 443); + this.YndNodeTabPage.TabIndex = 1; + this.YndNodeTabPage.Text = "Node"; + this.YndNodeTabPage.UseVisualStyleBackColor = true; + // + // YndNodePanel + // + this.YndNodePanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YndNodePanel.Controls.Add(this.PathNodeTabControl); + this.YndNodePanel.Enabled = false; + this.YndNodePanel.Location = new System.Drawing.Point(0, 0); + this.YndNodePanel.Name = "YndNodePanel"; + this.YndNodePanel.Size = new System.Drawing.Size(510, 443); + this.YndNodePanel.TabIndex = 0; + // + // PathNodeTabControl + // + this.PathNodeTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.PathNodeTabControl.Controls.Add(this.PathNodePropertiesTabPage); + this.PathNodeTabControl.Controls.Add(this.PathNodeLinksTabPage); + this.PathNodeTabControl.Controls.Add(this.PathNodeJunctionTabPage); + this.PathNodeTabControl.Location = new System.Drawing.Point(0, 3); + this.PathNodeTabControl.Name = "PathNodeTabControl"; + this.PathNodeTabControl.SelectedIndex = 0; + this.PathNodeTabControl.Size = new System.Drawing.Size(507, 440); + this.PathNodeTabControl.TabIndex = 28; + // + // PathNodePropertiesTabPage + // + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeFlags5GroupBox); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeFlags4GroupBox); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeFlags3GroupBox); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeFlags2GroupBox); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeFlags1GroupBox); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeFlags0GroupBox); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeDeleteButton); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeAreaIDUpDown); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeAddToProjectButton); + this.PathNodePropertiesTabPage.Controls.Add(this.label49); + this.PathNodePropertiesTabPage.Controls.Add(this.label50); + this.PathNodePropertiesTabPage.Controls.Add(this.label68); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeNodeIDUpDown); + this.PathNodePropertiesTabPage.Controls.Add(this.label52); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeStreetHashTextBox); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeGoToButton); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodeStreetNameLabel); + this.PathNodePropertiesTabPage.Controls.Add(this.PathNodePositionTextBox); + this.PathNodePropertiesTabPage.Controls.Add(this.label55); + this.PathNodePropertiesTabPage.Location = new System.Drawing.Point(4, 22); + this.PathNodePropertiesTabPage.Name = "PathNodePropertiesTabPage"; + this.PathNodePropertiesTabPage.Size = new System.Drawing.Size(499, 414); + this.PathNodePropertiesTabPage.TabIndex = 2; + this.PathNodePropertiesTabPage.Text = "Node Properties"; + this.PathNodePropertiesTabPage.UseVisualStyleBackColor = true; + // + // PathNodeFlags5GroupBox + // + this.PathNodeFlags5GroupBox.Controls.Add(this.PathNodeFlags52CheckBox); + this.PathNodeFlags5GroupBox.Controls.Add(this.PathNodeFlags53CheckBox); + this.PathNodeFlags5GroupBox.Controls.Add(this.PathNodeFlags51CheckBox); + this.PathNodeFlags5GroupBox.Controls.Add(this.PathNodeFlags5UpDown); + this.PathNodeFlags5GroupBox.Location = new System.Drawing.Point(249, 318); + this.PathNodeFlags5GroupBox.Name = "PathNodeFlags5GroupBox"; + this.PathNodeFlags5GroupBox.Size = new System.Drawing.Size(223, 84); + this.PathNodeFlags5GroupBox.TabIndex = 48; + this.PathNodeFlags5GroupBox.TabStop = false; + this.PathNodeFlags5GroupBox.Text = "Flags 5"; + // + // PathNodeFlags52CheckBox + // + this.PathNodeFlags52CheckBox.AutoSize = true; + this.PathNodeFlags52CheckBox.Location = new System.Drawing.Point(80, 41); + this.PathNodeFlags52CheckBox.Name = "PathNodeFlags52CheckBox"; + this.PathNodeFlags52CheckBox.Size = new System.Drawing.Size(87, 17); + this.PathNodeFlags52CheckBox.TabIndex = 36; + this.PathNodeFlags52CheckBox.Text = "Speed unk 1"; + this.PathNodeFlags52CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags52CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags52CheckBox_CheckedChanged); + // + // PathNodeFlags53CheckBox + // + this.PathNodeFlags53CheckBox.AutoSize = true; + this.PathNodeFlags53CheckBox.Location = new System.Drawing.Point(80, 62); + this.PathNodeFlags53CheckBox.Name = "PathNodeFlags53CheckBox"; + this.PathNodeFlags53CheckBox.Size = new System.Drawing.Size(87, 17); + this.PathNodeFlags53CheckBox.TabIndex = 37; + this.PathNodeFlags53CheckBox.Text = "Speed unk 2"; + this.PathNodeFlags53CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags53CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags53CheckBox_CheckedChanged); + // + // PathNodeFlags51CheckBox + // + this.PathNodeFlags51CheckBox.AutoSize = true; + this.PathNodeFlags51CheckBox.Location = new System.Drawing.Point(80, 20); + this.PathNodeFlags51CheckBox.Name = "PathNodeFlags51CheckBox"; + this.PathNodeFlags51CheckBox.Size = new System.Drawing.Size(137, 17); + this.PathNodeFlags51CheckBox.TabIndex = 35; + this.PathNodeFlags51CheckBox.Text = "Has junction heightmap"; + this.PathNodeFlags51CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags51CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags51CheckBox_CheckedChanged); + // + // PathNodeFlags5UpDown + // + this.PathNodeFlags5UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeFlags5UpDown.Maximum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.PathNodeFlags5UpDown.Name = "PathNodeFlags5UpDown"; + this.PathNodeFlags5UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeFlags5UpDown.TabIndex = 43; + this.PathNodeFlags5UpDown.ValueChanged += new System.EventHandler(this.PathNodeFlags5UpDown_ValueChanged); + // + // PathNodeFlags4GroupBox + // + this.PathNodeFlags4GroupBox.Controls.Add(this.PathNodeFlags45CheckBox); + this.PathNodeFlags4GroupBox.Controls.Add(this.PathNodeFlags46CheckBox); + this.PathNodeFlags4GroupBox.Controls.Add(this.PathNodeFlags47CheckBox); + this.PathNodeFlags4GroupBox.Controls.Add(this.PathNodeFlags48CheckBox); + this.PathNodeFlags4GroupBox.Controls.Add(this.PathNodeFlags42UpDown); + this.PathNodeFlags4GroupBox.Controls.Add(this.label71); + this.PathNodeFlags4GroupBox.Controls.Add(this.PathNodeFlags41CheckBox); + this.PathNodeFlags4GroupBox.Controls.Add(this.PathNodeFlags4UpDown); + this.PathNodeFlags4GroupBox.Controls.Add(this.PathNodeFlags4Label); + this.PathNodeFlags4GroupBox.Location = new System.Drawing.Point(370, 96); + this.PathNodeFlags4GroupBox.Name = "PathNodeFlags4GroupBox"; + this.PathNodeFlags4GroupBox.Size = new System.Drawing.Size(115, 175); + this.PathNodeFlags4GroupBox.TabIndex = 47; + this.PathNodeFlags4GroupBox.TabStop = false; + this.PathNodeFlags4GroupBox.Text = "Flags 4"; + // + // PathNodeFlags45CheckBox + // + this.PathNodeFlags45CheckBox.AutoSize = true; + this.PathNodeFlags45CheckBox.Location = new System.Drawing.Point(6, 66); + this.PathNodeFlags45CheckBox.Name = "PathNodeFlags45CheckBox"; + this.PathNodeFlags45CheckBox.Size = new System.Drawing.Size(70, 17); + this.PathNodeFlags45CheckBox.TabIndex = 36; + this.PathNodeFlags45CheckBox.Text = "Special 1"; + this.PathNodeFlags45CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags45CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags45CheckBox_CheckedChanged); + // + // PathNodeFlags46CheckBox + // + this.PathNodeFlags46CheckBox.AutoSize = true; + this.PathNodeFlags46CheckBox.Location = new System.Drawing.Point(6, 87); + this.PathNodeFlags46CheckBox.Name = "PathNodeFlags46CheckBox"; + this.PathNodeFlags46CheckBox.Size = new System.Drawing.Size(70, 17); + this.PathNodeFlags46CheckBox.TabIndex = 37; + this.PathNodeFlags46CheckBox.Text = "Special 2"; + this.PathNodeFlags46CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags46CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags46CheckBox_CheckedChanged); + // + // PathNodeFlags47CheckBox + // + this.PathNodeFlags47CheckBox.AutoSize = true; + this.PathNodeFlags47CheckBox.Location = new System.Drawing.Point(6, 108); + this.PathNodeFlags47CheckBox.Name = "PathNodeFlags47CheckBox"; + this.PathNodeFlags47CheckBox.Size = new System.Drawing.Size(70, 17); + this.PathNodeFlags47CheckBox.TabIndex = 38; + this.PathNodeFlags47CheckBox.Text = "Special 3"; + this.PathNodeFlags47CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags47CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags47CheckBox_CheckedChanged); + // + // PathNodeFlags48CheckBox + // + this.PathNodeFlags48CheckBox.AutoSize = true; + this.PathNodeFlags48CheckBox.Location = new System.Drawing.Point(6, 129); + this.PathNodeFlags48CheckBox.Name = "PathNodeFlags48CheckBox"; + this.PathNodeFlags48CheckBox.Size = new System.Drawing.Size(96, 17); + this.PathNodeFlags48CheckBox.TabIndex = 39; + this.PathNodeFlags48CheckBox.Text = "Junction unk 6"; + this.PathNodeFlags48CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags48CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags48CheckBox_CheckedChanged); + // + // PathNodeFlags42UpDown + // + this.PathNodeFlags42UpDown.Location = new System.Drawing.Point(41, 150); + this.PathNodeFlags42UpDown.Maximum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.PathNodeFlags42UpDown.Name = "PathNodeFlags42UpDown"; + this.PathNodeFlags42UpDown.Size = new System.Drawing.Size(57, 20); + this.PathNodeFlags42UpDown.TabIndex = 41; + this.PathNodeFlags42UpDown.ValueChanged += new System.EventHandler(this.PathNodeFlags42UpDown_ValueChanged); + // + // label71 + // + this.label71.AutoSize = true; + this.label71.Location = new System.Drawing.Point(4, 152); + this.label71.Name = "label71"; + this.label71.Size = new System.Drawing.Size(30, 13); + this.label71.TabIndex = 40; + this.label71.Text = "Unk:"; + // + // PathNodeFlags41CheckBox + // + this.PathNodeFlags41CheckBox.AutoSize = true; + this.PathNodeFlags41CheckBox.Location = new System.Drawing.Point(6, 45); + this.PathNodeFlags41CheckBox.Name = "PathNodeFlags41CheckBox"; + this.PathNodeFlags41CheckBox.Size = new System.Drawing.Size(79, 17); + this.PathNodeFlags41CheckBox.TabIndex = 35; + this.PathNodeFlags41CheckBox.Text = "Slow unk 4"; + this.PathNodeFlags41CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags41CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags41CheckBox_CheckedChanged); + // + // PathNodeFlags4UpDown + // + this.PathNodeFlags4UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeFlags4UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeFlags4UpDown.Name = "PathNodeFlags4UpDown"; + this.PathNodeFlags4UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeFlags4UpDown.TabIndex = 43; + this.PathNodeFlags4UpDown.ValueChanged += new System.EventHandler(this.PathNodeFlags4UpDown_ValueChanged); + // + // PathNodeFlags4Label + // + this.PathNodeFlags4Label.AutoSize = true; + this.PathNodeFlags4Label.Location = new System.Drawing.Point(74, 21); + this.PathNodeFlags4Label.Name = "PathNodeFlags4Label"; + this.PathNodeFlags4Label.Size = new System.Drawing.Size(30, 13); + this.PathNodeFlags4Label.TabIndex = 44; + this.PathNodeFlags4Label.Text = "0x00"; + // + // PathNodeFlags3GroupBox + // + this.PathNodeFlags3GroupBox.Controls.Add(this.PathNodeFlags32UpDown); + this.PathNodeFlags3GroupBox.Controls.Add(this.label70); + this.PathNodeFlags3GroupBox.Controls.Add(this.PathNodeFlags31CheckBox); + this.PathNodeFlags3GroupBox.Controls.Add(this.PathNodeFlags3UpDown); + this.PathNodeFlags3GroupBox.Controls.Add(this.PathNodeFlags3Label); + this.PathNodeFlags3GroupBox.Location = new System.Drawing.Point(7, 318); + this.PathNodeFlags3GroupBox.Name = "PathNodeFlags3GroupBox"; + this.PathNodeFlags3GroupBox.Size = new System.Drawing.Size(223, 84); + this.PathNodeFlags3GroupBox.TabIndex = 46; + this.PathNodeFlags3GroupBox.TabStop = false; + this.PathNodeFlags3GroupBox.Text = "Flags 3"; + // + // PathNodeFlags32UpDown + // + this.PathNodeFlags32UpDown.Location = new System.Drawing.Point(147, 44); + this.PathNodeFlags32UpDown.Maximum = new decimal(new int[] { + 127, + 0, + 0, + 0}); + this.PathNodeFlags32UpDown.Name = "PathNodeFlags32UpDown"; + this.PathNodeFlags32UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeFlags32UpDown.TabIndex = 37; + this.PathNodeFlags32UpDown.ValueChanged += new System.EventHandler(this.PathNodeFlags32UpDown_ValueChanged); + // + // label70 + // + this.label70.AutoSize = true; + this.label70.Location = new System.Drawing.Point(111, 46); + this.label70.Name = "label70"; + this.label70.Size = new System.Drawing.Size(30, 13); + this.label70.TabIndex = 36; + this.label70.Text = "Unk:"; + // + // PathNodeFlags31CheckBox + // + this.PathNodeFlags31CheckBox.AutoSize = true; + this.PathNodeFlags31CheckBox.Location = new System.Drawing.Point(6, 45); + this.PathNodeFlags31CheckBox.Name = "PathNodeFlags31CheckBox"; + this.PathNodeFlags31CheckBox.Size = new System.Drawing.Size(85, 17); + this.PathNodeFlags31CheckBox.TabIndex = 35; + this.PathNodeFlags31CheckBox.Text = "Interior node"; + this.PathNodeFlags31CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags31CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags31CheckBox_CheckedChanged); + // + // PathNodeFlags3UpDown + // + this.PathNodeFlags3UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeFlags3UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeFlags3UpDown.Name = "PathNodeFlags3UpDown"; + this.PathNodeFlags3UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeFlags3UpDown.TabIndex = 43; + this.PathNodeFlags3UpDown.ValueChanged += new System.EventHandler(this.PathNodeFlags3UpDown_ValueChanged); + // + // PathNodeFlags3Label + // + this.PathNodeFlags3Label.AutoSize = true; + this.PathNodeFlags3Label.Location = new System.Drawing.Point(74, 21); + this.PathNodeFlags3Label.Name = "PathNodeFlags3Label"; + this.PathNodeFlags3Label.Size = new System.Drawing.Size(30, 13); + this.PathNodeFlags3Label.TabIndex = 44; + this.PathNodeFlags3Label.Text = "0x00"; + // + // PathNodeFlags2GroupBox + // + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags21CheckBox); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags28CheckBox); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags22CheckBox); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags27CheckBox); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags23CheckBox); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags26CheckBox); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags24CheckBox); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags25CheckBox); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags2UpDown); + this.PathNodeFlags2GroupBox.Controls.Add(this.PathNodeFlags2Label); + this.PathNodeFlags2GroupBox.Location = new System.Drawing.Point(249, 96); + this.PathNodeFlags2GroupBox.Name = "PathNodeFlags2GroupBox"; + this.PathNodeFlags2GroupBox.Size = new System.Drawing.Size(115, 216); + this.PathNodeFlags2GroupBox.TabIndex = 45; + this.PathNodeFlags2GroupBox.TabStop = false; + this.PathNodeFlags2GroupBox.Text = "Flags 2"; + // + // PathNodeFlags21CheckBox + // + this.PathNodeFlags21CheckBox.AutoSize = true; + this.PathNodeFlags21CheckBox.Location = new System.Drawing.Point(6, 45); + this.PathNodeFlags21CheckBox.Name = "PathNodeFlags21CheckBox"; + this.PathNodeFlags21CheckBox.Size = new System.Drawing.Size(79, 17); + this.PathNodeFlags21CheckBox.TabIndex = 35; + this.PathNodeFlags21CheckBox.Text = "Slow unk 2"; + this.PathNodeFlags21CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags21CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags21CheckBox_CheckedChanged); + // + // PathNodeFlags28CheckBox + // + this.PathNodeFlags28CheckBox.AutoSize = true; + this.PathNodeFlags28CheckBox.Location = new System.Drawing.Point(6, 192); + this.PathNodeFlags28CheckBox.Name = "PathNodeFlags28CheckBox"; + this.PathNodeFlags28CheckBox.Size = new System.Drawing.Size(81, 17); + this.PathNodeFlags28CheckBox.TabIndex = 42; + this.PathNodeFlags28CheckBox.Text = "Back road?"; + this.PathNodeFlags28CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags28CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags28CheckBox_CheckedChanged); + // + // PathNodeFlags22CheckBox + // + this.PathNodeFlags22CheckBox.AutoSize = true; + this.PathNodeFlags22CheckBox.Location = new System.Drawing.Point(6, 66); + this.PathNodeFlags22CheckBox.Name = "PathNodeFlags22CheckBox"; + this.PathNodeFlags22CheckBox.Size = new System.Drawing.Size(72, 17); + this.PathNodeFlags22CheckBox.TabIndex = 36; + this.PathNodeFlags22CheckBox.Text = "Unused 2"; + this.PathNodeFlags22CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags22CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags22CheckBox_CheckedChanged); + // + // PathNodeFlags27CheckBox + // + this.PathNodeFlags27CheckBox.AutoSize = true; + this.PathNodeFlags27CheckBox.Location = new System.Drawing.Point(6, 171); + this.PathNodeFlags27CheckBox.Name = "PathNodeFlags27CheckBox"; + this.PathNodeFlags27CheckBox.Size = new System.Drawing.Size(66, 17); + this.PathNodeFlags27CheckBox.TabIndex = 41; + this.PathNodeFlags27CheckBox.Text = "Freeway"; + this.PathNodeFlags27CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags27CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags27CheckBox_CheckedChanged); + // + // PathNodeFlags23CheckBox + // + this.PathNodeFlags23CheckBox.AutoSize = true; + this.PathNodeFlags23CheckBox.Location = new System.Drawing.Point(6, 87); + this.PathNodeFlags23CheckBox.Name = "PathNodeFlags23CheckBox"; + this.PathNodeFlags23CheckBox.Size = new System.Drawing.Size(96, 17); + this.PathNodeFlags23CheckBox.TabIndex = 37; + this.PathNodeFlags23CheckBox.Text = "Junction unk 5"; + this.PathNodeFlags23CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags23CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags23CheckBox_CheckedChanged); + // + // PathNodeFlags26CheckBox + // + this.PathNodeFlags26CheckBox.AutoSize = true; + this.PathNodeFlags26CheckBox.Location = new System.Drawing.Point(6, 150); + this.PathNodeFlags26CheckBox.Name = "PathNodeFlags26CheckBox"; + this.PathNodeFlags26CheckBox.Size = new System.Drawing.Size(86, 17); + this.PathNodeFlags26CheckBox.TabIndex = 40; + this.PathNodeFlags26CheckBox.Text = "Water/boats"; + this.PathNodeFlags26CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags26CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags26CheckBox_CheckedChanged); + // + // PathNodeFlags24CheckBox + // + this.PathNodeFlags24CheckBox.AutoSize = true; + this.PathNodeFlags24CheckBox.Location = new System.Drawing.Point(6, 108); + this.PathNodeFlags24CheckBox.Name = "PathNodeFlags24CheckBox"; + this.PathNodeFlags24CheckBox.Size = new System.Drawing.Size(72, 17); + this.PathNodeFlags24CheckBox.TabIndex = 38; + this.PathNodeFlags24CheckBox.Text = "Unused 8"; + this.PathNodeFlags24CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags24CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags24CheckBox_CheckedChanged); + // + // PathNodeFlags25CheckBox + // + this.PathNodeFlags25CheckBox.AutoSize = true; + this.PathNodeFlags25CheckBox.Location = new System.Drawing.Point(6, 129); + this.PathNodeFlags25CheckBox.Name = "PathNodeFlags25CheckBox"; + this.PathNodeFlags25CheckBox.Size = new System.Drawing.Size(79, 17); + this.PathNodeFlags25CheckBox.TabIndex = 39; + this.PathNodeFlags25CheckBox.Text = "Slow unk 3"; + this.PathNodeFlags25CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags25CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags25CheckBox_CheckedChanged); + // + // PathNodeFlags2UpDown + // + this.PathNodeFlags2UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeFlags2UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeFlags2UpDown.Name = "PathNodeFlags2UpDown"; + this.PathNodeFlags2UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeFlags2UpDown.TabIndex = 43; + this.PathNodeFlags2UpDown.ValueChanged += new System.EventHandler(this.PathNodeFlags2UpDown_ValueChanged); + // + // PathNodeFlags2Label + // + this.PathNodeFlags2Label.AutoSize = true; + this.PathNodeFlags2Label.Location = new System.Drawing.Point(74, 21); + this.PathNodeFlags2Label.Name = "PathNodeFlags2Label"; + this.PathNodeFlags2Label.Size = new System.Drawing.Size(30, 13); + this.PathNodeFlags2Label.TabIndex = 44; + this.PathNodeFlags2Label.Text = "0x00"; + // + // PathNodeFlags1GroupBox + // + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags11CheckBox); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags18CheckBox); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags12CheckBox); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags17CheckBox); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags13CheckBox); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags16CheckBox); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags14CheckBox); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags15CheckBox); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags1UpDown); + this.PathNodeFlags1GroupBox.Controls.Add(this.PathNodeFlags1Label); + this.PathNodeFlags1GroupBox.Location = new System.Drawing.Point(128, 96); + this.PathNodeFlags1GroupBox.Name = "PathNodeFlags1GroupBox"; + this.PathNodeFlags1GroupBox.Size = new System.Drawing.Size(115, 216); + this.PathNodeFlags1GroupBox.TabIndex = 44; + this.PathNodeFlags1GroupBox.TabStop = false; + this.PathNodeFlags1GroupBox.Text = "Flags 1"; + // + // PathNodeFlags11CheckBox + // + this.PathNodeFlags11CheckBox.AutoSize = true; + this.PathNodeFlags11CheckBox.Location = new System.Drawing.Point(6, 45); + this.PathNodeFlags11CheckBox.Name = "PathNodeFlags11CheckBox"; + this.PathNodeFlags11CheckBox.Size = new System.Drawing.Size(82, 17); + this.PathNodeFlags11CheckBox.TabIndex = 35; + this.PathNodeFlags11CheckBox.Text = "L turn lane?"; + this.PathNodeFlags11CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags11CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags11CheckBox_CheckedChanged); + // + // PathNodeFlags18CheckBox + // + this.PathNodeFlags18CheckBox.AutoSize = true; + this.PathNodeFlags18CheckBox.Location = new System.Drawing.Point(6, 192); + this.PathNodeFlags18CheckBox.Name = "PathNodeFlags18CheckBox"; + this.PathNodeFlags18CheckBox.Size = new System.Drawing.Size(96, 17); + this.PathNodeFlags18CheckBox.TabIndex = 42; + this.PathNodeFlags18CheckBox.Text = "Junction unk 4"; + this.PathNodeFlags18CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags18CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags18CheckBox_CheckedChanged); + // + // PathNodeFlags12CheckBox + // + this.PathNodeFlags12CheckBox.AutoSize = true; + this.PathNodeFlags12CheckBox.Location = new System.Drawing.Point(6, 66); + this.PathNodeFlags12CheckBox.Name = "PathNodeFlags12CheckBox"; + this.PathNodeFlags12CheckBox.Size = new System.Drawing.Size(98, 17); + this.PathNodeFlags12CheckBox.TabIndex = 36; + this.PathNodeFlags12CheckBox.Text = "L turn no return"; + this.PathNodeFlags12CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags12CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags12CheckBox_CheckedChanged); + // + // PathNodeFlags17CheckBox + // + this.PathNodeFlags17CheckBox.AutoSize = true; + this.PathNodeFlags17CheckBox.Location = new System.Drawing.Point(6, 171); + this.PathNodeFlags17CheckBox.Name = "PathNodeFlags17CheckBox"; + this.PathNodeFlags17CheckBox.Size = new System.Drawing.Size(108, 17); + this.PathNodeFlags17CheckBox.TabIndex = 41; + this.PathNodeFlags17CheckBox.Text = "Traffic light unk 3"; + this.PathNodeFlags17CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags17CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags17CheckBox_CheckedChanged); + // + // PathNodeFlags13CheckBox + // + this.PathNodeFlags13CheckBox.AutoSize = true; + this.PathNodeFlags13CheckBox.Location = new System.Drawing.Point(6, 87); + this.PathNodeFlags13CheckBox.Name = "PathNodeFlags13CheckBox"; + this.PathNodeFlags13CheckBox.Size = new System.Drawing.Size(100, 17); + this.PathNodeFlags13CheckBox.TabIndex = 37; + this.PathNodeFlags13CheckBox.Text = "R turn no return"; + this.PathNodeFlags13CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags13CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags13CheckBox_CheckedChanged); + // + // PathNodeFlags16CheckBox + // + this.PathNodeFlags16CheckBox.AutoSize = true; + this.PathNodeFlags16CheckBox.Location = new System.Drawing.Point(6, 150); + this.PathNodeFlags16CheckBox.Name = "PathNodeFlags16CheckBox"; + this.PathNodeFlags16CheckBox.Size = new System.Drawing.Size(96, 17); + this.PathNodeFlags16CheckBox.TabIndex = 40; + this.PathNodeFlags16CheckBox.Text = "Junction unk 3"; + this.PathNodeFlags16CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags16CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags16CheckBox_CheckedChanged); + // + // PathNodeFlags14CheckBox + // + this.PathNodeFlags14CheckBox.AutoSize = true; + this.PathNodeFlags14CheckBox.Location = new System.Drawing.Point(6, 108); + this.PathNodeFlags14CheckBox.Name = "PathNodeFlags14CheckBox"; + this.PathNodeFlags14CheckBox.Size = new System.Drawing.Size(108, 17); + this.PathNodeFlags14CheckBox.TabIndex = 38; + this.PathNodeFlags14CheckBox.Text = "Traffic light unk 1"; + this.PathNodeFlags14CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags14CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags14CheckBox_CheckedChanged); + // + // PathNodeFlags15CheckBox + // + this.PathNodeFlags15CheckBox.AutoSize = true; + this.PathNodeFlags15CheckBox.Location = new System.Drawing.Point(6, 129); + this.PathNodeFlags15CheckBox.Name = "PathNodeFlags15CheckBox"; + this.PathNodeFlags15CheckBox.Size = new System.Drawing.Size(108, 17); + this.PathNodeFlags15CheckBox.TabIndex = 39; + this.PathNodeFlags15CheckBox.Text = "Traffic light unk 2"; + this.PathNodeFlags15CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags15CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags15CheckBox_CheckedChanged); + // + // PathNodeFlags1UpDown + // + this.PathNodeFlags1UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeFlags1UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeFlags1UpDown.Name = "PathNodeFlags1UpDown"; + this.PathNodeFlags1UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeFlags1UpDown.TabIndex = 43; + this.PathNodeFlags1UpDown.ValueChanged += new System.EventHandler(this.PathNodeFlags1UpDown_ValueChanged); + // + // PathNodeFlags1Label + // + this.PathNodeFlags1Label.AutoSize = true; + this.PathNodeFlags1Label.Location = new System.Drawing.Point(74, 21); + this.PathNodeFlags1Label.Name = "PathNodeFlags1Label"; + this.PathNodeFlags1Label.Size = new System.Drawing.Size(30, 13); + this.PathNodeFlags1Label.TabIndex = 44; + this.PathNodeFlags1Label.Text = "0x00"; + // + // PathNodeFlags0GroupBox + // + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags01CheckBox); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags08CheckBox); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags02CheckBox); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags07CheckBox); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags03CheckBox); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags06CheckBox); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags04CheckBox); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags05CheckBox); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags0UpDown); + this.PathNodeFlags0GroupBox.Controls.Add(this.PathNodeFlags0Label); + this.PathNodeFlags0GroupBox.Location = new System.Drawing.Point(7, 96); + this.PathNodeFlags0GroupBox.Name = "PathNodeFlags0GroupBox"; + this.PathNodeFlags0GroupBox.Size = new System.Drawing.Size(115, 216); + this.PathNodeFlags0GroupBox.TabIndex = 43; + this.PathNodeFlags0GroupBox.TabStop = false; + this.PathNodeFlags0GroupBox.Text = "Flags 0"; + // + // PathNodeFlags01CheckBox + // + this.PathNodeFlags01CheckBox.AutoSize = true; + this.PathNodeFlags01CheckBox.Location = new System.Drawing.Point(6, 45); + this.PathNodeFlags01CheckBox.Name = "PathNodeFlags01CheckBox"; + this.PathNodeFlags01CheckBox.Size = new System.Drawing.Size(65, 17); + this.PathNodeFlags01CheckBox.TabIndex = 35; + this.PathNodeFlags01CheckBox.Text = "Scripted"; + this.PathNodeFlags01CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags01CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags01CheckBox_CheckedChanged); + // + // PathNodeFlags08CheckBox + // + this.PathNodeFlags08CheckBox.AutoSize = true; + this.PathNodeFlags08CheckBox.Location = new System.Drawing.Point(6, 192); + this.PathNodeFlags08CheckBox.Name = "PathNodeFlags08CheckBox"; + this.PathNodeFlags08CheckBox.Size = new System.Drawing.Size(96, 17); + this.PathNodeFlags08CheckBox.TabIndex = 42; + this.PathNodeFlags08CheckBox.Text = "Junction unk 2"; + this.PathNodeFlags08CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags08CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags08CheckBox_CheckedChanged); + // + // PathNodeFlags02CheckBox + // + this.PathNodeFlags02CheckBox.AutoSize = true; + this.PathNodeFlags02CheckBox.Location = new System.Drawing.Point(6, 66); + this.PathNodeFlags02CheckBox.Name = "PathNodeFlags02CheckBox"; + this.PathNodeFlags02CheckBox.Size = new System.Drawing.Size(89, 17); + this.PathNodeFlags02CheckBox.TabIndex = 36; + this.PathNodeFlags02CheckBox.Text = "GPS enable?"; + this.PathNodeFlags02CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags02CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags02CheckBox_CheckedChanged); + // + // PathNodeFlags07CheckBox + // + this.PathNodeFlags07CheckBox.AutoSize = true; + this.PathNodeFlags07CheckBox.Location = new System.Drawing.Point(6, 171); + this.PathNodeFlags07CheckBox.Name = "PathNodeFlags07CheckBox"; + this.PathNodeFlags07CheckBox.Size = new System.Drawing.Size(96, 17); + this.PathNodeFlags07CheckBox.TabIndex = 41; + this.PathNodeFlags07CheckBox.Text = "Junction unk 1"; + this.PathNodeFlags07CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags07CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags07CheckBox_CheckedChanged); + // + // PathNodeFlags03CheckBox + // + this.PathNodeFlags03CheckBox.AutoSize = true; + this.PathNodeFlags03CheckBox.Location = new System.Drawing.Point(6, 87); + this.PathNodeFlags03CheckBox.Name = "PathNodeFlags03CheckBox"; + this.PathNodeFlags03CheckBox.Size = new System.Drawing.Size(72, 17); + this.PathNodeFlags03CheckBox.TabIndex = 37; + this.PathNodeFlags03CheckBox.Text = "Unused 4"; + this.PathNodeFlags03CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags03CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags03CheckBox_CheckedChanged); + // + // PathNodeFlags06CheckBox + // + this.PathNodeFlags06CheckBox.AutoSize = true; + this.PathNodeFlags06CheckBox.Location = new System.Drawing.Point(6, 150); + this.PathNodeFlags06CheckBox.Name = "PathNodeFlags06CheckBox"; + this.PathNodeFlags06CheckBox.Size = new System.Drawing.Size(79, 17); + this.PathNodeFlags06CheckBox.TabIndex = 40; + this.PathNodeFlags06CheckBox.Text = "Slow unk 1"; + this.PathNodeFlags06CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags06CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags06CheckBox_CheckedChanged); + // + // PathNodeFlags04CheckBox + // + this.PathNodeFlags04CheckBox.AutoSize = true; + this.PathNodeFlags04CheckBox.Location = new System.Drawing.Point(6, 108); + this.PathNodeFlags04CheckBox.Name = "PathNodeFlags04CheckBox"; + this.PathNodeFlags04CheckBox.Size = new System.Drawing.Size(87, 17); + this.PathNodeFlags04CheckBox.TabIndex = 38; + this.PathNodeFlags04CheckBox.Text = "Gravel road?"; + this.PathNodeFlags04CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags04CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags04CheckBox_CheckedChanged); + // + // PathNodeFlags05CheckBox + // + this.PathNodeFlags05CheckBox.AutoSize = true; + this.PathNodeFlags05CheckBox.Location = new System.Drawing.Point(6, 129); + this.PathNodeFlags05CheckBox.Name = "PathNodeFlags05CheckBox"; + this.PathNodeFlags05CheckBox.Size = new System.Drawing.Size(78, 17); + this.PathNodeFlags05CheckBox.TabIndex = 39; + this.PathNodeFlags05CheckBox.Text = "Unused 16"; + this.PathNodeFlags05CheckBox.UseVisualStyleBackColor = true; + this.PathNodeFlags05CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeFlags05CheckBox_CheckedChanged); + // + // PathNodeFlags0UpDown + // + this.PathNodeFlags0UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeFlags0UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeFlags0UpDown.Name = "PathNodeFlags0UpDown"; + this.PathNodeFlags0UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeFlags0UpDown.TabIndex = 43; + this.PathNodeFlags0UpDown.ValueChanged += new System.EventHandler(this.PathNodeFlags0UpDown_ValueChanged); + // + // PathNodeFlags0Label + // + this.PathNodeFlags0Label.AutoSize = true; + this.PathNodeFlags0Label.Location = new System.Drawing.Point(74, 21); + this.PathNodeFlags0Label.Name = "PathNodeFlags0Label"; + this.PathNodeFlags0Label.Size = new System.Drawing.Size(30, 13); + this.PathNodeFlags0Label.TabIndex = 44; + this.PathNodeFlags0Label.Text = "0x00"; + // + // PathNodeDeleteButton + // + this.PathNodeDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.PathNodeDeleteButton.Enabled = false; + this.PathNodeDeleteButton.Location = new System.Drawing.Point(406, 36); + this.PathNodeDeleteButton.Name = "PathNodeDeleteButton"; + this.PathNodeDeleteButton.Size = new System.Drawing.Size(90, 23); + this.PathNodeDeleteButton.TabIndex = 12; + this.PathNodeDeleteButton.Text = "Delete Node"; + this.PathNodeDeleteButton.UseVisualStyleBackColor = true; + this.PathNodeDeleteButton.Click += new System.EventHandler(this.PathNodeDeleteButton_Click); + // + // PathNodeAreaIDUpDown + // + this.PathNodeAreaIDUpDown.Location = new System.Drawing.Point(78, 12); + this.PathNodeAreaIDUpDown.Maximum = new decimal(new int[] { + 1023, + 0, + 0, + 0}); + this.PathNodeAreaIDUpDown.Name = "PathNodeAreaIDUpDown"; + this.PathNodeAreaIDUpDown.Size = new System.Drawing.Size(74, 20); + this.PathNodeAreaIDUpDown.TabIndex = 6; + this.PathNodeAreaIDUpDown.ValueChanged += new System.EventHandler(this.PathNodeAreaIDUpDown_ValueChanged); + // + // PathNodeAddToProjectButton + // + this.PathNodeAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.PathNodeAddToProjectButton.Enabled = false; + this.PathNodeAddToProjectButton.Location = new System.Drawing.Point(310, 36); + this.PathNodeAddToProjectButton.Name = "PathNodeAddToProjectButton"; + this.PathNodeAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.PathNodeAddToProjectButton.TabIndex = 11; + this.PathNodeAddToProjectButton.Text = "Add to Project"; + this.PathNodeAddToProjectButton.UseVisualStyleBackColor = true; + this.PathNodeAddToProjectButton.Click += new System.EventHandler(this.PathNodeAddToProjectButton_Click); + // + // label49 + // + this.label49.AutoSize = true; + this.label49.Location = new System.Drawing.Point(26, 14); + this.label49.Name = "label49"; + this.label49.Size = new System.Drawing.Size(46, 13); + this.label49.TabIndex = 5; + this.label49.Text = "Area ID:"; + // + // label50 + // + this.label50.AutoSize = true; + this.label50.Location = new System.Drawing.Point(166, 14); + this.label50.Name = "label50"; + this.label50.Size = new System.Drawing.Size(50, 13); + this.label50.TabIndex = 7; + this.label50.Text = "Node ID:"; + // + // label68 + // + this.label68.AutoSize = true; + this.label68.Location = new System.Drawing.Point(302, 14); + this.label68.Name = "label68"; + this.label68.Size = new System.Drawing.Size(156, 13); + this.label68.TabIndex = 32; + this.label68.Text = "(These will be set automatically)"; + // + // PathNodeNodeIDUpDown + // + this.PathNodeNodeIDUpDown.Location = new System.Drawing.Point(222, 12); + this.PathNodeNodeIDUpDown.Maximum = new decimal(new int[] { + 100000, + 0, + 0, + 0}); + this.PathNodeNodeIDUpDown.Name = "PathNodeNodeIDUpDown"; + this.PathNodeNodeIDUpDown.Size = new System.Drawing.Size(74, 20); + this.PathNodeNodeIDUpDown.TabIndex = 8; + this.PathNodeNodeIDUpDown.ValueChanged += new System.EventHandler(this.PathNodeNodeIDUpDown_ValueChanged); + // + // label52 + // + this.label52.AutoSize = true; + this.label52.Location = new System.Drawing.Point(4, 67); + this.label52.Name = "label52"; + this.label52.Size = new System.Drawing.Size(70, 13); + this.label52.TabIndex = 9; + this.label52.Text = "Street (hash):"; + // + // PathNodeStreetHashTextBox + // + this.PathNodeStreetHashTextBox.Location = new System.Drawing.Point(78, 64); + this.PathNodeStreetHashTextBox.Name = "PathNodeStreetHashTextBox"; + this.PathNodeStreetHashTextBox.Size = new System.Drawing.Size(138, 20); + this.PathNodeStreetHashTextBox.TabIndex = 13; + this.PathNodeStreetHashTextBox.TextChanged += new System.EventHandler(this.PathNodeStreetHashTextBox_TextChanged); + // + // PathNodeGoToButton + // + this.PathNodeGoToButton.Location = new System.Drawing.Point(222, 36); + this.PathNodeGoToButton.Name = "PathNodeGoToButton"; + this.PathNodeGoToButton.Size = new System.Drawing.Size(68, 23); + this.PathNodeGoToButton.TabIndex = 10; + this.PathNodeGoToButton.Text = "Go to"; + this.PathNodeGoToButton.UseVisualStyleBackColor = true; + this.PathNodeGoToButton.Click += new System.EventHandler(this.PathNodeGoToButton_Click); + // + // PathNodeStreetNameLabel + // + this.PathNodeStreetNameLabel.AutoSize = true; + this.PathNodeStreetNameLabel.Location = new System.Drawing.Point(223, 67); + this.PathNodeStreetNameLabel.Name = "PathNodeStreetNameLabel"; + this.PathNodeStreetNameLabel.Size = new System.Drawing.Size(73, 13); + this.PathNodeStreetNameLabel.TabIndex = 11; + this.PathNodeStreetNameLabel.Text = "Name: [None]"; + // + // PathNodePositionTextBox + // + this.PathNodePositionTextBox.Location = new System.Drawing.Point(78, 38); + this.PathNodePositionTextBox.Name = "PathNodePositionTextBox"; + this.PathNodePositionTextBox.Size = new System.Drawing.Size(138, 20); + this.PathNodePositionTextBox.TabIndex = 9; + this.PathNodePositionTextBox.TextChanged += new System.EventHandler(this.PathNodePositionTextBox_TextChanged); + // + // label55 + // + this.label55.AutoSize = true; + this.label55.Location = new System.Drawing.Point(25, 41); + this.label55.Name = "label55"; + this.label55.Size = new System.Drawing.Size(47, 13); + this.label55.TabIndex = 28; + this.label55.Text = "Position:"; + // + // PathNodeLinksTabPage + // + this.PathNodeLinksTabPage.Controls.Add(this.splitContainer2); + this.PathNodeLinksTabPage.Location = new System.Drawing.Point(4, 22); + this.PathNodeLinksTabPage.Name = "PathNodeLinksTabPage"; + this.PathNodeLinksTabPage.Padding = new System.Windows.Forms.Padding(3); + this.PathNodeLinksTabPage.Size = new System.Drawing.Size(499, 414); + this.PathNodeLinksTabPage.TabIndex = 0; + this.PathNodeLinksTabPage.Text = "Path Links"; + this.PathNodeLinksTabPage.UseVisualStyleBackColor = true; + // + // splitContainer2 + // + this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer2.Location = new System.Drawing.Point(3, 3); + this.splitContainer2.Name = "splitContainer2"; + // + // splitContainer2.Panel1 + // + this.splitContainer2.Panel1.Controls.Add(this.PathNodeRemoveLinkButton); + this.splitContainer2.Panel1.Controls.Add(this.PathNodeAddLinkButton); + this.splitContainer2.Panel1.Controls.Add(this.PathNodeLinksListBox); + this.splitContainer2.Panel1.Controls.Add(this.PathNodeLinkCountLabel); + // + // splitContainer2.Panel2 + // + this.splitContainer2.Panel2.Controls.Add(this.PathNodeLinkPanel); + this.splitContainer2.Size = new System.Drawing.Size(493, 408); + this.splitContainer2.SplitterDistance = 168; + this.splitContainer2.TabIndex = 0; + // + // PathNodeRemoveLinkButton + // + this.PathNodeRemoveLinkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.PathNodeRemoveLinkButton.Location = new System.Drawing.Point(85, 382); + this.PathNodeRemoveLinkButton.Name = "PathNodeRemoveLinkButton"; + this.PathNodeRemoveLinkButton.Size = new System.Drawing.Size(76, 23); + this.PathNodeRemoveLinkButton.TabIndex = 2; + this.PathNodeRemoveLinkButton.Text = "Remove"; + this.PathNodeRemoveLinkButton.UseVisualStyleBackColor = true; + this.PathNodeRemoveLinkButton.Click += new System.EventHandler(this.PathNodeRemoveLinkButton_Click); + // + // PathNodeAddLinkButton + // + this.PathNodeAddLinkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.PathNodeAddLinkButton.Location = new System.Drawing.Point(3, 382); + this.PathNodeAddLinkButton.Name = "PathNodeAddLinkButton"; + this.PathNodeAddLinkButton.Size = new System.Drawing.Size(76, 23); + this.PathNodeAddLinkButton.TabIndex = 1; + this.PathNodeAddLinkButton.Text = "Add"; + this.PathNodeAddLinkButton.UseVisualStyleBackColor = true; + this.PathNodeAddLinkButton.Click += new System.EventHandler(this.PathNodeAddLinkButton_Click); + // + // PathNodeLinksListBox + // + this.PathNodeLinksListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.PathNodeLinksListBox.FormattingEnabled = true; + this.PathNodeLinksListBox.Location = new System.Drawing.Point(0, 0); + this.PathNodeLinksListBox.Name = "PathNodeLinksListBox"; + this.PathNodeLinksListBox.Size = new System.Drawing.Size(165, 342); + this.PathNodeLinksListBox.TabIndex = 0; + this.PathNodeLinksListBox.SelectedIndexChanged += new System.EventHandler(this.PathNodeLinksListBox_SelectedIndexChanged); + // + // PathNodeLinkCountLabel + // + this.PathNodeLinkCountLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.PathNodeLinkCountLabel.AutoSize = true; + this.PathNodeLinkCountLabel.Location = new System.Drawing.Point(3, 366); + this.PathNodeLinkCountLabel.Name = "PathNodeLinkCountLabel"; + this.PathNodeLinkCountLabel.Size = new System.Drawing.Size(70, 13); + this.PathNodeLinkCountLabel.TabIndex = 31; + this.PathNodeLinkCountLabel.Text = "Link Count: 0"; + // + // PathNodeLinkPanel + // + this.PathNodeLinkPanel.Controls.Add(this.PathLinkFlags2GroupBox); + this.PathNodeLinkPanel.Controls.Add(this.PathLinkFlags1GroupBox); + this.PathNodeLinkPanel.Controls.Add(this.PathLinkFlags0GroupBox); + this.PathNodeLinkPanel.Controls.Add(this.PathNodeLinkageStatusLabel); + this.PathNodeLinkPanel.Controls.Add(this.PathNodeLinkLengthUpDown); + this.PathNodeLinkPanel.Controls.Add(this.label57); + this.PathNodeLinkPanel.Controls.Add(this.PathNodeLinkNodeIDUpDown); + this.PathNodeLinkPanel.Controls.Add(this.label51); + this.PathNodeLinkPanel.Controls.Add(this.PathNodeLinkAreaIDUpDown); + this.PathNodeLinkPanel.Controls.Add(this.label54); + this.PathNodeLinkPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.PathNodeLinkPanel.Enabled = false; + this.PathNodeLinkPanel.Location = new System.Drawing.Point(0, 0); + this.PathNodeLinkPanel.Name = "PathNodeLinkPanel"; + this.PathNodeLinkPanel.Size = new System.Drawing.Size(321, 408); + this.PathNodeLinkPanel.TabIndex = 0; + // + // PathLinkFlags2GroupBox + // + this.PathLinkFlags2GroupBox.Controls.Add(this.PathNodeLinkFlags21CheckBox); + this.PathLinkFlags2GroupBox.Controls.Add(this.PathNodeLinkFlags22CheckBox); + this.PathLinkFlags2GroupBox.Controls.Add(this.label53); + this.PathLinkFlags2GroupBox.Controls.Add(this.PathNodeLinkFwdLanesUpDown); + this.PathLinkFlags2GroupBox.Controls.Add(this.label56); + this.PathLinkFlags2GroupBox.Controls.Add(this.PathNodeLinkBackLanesUpDown); + this.PathLinkFlags2GroupBox.Controls.Add(this.PathNodeLinkFlags2UpDown); + this.PathLinkFlags2GroupBox.Controls.Add(this.PathNodeLinkFlags2Label); + this.PathLinkFlags2GroupBox.Location = new System.Drawing.Point(13, 240); + this.PathLinkFlags2GroupBox.Name = "PathLinkFlags2GroupBox"; + this.PathLinkFlags2GroupBox.Size = new System.Drawing.Size(141, 145); + this.PathLinkFlags2GroupBox.TabIndex = 18; + this.PathLinkFlags2GroupBox.TabStop = false; + this.PathLinkFlags2GroupBox.Text = "Flags 2"; + // + // PathNodeLinkFlags21CheckBox + // + this.PathNodeLinkFlags21CheckBox.AutoSize = true; + this.PathNodeLinkFlags21CheckBox.Location = new System.Drawing.Point(6, 45); + this.PathNodeLinkFlags21CheckBox.Name = "PathNodeLinkFlags21CheckBox"; + this.PathNodeLinkFlags21CheckBox.Size = new System.Drawing.Size(123, 17); + this.PathNodeLinkFlags21CheckBox.TabIndex = 33; + this.PathNodeLinkFlags21CheckBox.Text = "Angled/merged links"; + this.PathNodeLinkFlags21CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags21CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags21CheckBox_CheckedChanged); + // + // PathNodeLinkFlags22CheckBox + // + this.PathNodeLinkFlags22CheckBox.AutoSize = true; + this.PathNodeLinkFlags22CheckBox.Location = new System.Drawing.Point(6, 66); + this.PathNodeLinkFlags22CheckBox.Name = "PathNodeLinkFlags22CheckBox"; + this.PathNodeLinkFlags22CheckBox.Size = new System.Drawing.Size(129, 17); + this.PathNodeLinkFlags22CheckBox.TabIndex = 34; + this.PathNodeLinkFlags22CheckBox.Text = "Lane change / U-turn"; + this.PathNodeLinkFlags22CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags22CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags22CheckBox_CheckedChanged); + // + // label53 + // + this.label53.AutoSize = true; + this.label53.Location = new System.Drawing.Point(7, 118); + this.label53.Name = "label53"; + this.label53.Size = new System.Drawing.Size(58, 13); + this.label53.TabIndex = 37; + this.label53.Text = "Fwd lanes:"; + // + // PathNodeLinkFwdLanesUpDown + // + this.PathNodeLinkFwdLanesUpDown.Location = new System.Drawing.Point(71, 116); + this.PathNodeLinkFwdLanesUpDown.Maximum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.PathNodeLinkFwdLanesUpDown.Name = "PathNodeLinkFwdLanesUpDown"; + this.PathNodeLinkFwdLanesUpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeLinkFwdLanesUpDown.TabIndex = 38; + this.PathNodeLinkFwdLanesUpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkFwdLanesUpDown_ValueChanged); + // + // label56 + // + this.label56.AutoSize = true; + this.label56.Location = new System.Drawing.Point(3, 92); + this.label56.Name = "label56"; + this.label56.Size = new System.Drawing.Size(63, 13); + this.label56.TabIndex = 35; + this.label56.Text = "Back lanes:"; + // + // PathNodeLinkBackLanesUpDown + // + this.PathNodeLinkBackLanesUpDown.Location = new System.Drawing.Point(72, 90); + this.PathNodeLinkBackLanesUpDown.Maximum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.PathNodeLinkBackLanesUpDown.Name = "PathNodeLinkBackLanesUpDown"; + this.PathNodeLinkBackLanesUpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeLinkBackLanesUpDown.TabIndex = 36; + this.PathNodeLinkBackLanesUpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkBackLanesUpDown_ValueChanged); + // + // PathNodeLinkFlags2UpDown + // + this.PathNodeLinkFlags2UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeLinkFlags2UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeLinkFlags2UpDown.Name = "PathNodeLinkFlags2UpDown"; + this.PathNodeLinkFlags2UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeLinkFlags2UpDown.TabIndex = 31; + this.PathNodeLinkFlags2UpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkFlags2UpDown_ValueChanged); + // + // PathNodeLinkFlags2Label + // + this.PathNodeLinkFlags2Label.AutoSize = true; + this.PathNodeLinkFlags2Label.Location = new System.Drawing.Point(74, 21); + this.PathNodeLinkFlags2Label.Name = "PathNodeLinkFlags2Label"; + this.PathNodeLinkFlags2Label.Size = new System.Drawing.Size(30, 13); + this.PathNodeLinkFlags2Label.TabIndex = 32; + this.PathNodeLinkFlags2Label.Text = "0x00"; + // + // PathLinkFlags1GroupBox + // + this.PathLinkFlags1GroupBox.Controls.Add(this.PathNodeLinkOffsetSizeUpDown); + this.PathLinkFlags1GroupBox.Controls.Add(this.label61); + this.PathLinkFlags1GroupBox.Controls.Add(this.PathNodeLinkFlags11CheckBox); + this.PathLinkFlags1GroupBox.Controls.Add(this.PathNodeLinkFlags18CheckBox); + this.PathLinkFlags1GroupBox.Controls.Add(this.PathNodeLinkFlags12CheckBox); + this.PathLinkFlags1GroupBox.Controls.Add(this.PathNodeLinkFlags13CheckBox); + this.PathLinkFlags1GroupBox.Controls.Add(this.PathNodeLinkFlags14CheckBox); + this.PathLinkFlags1GroupBox.Controls.Add(this.PathNodeLinkFlags1UpDown); + this.PathLinkFlags1GroupBox.Controls.Add(this.PathNodeLinkFlags1Label); + this.PathLinkFlags1GroupBox.Location = new System.Drawing.Point(165, 93); + this.PathLinkFlags1GroupBox.Name = "PathLinkFlags1GroupBox"; + this.PathLinkFlags1GroupBox.Size = new System.Drawing.Size(133, 181); + this.PathLinkFlags1GroupBox.TabIndex = 17; + this.PathLinkFlags1GroupBox.TabStop = false; + this.PathLinkFlags1GroupBox.Text = "Flags 1"; + // + // PathNodeLinkOffsetSizeUpDown + // + this.PathNodeLinkOffsetSizeUpDown.Location = new System.Drawing.Point(70, 152); + this.PathNodeLinkOffsetSizeUpDown.Maximum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.PathNodeLinkOffsetSizeUpDown.Name = "PathNodeLinkOffsetSizeUpDown"; + this.PathNodeLinkOffsetSizeUpDown.Size = new System.Drawing.Size(57, 20); + this.PathNodeLinkOffsetSizeUpDown.TabIndex = 39; + this.PathNodeLinkOffsetSizeUpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkOffsetSizeUpDown_ValueChanged); + // + // label61 + // + this.label61.AutoSize = true; + this.label61.Location = new System.Drawing.Point(6, 154); + this.label61.Name = "label61"; + this.label61.Size = new System.Drawing.Size(59, 13); + this.label61.TabIndex = 38; + this.label61.Text = "Offset size:"; + // + // PathNodeLinkFlags11CheckBox + // + this.PathNodeLinkFlags11CheckBox.AutoSize = true; + this.PathNodeLinkFlags11CheckBox.Location = new System.Drawing.Point(6, 45); + this.PathNodeLinkFlags11CheckBox.Name = "PathNodeLinkFlags11CheckBox"; + this.PathNodeLinkFlags11CheckBox.Size = new System.Drawing.Size(72, 17); + this.PathNodeLinkFlags11CheckBox.TabIndex = 30; + this.PathNodeLinkFlags11CheckBox.Text = "Unused 1"; + this.PathNodeLinkFlags11CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags11CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags11CheckBox_CheckedChanged); + // + // PathNodeLinkFlags18CheckBox + // + this.PathNodeLinkFlags18CheckBox.AutoSize = true; + this.PathNodeLinkFlags18CheckBox.Location = new System.Drawing.Point(6, 129); + this.PathNodeLinkFlags18CheckBox.Name = "PathNodeLinkFlags18CheckBox"; + this.PathNodeLinkFlags18CheckBox.Size = new System.Drawing.Size(98, 17); + this.PathNodeLinkFlags18CheckBox.TabIndex = 37; + this.PathNodeLinkFlags18CheckBox.Text = "Negative offset"; + this.PathNodeLinkFlags18CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags18CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags18CheckBox_CheckedChanged); + // + // PathNodeLinkFlags12CheckBox + // + this.PathNodeLinkFlags12CheckBox.AutoSize = true; + this.PathNodeLinkFlags12CheckBox.Location = new System.Drawing.Point(6, 66); + this.PathNodeLinkFlags12CheckBox.Name = "PathNodeLinkFlags12CheckBox"; + this.PathNodeLinkFlags12CheckBox.Size = new System.Drawing.Size(81, 17); + this.PathNodeLinkFlags12CheckBox.TabIndex = 31; + this.PathNodeLinkFlags12CheckBox.Text = "Unknown 1"; + this.PathNodeLinkFlags12CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags12CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags12CheckBox_CheckedChanged); + // + // PathNodeLinkFlags13CheckBox + // + this.PathNodeLinkFlags13CheckBox.AutoSize = true; + this.PathNodeLinkFlags13CheckBox.Location = new System.Drawing.Point(6, 87); + this.PathNodeLinkFlags13CheckBox.Name = "PathNodeLinkFlags13CheckBox"; + this.PathNodeLinkFlags13CheckBox.Size = new System.Drawing.Size(73, 17); + this.PathNodeLinkFlags13CheckBox.TabIndex = 32; + this.PathNodeLinkFlags13CheckBox.Text = "Dead end"; + this.PathNodeLinkFlags13CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags13CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags13CheckBox_CheckedChanged); + // + // PathNodeLinkFlags14CheckBox + // + this.PathNodeLinkFlags14CheckBox.AutoSize = true; + this.PathNodeLinkFlags14CheckBox.Location = new System.Drawing.Point(6, 108); + this.PathNodeLinkFlags14CheckBox.Name = "PathNodeLinkFlags14CheckBox"; + this.PathNodeLinkFlags14CheckBox.Size = new System.Drawing.Size(92, 17); + this.PathNodeLinkFlags14CheckBox.TabIndex = 33; + this.PathNodeLinkFlags14CheckBox.Text = "Dead end exit"; + this.PathNodeLinkFlags14CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags14CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags14CheckBox_CheckedChanged); + // + // PathNodeLinkFlags1UpDown + // + this.PathNodeLinkFlags1UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeLinkFlags1UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeLinkFlags1UpDown.Name = "PathNodeLinkFlags1UpDown"; + this.PathNodeLinkFlags1UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeLinkFlags1UpDown.TabIndex = 28; + this.PathNodeLinkFlags1UpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkFlags1UpDown_ValueChanged); + // + // PathNodeLinkFlags1Label + // + this.PathNodeLinkFlags1Label.AutoSize = true; + this.PathNodeLinkFlags1Label.Location = new System.Drawing.Point(74, 21); + this.PathNodeLinkFlags1Label.Name = "PathNodeLinkFlags1Label"; + this.PathNodeLinkFlags1Label.Size = new System.Drawing.Size(30, 13); + this.PathNodeLinkFlags1Label.TabIndex = 29; + this.PathNodeLinkFlags1Label.Text = "0x00"; + // + // PathLinkFlags0GroupBox + // + this.PathLinkFlags0GroupBox.Controls.Add(this.PathNodeLinkFlags04UpDown); + this.PathLinkFlags0GroupBox.Controls.Add(this.label60); + this.PathLinkFlags0GroupBox.Controls.Add(this.PathNodeLinkFlags03UpDown); + this.PathLinkFlags0GroupBox.Controls.Add(this.label58); + this.PathLinkFlags0GroupBox.Controls.Add(this.PathNodeLinkFlags01CheckBox); + this.PathLinkFlags0GroupBox.Controls.Add(this.PathNodeLinkFlags02CheckBox); + this.PathLinkFlags0GroupBox.Controls.Add(this.PathNodeLinkFlags0UpDown); + this.PathLinkFlags0GroupBox.Controls.Add(this.PathNodeLinkFlags0Label); + this.PathLinkFlags0GroupBox.Location = new System.Drawing.Point(13, 93); + this.PathLinkFlags0GroupBox.Name = "PathLinkFlags0GroupBox"; + this.PathLinkFlags0GroupBox.Size = new System.Drawing.Size(141, 141); + this.PathLinkFlags0GroupBox.TabIndex = 16; + this.PathLinkFlags0GroupBox.TabStop = false; + this.PathLinkFlags0GroupBox.Text = "Flags 0"; + // + // PathNodeLinkFlags04UpDown + // + this.PathNodeLinkFlags04UpDown.Location = new System.Drawing.Point(71, 112); + this.PathNodeLinkFlags04UpDown.Maximum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.PathNodeLinkFlags04UpDown.Name = "PathNodeLinkFlags04UpDown"; + this.PathNodeLinkFlags04UpDown.Size = new System.Drawing.Size(57, 20); + this.PathNodeLinkFlags04UpDown.TabIndex = 32; + this.PathNodeLinkFlags04UpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkFlags04UpDown_ValueChanged); + // + // label60 + // + this.label60.AutoSize = true; + this.label60.Location = new System.Drawing.Point(26, 114); + this.label60.Name = "label60"; + this.label60.Size = new System.Drawing.Size(39, 13); + this.label60.TabIndex = 31; + this.label60.Text = "Unk 2:"; + // + // PathNodeLinkFlags03UpDown + // + this.PathNodeLinkFlags03UpDown.Location = new System.Drawing.Point(71, 88); + this.PathNodeLinkFlags03UpDown.Maximum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.PathNodeLinkFlags03UpDown.Name = "PathNodeLinkFlags03UpDown"; + this.PathNodeLinkFlags03UpDown.Size = new System.Drawing.Size(57, 20); + this.PathNodeLinkFlags03UpDown.TabIndex = 30; + this.PathNodeLinkFlags03UpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkFlags03UpDown_ValueChanged); + // + // label58 + // + this.label58.AutoSize = true; + this.label58.Location = new System.Drawing.Point(26, 90); + this.label58.Name = "label58"; + this.label58.Size = new System.Drawing.Size(39, 13); + this.label58.TabIndex = 29; + this.label58.Text = "Unk 1:"; + // + // PathNodeLinkFlags01CheckBox + // + this.PathNodeLinkFlags01CheckBox.AutoSize = true; + this.PathNodeLinkFlags01CheckBox.Location = new System.Drawing.Point(6, 45); + this.PathNodeLinkFlags01CheckBox.Name = "PathNodeLinkFlags01CheckBox"; + this.PathNodeLinkFlags01CheckBox.Size = new System.Drawing.Size(70, 17); + this.PathNodeLinkFlags01CheckBox.TabIndex = 27; + this.PathNodeLinkFlags01CheckBox.Text = "Special 1"; + this.PathNodeLinkFlags01CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags01CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags01CheckBox_CheckedChanged); + // + // PathNodeLinkFlags02CheckBox + // + this.PathNodeLinkFlags02CheckBox.AutoSize = true; + this.PathNodeLinkFlags02CheckBox.Location = new System.Drawing.Point(6, 66); + this.PathNodeLinkFlags02CheckBox.Name = "PathNodeLinkFlags02CheckBox"; + this.PathNodeLinkFlags02CheckBox.Size = new System.Drawing.Size(86, 17); + this.PathNodeLinkFlags02CheckBox.TabIndex = 28; + this.PathNodeLinkFlags02CheckBox.Text = "Scripted unk"; + this.PathNodeLinkFlags02CheckBox.UseVisualStyleBackColor = true; + this.PathNodeLinkFlags02CheckBox.CheckedChanged += new System.EventHandler(this.PathNodeLinkFlags02CheckBox_CheckedChanged); + // + // PathNodeLinkFlags0UpDown + // + this.PathNodeLinkFlags0UpDown.Location = new System.Drawing.Point(6, 19); + this.PathNodeLinkFlags0UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeLinkFlags0UpDown.Name = "PathNodeLinkFlags0UpDown"; + this.PathNodeLinkFlags0UpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeLinkFlags0UpDown.TabIndex = 25; + this.PathNodeLinkFlags0UpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkFlags0UpDown_ValueChanged); + // + // PathNodeLinkFlags0Label + // + this.PathNodeLinkFlags0Label.AutoSize = true; + this.PathNodeLinkFlags0Label.Location = new System.Drawing.Point(74, 21); + this.PathNodeLinkFlags0Label.Name = "PathNodeLinkFlags0Label"; + this.PathNodeLinkFlags0Label.Size = new System.Drawing.Size(30, 13); + this.PathNodeLinkFlags0Label.TabIndex = 26; + this.PathNodeLinkFlags0Label.Text = "0x00"; + // + // PathNodeLinkageStatusLabel + // + this.PathNodeLinkageStatusLabel.AutoSize = true; + this.PathNodeLinkageStatusLabel.Location = new System.Drawing.Point(74, 33); + this.PathNodeLinkageStatusLabel.Name = "PathNodeLinkageStatusLabel"; + this.PathNodeLinkageStatusLabel.Size = new System.Drawing.Size(10, 13); + this.PathNodeLinkageStatusLabel.TabIndex = 13; + this.PathNodeLinkageStatusLabel.Text = "-"; + // + // PathNodeLinkLengthUpDown + // + this.PathNodeLinkLengthUpDown.Location = new System.Drawing.Point(74, 57); + this.PathNodeLinkLengthUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeLinkLengthUpDown.Name = "PathNodeLinkLengthUpDown"; + this.PathNodeLinkLengthUpDown.Size = new System.Drawing.Size(74, 20); + this.PathNodeLinkLengthUpDown.TabIndex = 15; + this.PathNodeLinkLengthUpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkLengthUpDown_ValueChanged); + // + // label57 + // + this.label57.AutoSize = true; + this.label57.Location = new System.Drawing.Point(6, 59); + this.label57.Name = "label57"; + this.label57.Size = new System.Drawing.Size(62, 13); + this.label57.TabIndex = 14; + this.label57.Text = "Link length:"; + // + // PathNodeLinkNodeIDUpDown + // + this.PathNodeLinkNodeIDUpDown.Location = new System.Drawing.Point(219, 8); + this.PathNodeLinkNodeIDUpDown.Maximum = new decimal(new int[] { + 100000, + 0, + 0, + 0}); + this.PathNodeLinkNodeIDUpDown.Name = "PathNodeLinkNodeIDUpDown"; + this.PathNodeLinkNodeIDUpDown.Size = new System.Drawing.Size(74, 20); + this.PathNodeLinkNodeIDUpDown.TabIndex = 12; + this.PathNodeLinkNodeIDUpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkNodeIDUpDown_ValueChanged); + // + // label51 + // + this.label51.AutoSize = true; + this.label51.Location = new System.Drawing.Point(163, 10); + this.label51.Name = "label51"; + this.label51.Size = new System.Drawing.Size(50, 13); + this.label51.TabIndex = 11; + this.label51.Text = "Node ID:"; + // + // PathNodeLinkAreaIDUpDown + // + this.PathNodeLinkAreaIDUpDown.Location = new System.Drawing.Point(74, 8); + this.PathNodeLinkAreaIDUpDown.Maximum = new decimal(new int[] { + 1023, + 0, + 0, + 0}); + this.PathNodeLinkAreaIDUpDown.Name = "PathNodeLinkAreaIDUpDown"; + this.PathNodeLinkAreaIDUpDown.Size = new System.Drawing.Size(74, 20); + this.PathNodeLinkAreaIDUpDown.TabIndex = 10; + this.PathNodeLinkAreaIDUpDown.ValueChanged += new System.EventHandler(this.PathNodeLinkAreaIDUpDown_ValueChanged); + // + // label54 + // + this.label54.AutoSize = true; + this.label54.Location = new System.Drawing.Point(22, 10); + this.label54.Name = "label54"; + this.label54.Size = new System.Drawing.Size(46, 13); + this.label54.TabIndex = 9; + this.label54.Text = "Area ID:"; + // + // PathNodeJunctionTabPage + // + this.PathNodeJunctionTabPage.Controls.Add(this.label78); + this.PathNodeJunctionTabPage.Controls.Add(this.PathNodeJunctionPanel); + this.PathNodeJunctionTabPage.Controls.Add(this.PathNodeJunctionEnableCheckBox); + this.PathNodeJunctionTabPage.Location = new System.Drawing.Point(4, 22); + this.PathNodeJunctionTabPage.Name = "PathNodeJunctionTabPage"; + this.PathNodeJunctionTabPage.Padding = new System.Windows.Forms.Padding(3); + this.PathNodeJunctionTabPage.Size = new System.Drawing.Size(499, 414); + this.PathNodeJunctionTabPage.TabIndex = 1; + this.PathNodeJunctionTabPage.Text = "Junction"; + this.PathNodeJunctionTabPage.UseVisualStyleBackColor = true; + // + // label78 + // + this.label78.AutoSize = true; + this.label78.Location = new System.Drawing.Point(182, 7); + this.label78.Name = "label78"; + this.label78.Size = new System.Drawing.Size(113, 13); + this.label78.TabIndex = 51; + this.label78.Text = "Height map byte array:"; + // + // PathNodeJunctionPanel + // + this.PathNodeJunctionPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.PathNodeJunctionPanel.Controls.Add(this.PathNodeJunctionPosYUpDown); + this.PathNodeJunctionPanel.Controls.Add(this.label59); + this.PathNodeJunctionPanel.Controls.Add(this.PathNodeJunctionPosXUpDown); + this.PathNodeJunctionPanel.Controls.Add(this.label69); + this.PathNodeJunctionPanel.Controls.Add(this.PathNodeJunctionHeightmapBytesTextBox); + this.PathNodeJunctionPanel.Controls.Add(this.PathNodeJunctionHeightmapDimYUpDown); + this.PathNodeJunctionPanel.Controls.Add(this.label77); + this.PathNodeJunctionPanel.Controls.Add(this.PathNodeJunctionHeightmapDimXUpDown); + this.PathNodeJunctionPanel.Controls.Add(this.label76); + this.PathNodeJunctionPanel.Controls.Add(this.PathNodeJunctionMinZUpDown); + this.PathNodeJunctionPanel.Controls.Add(this.label67); + this.PathNodeJunctionPanel.Controls.Add(this.PathNodeJunctionMaxZUpDown); + this.PathNodeJunctionPanel.Controls.Add(this.label65); + this.PathNodeJunctionPanel.Enabled = false; + this.PathNodeJunctionPanel.Location = new System.Drawing.Point(6, 29); + this.PathNodeJunctionPanel.Name = "PathNodeJunctionPanel"; + this.PathNodeJunctionPanel.Size = new System.Drawing.Size(490, 379); + this.PathNodeJunctionPanel.TabIndex = 1; + // + // PathNodeJunctionPosYUpDown + // + this.PathNodeJunctionPosYUpDown.Location = new System.Drawing.Point(57, 81); + this.PathNodeJunctionPosYUpDown.Maximum = new decimal(new int[] { + 32767, + 0, + 0, + 0}); + this.PathNodeJunctionPosYUpDown.Minimum = new decimal(new int[] { + 32768, + 0, + 0, + -2147483648}); + this.PathNodeJunctionPosYUpDown.Name = "PathNodeJunctionPosYUpDown"; + this.PathNodeJunctionPosYUpDown.Size = new System.Drawing.Size(86, 20); + this.PathNodeJunctionPosYUpDown.TabIndex = 53; + this.PathNodeJunctionPosYUpDown.ValueChanged += new System.EventHandler(this.PathNodeJunctionPosYUpDown_ValueChanged); + // + // label59 + // + this.label59.AutoSize = true; + this.label59.Location = new System.Drawing.Point(13, 83); + this.label59.Name = "label59"; + this.label59.Size = new System.Drawing.Size(38, 13); + this.label59.TabIndex = 54; + this.label59.Text = "Pos Y:"; + // + // PathNodeJunctionPosXUpDown + // + this.PathNodeJunctionPosXUpDown.Location = new System.Drawing.Point(57, 55); + this.PathNodeJunctionPosXUpDown.Maximum = new decimal(new int[] { + 32767, + 0, + 0, + 0}); + this.PathNodeJunctionPosXUpDown.Minimum = new decimal(new int[] { + 32768, + 0, + 0, + -2147483648}); + this.PathNodeJunctionPosXUpDown.Name = "PathNodeJunctionPosXUpDown"; + this.PathNodeJunctionPosXUpDown.Size = new System.Drawing.Size(86, 20); + this.PathNodeJunctionPosXUpDown.TabIndex = 51; + this.PathNodeJunctionPosXUpDown.ValueChanged += new System.EventHandler(this.PathNodeJunctionPosXUpDown_ValueChanged); + // + // label69 + // + this.label69.AutoSize = true; + this.label69.Location = new System.Drawing.Point(13, 57); + this.label69.Name = "label69"; + this.label69.Size = new System.Drawing.Size(38, 13); + this.label69.TabIndex = 52; + this.label69.Text = "Pos X:"; + // + // PathNodeJunctionHeightmapBytesTextBox + // + this.PathNodeJunctionHeightmapBytesTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.PathNodeJunctionHeightmapBytesTextBox.Location = new System.Drawing.Point(159, 3); + this.PathNodeJunctionHeightmapBytesTextBox.Multiline = true; + this.PathNodeJunctionHeightmapBytesTextBox.Name = "PathNodeJunctionHeightmapBytesTextBox"; + this.PathNodeJunctionHeightmapBytesTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.PathNodeJunctionHeightmapBytesTextBox.Size = new System.Drawing.Size(328, 373); + this.PathNodeJunctionHeightmapBytesTextBox.TabIndex = 50; + this.PathNodeJunctionHeightmapBytesTextBox.WordWrap = false; + this.PathNodeJunctionHeightmapBytesTextBox.TextChanged += new System.EventHandler(this.PathNodeJunctionHeightmapBytesTextBox_TextChanged); + // + // PathNodeJunctionHeightmapDimYUpDown + // + this.PathNodeJunctionHeightmapDimYUpDown.Location = new System.Drawing.Point(57, 133); + this.PathNodeJunctionHeightmapDimYUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeJunctionHeightmapDimYUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.PathNodeJunctionHeightmapDimYUpDown.Name = "PathNodeJunctionHeightmapDimYUpDown"; + this.PathNodeJunctionHeightmapDimYUpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeJunctionHeightmapDimYUpDown.TabIndex = 49; + this.PathNodeJunctionHeightmapDimYUpDown.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.PathNodeJunctionHeightmapDimYUpDown.ValueChanged += new System.EventHandler(this.PathNodeJunctionHeightmapDimYUpDown_ValueChanged); + // + // label77 + // + this.label77.AutoSize = true; + this.label77.Location = new System.Drawing.Point(11, 135); + this.label77.Name = "label77"; + this.label77.Size = new System.Drawing.Size(40, 13); + this.label77.TabIndex = 48; + this.label77.Text = "Size Y:"; + // + // PathNodeJunctionHeightmapDimXUpDown + // + this.PathNodeJunctionHeightmapDimXUpDown.Location = new System.Drawing.Point(57, 107); + this.PathNodeJunctionHeightmapDimXUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.PathNodeJunctionHeightmapDimXUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.PathNodeJunctionHeightmapDimXUpDown.Name = "PathNodeJunctionHeightmapDimXUpDown"; + this.PathNodeJunctionHeightmapDimXUpDown.Size = new System.Drawing.Size(62, 20); + this.PathNodeJunctionHeightmapDimXUpDown.TabIndex = 47; + this.PathNodeJunctionHeightmapDimXUpDown.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.PathNodeJunctionHeightmapDimXUpDown.ValueChanged += new System.EventHandler(this.PathNodeJunctionHeightmapDimXUpDown_ValueChanged); + // + // label76 + // + this.label76.AutoSize = true; + this.label76.Location = new System.Drawing.Point(11, 109); + this.label76.Name = "label76"; + this.label76.Size = new System.Drawing.Size(40, 13); + this.label76.TabIndex = 46; + this.label76.Text = "Size X:"; + // + // PathNodeJunctionMinZUpDown + // + this.PathNodeJunctionMinZUpDown.Location = new System.Drawing.Point(57, 29); + this.PathNodeJunctionMinZUpDown.Maximum = new decimal(new int[] { + 32767, + 0, + 0, + 0}); + this.PathNodeJunctionMinZUpDown.Minimum = new decimal(new int[] { + 32768, + 0, + 0, + -2147483648}); + this.PathNodeJunctionMinZUpDown.Name = "PathNodeJunctionMinZUpDown"; + this.PathNodeJunctionMinZUpDown.Size = new System.Drawing.Size(86, 20); + this.PathNodeJunctionMinZUpDown.TabIndex = 32; + this.PathNodeJunctionMinZUpDown.ValueChanged += new System.EventHandler(this.PathNodeJunctionMinZUpDown_ValueChanged); + // + // label67 + // + this.label67.AutoSize = true; + this.label67.Location = new System.Drawing.Point(14, 32); + this.label67.Name = "label67"; + this.label67.Size = new System.Drawing.Size(37, 13); + this.label67.TabIndex = 33; + this.label67.Text = "Min Z:"; + // + // PathNodeJunctionMaxZUpDown + // + this.PathNodeJunctionMaxZUpDown.Location = new System.Drawing.Point(57, 3); + this.PathNodeJunctionMaxZUpDown.Maximum = new decimal(new int[] { + 32767, + 0, + 0, + 0}); + this.PathNodeJunctionMaxZUpDown.Minimum = new decimal(new int[] { + 32768, + 0, + 0, + -2147483648}); + this.PathNodeJunctionMaxZUpDown.Name = "PathNodeJunctionMaxZUpDown"; + this.PathNodeJunctionMaxZUpDown.Size = new System.Drawing.Size(86, 20); + this.PathNodeJunctionMaxZUpDown.TabIndex = 30; + this.PathNodeJunctionMaxZUpDown.ValueChanged += new System.EventHandler(this.PathNodeJunctionMaxZUpDown_ValueChanged); + // + // label65 + // + this.label65.AutoSize = true; + this.label65.Location = new System.Drawing.Point(11, 5); + this.label65.Name = "label65"; + this.label65.Size = new System.Drawing.Size(40, 13); + this.label65.TabIndex = 31; + this.label65.Text = "Max Z:"; + // + // PathNodeJunctionEnableCheckBox + // + this.PathNodeJunctionEnableCheckBox.AutoSize = true; + this.PathNodeJunctionEnableCheckBox.Location = new System.Drawing.Point(6, 6); + this.PathNodeJunctionEnableCheckBox.Name = "PathNodeJunctionEnableCheckBox"; + this.PathNodeJunctionEnableCheckBox.Size = new System.Drawing.Size(156, 17); + this.PathNodeJunctionEnableCheckBox.TabIndex = 0; + this.PathNodeJunctionEnableCheckBox.Text = "Enable Junction Heightmap"; + this.PathNodeJunctionEnableCheckBox.UseVisualStyleBackColor = true; + this.PathNodeJunctionEnableCheckBox.CheckedChanged += new System.EventHandler(this.PathNodeJunctionEnableCheckBox_CheckedChanged); + // + // YnvTabPage + // + this.YnvTabPage.Controls.Add(this.YnvTabControl); + this.YnvTabPage.Location = new System.Drawing.Point(4, 22); + this.YnvTabPage.Name = "YnvTabPage"; + this.YnvTabPage.Size = new System.Drawing.Size(521, 472); + this.YnvTabPage.TabIndex = 4; + this.YnvTabPage.Text = "Nav Mesh"; + this.YnvTabPage.UseVisualStyleBackColor = true; + // + // YnvTabControl + // + this.YnvTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YnvTabControl.Controls.Add(this.YnvYnvTabPage); + this.YnvTabControl.Controls.Add(this.YnvPolyTabPage); + this.YnvTabControl.Controls.Add(this.YnvPortalTabPage); + this.YnvTabControl.Location = new System.Drawing.Point(0, 3); + this.YnvTabControl.Name = "YnvTabControl"; + this.YnvTabControl.SelectedIndex = 0; + this.YnvTabControl.Size = new System.Drawing.Size(518, 469); + this.YnvTabControl.TabIndex = 0; + // + // YnvYnvTabPage + // + this.YnvYnvTabPage.Controls.Add(this.YnvPanel); + this.YnvYnvTabPage.Location = new System.Drawing.Point(4, 22); + this.YnvYnvTabPage.Name = "YnvYnvTabPage"; + this.YnvYnvTabPage.Padding = new System.Windows.Forms.Padding(3); + this.YnvYnvTabPage.Size = new System.Drawing.Size(510, 443); + this.YnvYnvTabPage.TabIndex = 0; + this.YnvYnvTabPage.Text = "Ynv"; + this.YnvYnvTabPage.UseVisualStyleBackColor = true; + // + // YnvPanel + // + this.YnvPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YnvPanel.Controls.Add(this.YnvAABBSizeTextBox); + this.YnvPanel.Controls.Add(this.label91); + this.YnvPanel.Controls.Add(this.label89); + this.YnvPanel.Controls.Add(this.YnvAreaIDYUpDown); + this.YnvPanel.Controls.Add(this.label90); + this.YnvPanel.Controls.Add(this.YnvAreaIDXUpDown); + this.YnvPanel.Controls.Add(this.YnvAreaIDInfoLabel); + this.YnvPanel.Controls.Add(this.label92); + this.YnvPanel.Enabled = false; + this.YnvPanel.Location = new System.Drawing.Point(0, 0); + this.YnvPanel.Name = "YnvPanel"; + this.YnvPanel.Size = new System.Drawing.Size(510, 443); + this.YnvPanel.TabIndex = 0; + // + // YnvAABBSizeTextBox + // + this.YnvAABBSizeTextBox.Location = new System.Drawing.Point(107, 45); + this.YnvAABBSizeTextBox.Name = "YnvAABBSizeTextBox"; + this.YnvAABBSizeTextBox.Size = new System.Drawing.Size(138, 20); + this.YnvAABBSizeTextBox.TabIndex = 29; + // + // label91 + // + this.label91.AutoSize = true; + this.label91.Location = new System.Drawing.Point(40, 48); + this.label91.Name = "label91"; + this.label91.Size = new System.Drawing.Size(61, 13); + this.label91.TabIndex = 30; + this.label91.Text = "AABB Size:"; + // + // label89 + // + this.label89.AutoSize = true; + this.label89.Location = new System.Drawing.Point(166, 11); + this.label89.Name = "label89"; + this.label89.Size = new System.Drawing.Size(17, 13); + this.label89.TabIndex = 25; + this.label89.Text = "Y:"; + // + // YnvAreaIDYUpDown + // + this.YnvAreaIDYUpDown.Location = new System.Drawing.Point(189, 9); + this.YnvAreaIDYUpDown.Maximum = new decimal(new int[] { + 31, + 0, + 0, + 0}); + this.YnvAreaIDYUpDown.Name = "YnvAreaIDYUpDown"; + this.YnvAreaIDYUpDown.Size = new System.Drawing.Size(48, 20); + this.YnvAreaIDYUpDown.TabIndex = 24; + // + // label90 + // + this.label90.AutoSize = true; + this.label90.Location = new System.Drawing.Point(84, 11); + this.label90.Name = "label90"; + this.label90.Size = new System.Drawing.Size(17, 13); + this.label90.TabIndex = 23; + this.label90.Text = "X:"; + // + // YnvAreaIDXUpDown + // + this.YnvAreaIDXUpDown.Location = new System.Drawing.Point(107, 9); + this.YnvAreaIDXUpDown.Maximum = new decimal(new int[] { + 31, + 0, + 0, + 0}); + this.YnvAreaIDXUpDown.Name = "YnvAreaIDXUpDown"; + this.YnvAreaIDXUpDown.Size = new System.Drawing.Size(48, 20); + this.YnvAreaIDXUpDown.TabIndex = 22; + // + // YnvAreaIDInfoLabel + // + this.YnvAreaIDInfoLabel.AutoSize = true; + this.YnvAreaIDInfoLabel.Location = new System.Drawing.Point(254, 11); + this.YnvAreaIDInfoLabel.Name = "YnvAreaIDInfoLabel"; + this.YnvAreaIDInfoLabel.Size = new System.Drawing.Size(30, 13); + this.YnvAreaIDInfoLabel.TabIndex = 21; + this.YnvAreaIDInfoLabel.Text = "ID: 0"; + // + // label92 + // + this.label92.AutoSize = true; + this.label92.Location = new System.Drawing.Point(28, 11); + this.label92.Name = "label92"; + this.label92.Size = new System.Drawing.Size(46, 13); + this.label92.TabIndex = 20; + this.label92.Text = "Area ID:"; + // + // YnvPolyTabPage + // + this.YnvPolyTabPage.Controls.Add(this.YnvPolygonPanel); + this.YnvPolyTabPage.Location = new System.Drawing.Point(4, 22); + this.YnvPolyTabPage.Name = "YnvPolyTabPage"; + this.YnvPolyTabPage.Padding = new System.Windows.Forms.Padding(3); + this.YnvPolyTabPage.Size = new System.Drawing.Size(510, 443); + this.YnvPolyTabPage.TabIndex = 1; + this.YnvPolyTabPage.Text = "Polygon"; + this.YnvPolyTabPage.UseVisualStyleBackColor = true; + // + // YnvPolygonPanel + // + this.YnvPolygonPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YnvPolygonPanel.Enabled = false; + this.YnvPolygonPanel.Location = new System.Drawing.Point(0, 0); + this.YnvPolygonPanel.Name = "YnvPolygonPanel"; + this.YnvPolygonPanel.Size = new System.Drawing.Size(510, 443); + this.YnvPolygonPanel.TabIndex = 1; + // + // YnvPortalTabPage + // + this.YnvPortalTabPage.Controls.Add(this.YnvPortalPanel); + this.YnvPortalTabPage.Location = new System.Drawing.Point(4, 22); + this.YnvPortalTabPage.Name = "YnvPortalTabPage"; + this.YnvPortalTabPage.Size = new System.Drawing.Size(510, 443); + this.YnvPortalTabPage.TabIndex = 2; + this.YnvPortalTabPage.Text = "Portal"; + this.YnvPortalTabPage.UseVisualStyleBackColor = true; + // + // YnvPortalPanel + // + this.YnvPortalPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YnvPortalPanel.Enabled = false; + this.YnvPortalPanel.Location = new System.Drawing.Point(0, 0); + this.YnvPortalPanel.Name = "YnvPortalPanel"; + this.YnvPortalPanel.Size = new System.Drawing.Size(510, 443); + this.YnvPortalPanel.TabIndex = 1; + // + // TrainsTabPage + // + this.TrainsTabPage.Controls.Add(this.TrainsTabControl); + this.TrainsTabPage.Location = new System.Drawing.Point(4, 22); + this.TrainsTabPage.Name = "TrainsTabPage"; + this.TrainsTabPage.Size = new System.Drawing.Size(521, 472); + this.TrainsTabPage.TabIndex = 3; + this.TrainsTabPage.Text = "Trains"; + this.TrainsTabPage.UseVisualStyleBackColor = true; + // + // TrainsTabControl + // + this.TrainsTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainsTabControl.Controls.Add(this.TrainTrackTabPage); + this.TrainsTabControl.Controls.Add(this.TrainNodeTabPage); + this.TrainsTabControl.Location = new System.Drawing.Point(0, 3); + this.TrainsTabControl.Name = "TrainsTabControl"; + this.TrainsTabControl.SelectedIndex = 0; + this.TrainsTabControl.Size = new System.Drawing.Size(518, 469); + this.TrainsTabControl.TabIndex = 0; + // + // TrainTrackTabPage + // + this.TrainTrackTabPage.Controls.Add(this.TrainTrackFilePanel); + this.TrainTrackTabPage.Location = new System.Drawing.Point(4, 22); + this.TrainTrackTabPage.Name = "TrainTrackTabPage"; + this.TrainTrackTabPage.Padding = new System.Windows.Forms.Padding(3); + this.TrainTrackTabPage.Size = new System.Drawing.Size(510, 443); + this.TrainTrackTabPage.TabIndex = 0; + this.TrainTrackTabPage.Text = "Track File"; + this.TrainTrackTabPage.UseVisualStyleBackColor = true; + // + // TrainTrackFilePanel + // + this.TrainTrackFilePanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackInfoLabel); + this.TrainTrackFilePanel.Controls.Add(this.label86); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackBrakingDistTextBox); + this.TrainTrackFilePanel.Controls.Add(this.label85); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackSpeedTextBox); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackMPStopsAtStationsCheckBox); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackStopsAtStationsCheckBox); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackIsPingPongCheckBox); + this.TrainTrackFilePanel.Controls.Add(this.label84); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackConfigNameTextBox); + this.TrainTrackFilePanel.Controls.Add(this.label83); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackFilenameTextBox); + this.TrainTrackFilePanel.Controls.Add(this.label74); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackProjectPathTextBox); + this.TrainTrackFilePanel.Controls.Add(this.label79); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackFilePathTextBox); + this.TrainTrackFilePanel.Controls.Add(this.label80); + this.TrainTrackFilePanel.Controls.Add(this.TrainTrackRpfPathTextBox); + this.TrainTrackFilePanel.Enabled = false; + this.TrainTrackFilePanel.Location = new System.Drawing.Point(0, 0); + this.TrainTrackFilePanel.Name = "TrainTrackFilePanel"; + this.TrainTrackFilePanel.Size = new System.Drawing.Size(510, 443); + this.TrainTrackFilePanel.TabIndex = 1; + // + // TrainTrackInfoLabel + // + this.TrainTrackInfoLabel.AutoSize = true; + this.TrainTrackInfoLabel.Location = new System.Drawing.Point(97, 133); + this.TrainTrackInfoLabel.Name = "TrainTrackInfoLabel"; + this.TrainTrackInfoLabel.Size = new System.Drawing.Size(10, 13); + this.TrainTrackInfoLabel.TabIndex = 36; + this.TrainTrackInfoLabel.Text = "-"; + // + // label86 + // + this.label86.AutoSize = true; + this.label86.Location = new System.Drawing.Point(282, 84); + this.label86.Name = "label86"; + this.label86.Size = new System.Drawing.Size(63, 13); + this.label86.TabIndex = 32; + this.label86.Text = "brakingDist:"; + // + // TrainTrackBrakingDistTextBox + // + this.TrainTrackBrakingDistTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainTrackBrakingDistTextBox.Location = new System.Drawing.Point(351, 81); + this.TrainTrackBrakingDistTextBox.Name = "TrainTrackBrakingDistTextBox"; + this.TrainTrackBrakingDistTextBox.ReadOnly = true; + this.TrainTrackBrakingDistTextBox.Size = new System.Drawing.Size(107, 20); + this.TrainTrackBrakingDistTextBox.TabIndex = 31; + // + // label85 + // + this.label85.AutoSize = true; + this.label85.Location = new System.Drawing.Point(55, 84); + this.label85.Name = "label85"; + this.label85.Size = new System.Drawing.Size(39, 13); + this.label85.TabIndex = 30; + this.label85.Text = "speed:"; + // + // TrainTrackSpeedTextBox + // + this.TrainTrackSpeedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainTrackSpeedTextBox.Location = new System.Drawing.Point(100, 81); + this.TrainTrackSpeedTextBox.Name = "TrainTrackSpeedTextBox"; + this.TrainTrackSpeedTextBox.ReadOnly = true; + this.TrainTrackSpeedTextBox.Size = new System.Drawing.Size(107, 20); + this.TrainTrackSpeedTextBox.TabIndex = 29; + // + // TrainTrackMPStopsAtStationsCheckBox + // + this.TrainTrackMPStopsAtStationsCheckBox.AutoSize = true; + this.TrainTrackMPStopsAtStationsCheckBox.Enabled = false; + this.TrainTrackMPStopsAtStationsCheckBox.Location = new System.Drawing.Point(351, 58); + this.TrainTrackMPStopsAtStationsCheckBox.Name = "TrainTrackMPStopsAtStationsCheckBox"; + this.TrainTrackMPStopsAtStationsCheckBox.Size = new System.Drawing.Size(115, 17); + this.TrainTrackMPStopsAtStationsCheckBox.TabIndex = 28; + this.TrainTrackMPStopsAtStationsCheckBox.Text = "MPstopsAtStations"; + this.TrainTrackMPStopsAtStationsCheckBox.UseVisualStyleBackColor = true; + // + // TrainTrackStopsAtStationsCheckBox + // + this.TrainTrackStopsAtStationsCheckBox.AutoSize = true; + this.TrainTrackStopsAtStationsCheckBox.Enabled = false; + this.TrainTrackStopsAtStationsCheckBox.Location = new System.Drawing.Point(225, 58); + this.TrainTrackStopsAtStationsCheckBox.Name = "TrainTrackStopsAtStationsCheckBox"; + this.TrainTrackStopsAtStationsCheckBox.Size = new System.Drawing.Size(99, 17); + this.TrainTrackStopsAtStationsCheckBox.TabIndex = 27; + this.TrainTrackStopsAtStationsCheckBox.Text = "stopsAtStations"; + this.TrainTrackStopsAtStationsCheckBox.UseVisualStyleBackColor = true; + // + // TrainTrackIsPingPongCheckBox + // + this.TrainTrackIsPingPongCheckBox.AutoSize = true; + this.TrainTrackIsPingPongCheckBox.Enabled = false; + this.TrainTrackIsPingPongCheckBox.Location = new System.Drawing.Point(100, 58); + this.TrainTrackIsPingPongCheckBox.Name = "TrainTrackIsPingPongCheckBox"; + this.TrainTrackIsPingPongCheckBox.Size = new System.Drawing.Size(107, 17); + this.TrainTrackIsPingPongCheckBox.TabIndex = 26; + this.TrainTrackIsPingPongCheckBox.Text = "isPingPongTrack"; + this.TrainTrackIsPingPongCheckBox.UseVisualStyleBackColor = true; + // + // label84 + // + this.label84.AutoSize = true; + this.label84.Location = new System.Drawing.Point(6, 35); + this.label84.Name = "label84"; + this.label84.Size = new System.Drawing.Size(88, 13); + this.label84.TabIndex = 25; + this.label84.Text = "trainConfigName:"; + // + // TrainTrackConfigNameTextBox + // + this.TrainTrackConfigNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainTrackConfigNameTextBox.Location = new System.Drawing.Point(100, 32); + this.TrainTrackConfigNameTextBox.Name = "TrainTrackConfigNameTextBox"; + this.TrainTrackConfigNameTextBox.ReadOnly = true; + this.TrainTrackConfigNameTextBox.Size = new System.Drawing.Size(366, 20); + this.TrainTrackConfigNameTextBox.TabIndex = 24; + // + // label83 + // + this.label83.AutoSize = true; + this.label83.Location = new System.Drawing.Point(45, 9); + this.label83.Name = "label83"; + this.label83.Size = new System.Drawing.Size(49, 13); + this.label83.TabIndex = 23; + this.label83.Text = "filename:"; + // + // TrainTrackFilenameTextBox + // + this.TrainTrackFilenameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainTrackFilenameTextBox.Location = new System.Drawing.Point(100, 6); + this.TrainTrackFilenameTextBox.Name = "TrainTrackFilenameTextBox"; + this.TrainTrackFilenameTextBox.ReadOnly = true; + this.TrainTrackFilenameTextBox.Size = new System.Drawing.Size(366, 20); + this.TrainTrackFilenameTextBox.TabIndex = 22; + // + // label74 + // + this.label74.AutoSize = true; + this.label74.Location = new System.Drawing.Point(6, 254); + this.label74.Name = "label74"; + this.label74.Size = new System.Drawing.Size(68, 13); + this.label74.TabIndex = 21; + this.label74.Text = "Project Path:"; + // + // TrainTrackProjectPathTextBox + // + this.TrainTrackProjectPathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainTrackProjectPathTextBox.Location = new System.Drawing.Point(80, 251); + this.TrainTrackProjectPathTextBox.Name = "TrainTrackProjectPathTextBox"; + this.TrainTrackProjectPathTextBox.ReadOnly = true; + this.TrainTrackProjectPathTextBox.Size = new System.Drawing.Size(386, 20); + this.TrainTrackProjectPathTextBox.TabIndex = 35; + // + // label79 + // + this.label79.AutoSize = true; + this.label79.Location = new System.Drawing.Point(6, 228); + this.label79.Name = "label79"; + this.label79.Size = new System.Drawing.Size(51, 13); + this.label79.TabIndex = 19; + this.label79.Text = "File Path:"; + // + // TrainTrackFilePathTextBox + // + this.TrainTrackFilePathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainTrackFilePathTextBox.Location = new System.Drawing.Point(80, 225); + this.TrainTrackFilePathTextBox.Name = "TrainTrackFilePathTextBox"; + this.TrainTrackFilePathTextBox.ReadOnly = true; + this.TrainTrackFilePathTextBox.Size = new System.Drawing.Size(386, 20); + this.TrainTrackFilePathTextBox.TabIndex = 34; + // + // label80 + // + this.label80.AutoSize = true; + this.label80.Location = new System.Drawing.Point(6, 202); + this.label80.Name = "label80"; + this.label80.Size = new System.Drawing.Size(52, 13); + this.label80.TabIndex = 17; + this.label80.Text = "Rpf Path:"; + // + // TrainTrackRpfPathTextBox + // + this.TrainTrackRpfPathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainTrackRpfPathTextBox.Location = new System.Drawing.Point(80, 199); + this.TrainTrackRpfPathTextBox.Name = "TrainTrackRpfPathTextBox"; + this.TrainTrackRpfPathTextBox.ReadOnly = true; + this.TrainTrackRpfPathTextBox.Size = new System.Drawing.Size(386, 20); + this.TrainTrackRpfPathTextBox.TabIndex = 33; + // + // TrainNodeTabPage + // + this.TrainNodeTabPage.Controls.Add(this.TrainNodePanel); + this.TrainNodeTabPage.Location = new System.Drawing.Point(4, 22); + this.TrainNodeTabPage.Name = "TrainNodeTabPage"; + this.TrainNodeTabPage.Padding = new System.Windows.Forms.Padding(3); + this.TrainNodeTabPage.Size = new System.Drawing.Size(510, 443); + this.TrainNodeTabPage.TabIndex = 1; + this.TrainNodeTabPage.Text = "Node"; + this.TrainNodeTabPage.UseVisualStyleBackColor = true; + // + // TrainNodePanel + // + this.TrainNodePanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TrainNodePanel.Controls.Add(this.TrainNodeTypeComboBox); + this.TrainNodePanel.Controls.Add(this.label82); + this.TrainNodePanel.Controls.Add(this.TrainNodeDeleteButton); + this.TrainNodePanel.Controls.Add(this.TrainNodeAddToProjectButton); + this.TrainNodePanel.Controls.Add(this.TrainNodeGoToButton); + this.TrainNodePanel.Controls.Add(this.TrainNodePositionTextBox); + this.TrainNodePanel.Controls.Add(this.label81); + this.TrainNodePanel.Enabled = false; + this.TrainNodePanel.Location = new System.Drawing.Point(0, 0); + this.TrainNodePanel.Name = "TrainNodePanel"; + this.TrainNodePanel.Size = new System.Drawing.Size(510, 443); + this.TrainNodePanel.TabIndex = 0; + // + // TrainNodeTypeComboBox + // + this.TrainNodeTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.TrainNodeTypeComboBox.FormattingEnabled = true; + this.TrainNodeTypeComboBox.Items.AddRange(new object[] { + "0 - Default", + "1 - Default Station", + "2 - Freight Station", + "3 - (Not used)", + "4 - Underground", + "5 - Underground Station"}); + this.TrainNodeTypeComboBox.Location = new System.Drawing.Point(75, 62); + this.TrainNodeTypeComboBox.Name = "TrainNodeTypeComboBox"; + this.TrainNodeTypeComboBox.Size = new System.Drawing.Size(142, 21); + this.TrainNodeTypeComboBox.TabIndex = 40; + this.TrainNodeTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.TrainNodeTypeComboBox_SelectedIndexChanged); + // + // label82 + // + this.label82.AutoSize = true; + this.label82.Location = new System.Drawing.Point(22, 65); + this.label82.Name = "label82"; + this.label82.Size = new System.Drawing.Size(34, 13); + this.label82.TabIndex = 39; + this.label82.Text = "Type:"; + // + // TrainNodeDeleteButton + // + this.TrainNodeDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.TrainNodeDeleteButton.Enabled = false; + this.TrainNodeDeleteButton.Location = new System.Drawing.Point(401, 99); + this.TrainNodeDeleteButton.Name = "TrainNodeDeleteButton"; + this.TrainNodeDeleteButton.Size = new System.Drawing.Size(90, 23); + this.TrainNodeDeleteButton.TabIndex = 42; + this.TrainNodeDeleteButton.Text = "Delete Node"; + this.TrainNodeDeleteButton.UseVisualStyleBackColor = true; + this.TrainNodeDeleteButton.Click += new System.EventHandler(this.TrainNodeDeleteButton_Click); + // + // TrainNodeAddToProjectButton + // + this.TrainNodeAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.TrainNodeAddToProjectButton.Enabled = false; + this.TrainNodeAddToProjectButton.Location = new System.Drawing.Point(305, 99); + this.TrainNodeAddToProjectButton.Name = "TrainNodeAddToProjectButton"; + this.TrainNodeAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.TrainNodeAddToProjectButton.TabIndex = 41; + this.TrainNodeAddToProjectButton.Text = "Add to Project"; + this.TrainNodeAddToProjectButton.UseVisualStyleBackColor = true; + this.TrainNodeAddToProjectButton.Click += new System.EventHandler(this.TrainNodeAddToProjectButton_Click); + // + // TrainNodeGoToButton + // + this.TrainNodeGoToButton.Location = new System.Drawing.Point(305, 27); + this.TrainNodeGoToButton.Name = "TrainNodeGoToButton"; + this.TrainNodeGoToButton.Size = new System.Drawing.Size(68, 23); + this.TrainNodeGoToButton.TabIndex = 35; + this.TrainNodeGoToButton.Text = "Go to"; + this.TrainNodeGoToButton.UseVisualStyleBackColor = true; + this.TrainNodeGoToButton.Click += new System.EventHandler(this.TrainNodeGoToButton_Click); + // + // TrainNodePositionTextBox + // + this.TrainNodePositionTextBox.Location = new System.Drawing.Point(75, 29); + this.TrainNodePositionTextBox.Name = "TrainNodePositionTextBox"; + this.TrainNodePositionTextBox.Size = new System.Drawing.Size(224, 20); + this.TrainNodePositionTextBox.TabIndex = 34; + this.TrainNodePositionTextBox.TextChanged += new System.EventHandler(this.TrainNodePositionTextBox_TextChanged); + // + // label81 + // + this.label81.AutoSize = true; + this.label81.Location = new System.Drawing.Point(22, 32); + this.label81.Name = "label81"; + this.label81.Size = new System.Drawing.Size(47, 13); + this.label81.TabIndex = 38; + this.label81.Text = "Position:"; + // + // ScenarioTabPage + // + this.ScenarioTabPage.Controls.Add(this.ScenarioTabControl); + this.ScenarioTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioTabPage.Name = "ScenarioTabPage"; + this.ScenarioTabPage.Size = new System.Drawing.Size(521, 472); + this.ScenarioTabPage.TabIndex = 5; + this.ScenarioTabPage.Text = "Scenario"; + this.ScenarioTabPage.UseVisualStyleBackColor = true; + // + // ScenarioTabControl + // + this.ScenarioTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioTabControl.Controls.Add(this.ScenarioYmtTabPage); + this.ScenarioTabControl.Controls.Add(this.ScenarioPointTabPage); + this.ScenarioTabControl.Controls.Add(this.ScenarioEntityTabPage); + this.ScenarioTabControl.Controls.Add(this.ScenarioEntityPointTabPage); + this.ScenarioTabControl.Controls.Add(this.ScenarioChainTabPage); + this.ScenarioTabControl.Controls.Add(this.ScenarioChainNodeTabPage); + this.ScenarioTabControl.Controls.Add(this.ScenarioClusterTabPage); + this.ScenarioTabControl.Controls.Add(this.ScenarioClusterPointTabPage); + this.ScenarioTabControl.Location = new System.Drawing.Point(0, 3); + this.ScenarioTabControl.Name = "ScenarioTabControl"; + this.ScenarioTabControl.SelectedIndex = 0; + this.ScenarioTabControl.Size = new System.Drawing.Size(518, 469); + this.ScenarioTabControl.TabIndex = 0; + // + // ScenarioYmtTabPage + // + this.ScenarioYmtTabPage.Controls.Add(this.ScenarioYmtPanel); + this.ScenarioYmtTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioYmtTabPage.Name = "ScenarioYmtTabPage"; + this.ScenarioYmtTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ScenarioYmtTabPage.Size = new System.Drawing.Size(510, 443); + this.ScenarioYmtTabPage.TabIndex = 0; + this.ScenarioYmtTabPage.Text = "Ymt"; + this.ScenarioYmtTabPage.UseVisualStyleBackColor = true; + // + // ScenarioYmtPanel + // + this.ScenarioYmtPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtExtentsMaxTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label103); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtExtentsMinTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label150); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtGridInfoLabel); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtGridScaleTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label96); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtProjectPathTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label66); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtFileLocationTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label72); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtGridMaxTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label73); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtGridMinTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label75); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtVersionTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label64); + this.ScenarioYmtPanel.Controls.Add(this.ScenarioYmtNameTextBox); + this.ScenarioYmtPanel.Controls.Add(this.label63); + this.ScenarioYmtPanel.Enabled = false; + this.ScenarioYmtPanel.Location = new System.Drawing.Point(0, 0); + this.ScenarioYmtPanel.Name = "ScenarioYmtPanel"; + this.ScenarioYmtPanel.Size = new System.Drawing.Size(510, 443); + this.ScenarioYmtPanel.TabIndex = 0; + // + // ScenarioYmtExtentsMaxTextBox + // + this.ScenarioYmtExtentsMaxTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtExtentsMaxTextBox.Location = new System.Drawing.Point(94, 256); + this.ScenarioYmtExtentsMaxTextBox.Name = "ScenarioYmtExtentsMaxTextBox"; + this.ScenarioYmtExtentsMaxTextBox.ReadOnly = true; + this.ScenarioYmtExtentsMaxTextBox.Size = new System.Drawing.Size(277, 20); + this.ScenarioYmtExtentsMaxTextBox.TabIndex = 15; + // + // label103 + // + this.label103.AutoSize = true; + this.label103.Location = new System.Drawing.Point(6, 259); + this.label103.Name = "label103"; + this.label103.Size = new System.Drawing.Size(68, 13); + this.label103.TabIndex = 14; + this.label103.Text = "Extents Max:"; + // + // ScenarioYmtExtentsMinTextBox + // + this.ScenarioYmtExtentsMinTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtExtentsMinTextBox.Location = new System.Drawing.Point(94, 230); + this.ScenarioYmtExtentsMinTextBox.Name = "ScenarioYmtExtentsMinTextBox"; + this.ScenarioYmtExtentsMinTextBox.ReadOnly = true; + this.ScenarioYmtExtentsMinTextBox.Size = new System.Drawing.Size(277, 20); + this.ScenarioYmtExtentsMinTextBox.TabIndex = 13; + // + // label150 + // + this.label150.AutoSize = true; + this.label150.Location = new System.Drawing.Point(6, 233); + this.label150.Name = "label150"; + this.label150.Size = new System.Drawing.Size(65, 13); + this.label150.TabIndex = 12; + this.label150.Text = "Extents Min:"; + // + // ScenarioYmtGridInfoLabel + // + this.ScenarioYmtGridInfoLabel.AutoSize = true; + this.ScenarioYmtGridInfoLabel.Location = new System.Drawing.Point(91, 169); + this.ScenarioYmtGridInfoLabel.Name = "ScenarioYmtGridInfoLabel"; + this.ScenarioYmtGridInfoLabel.Size = new System.Drawing.Size(94, 13); + this.ScenarioYmtGridInfoLabel.TabIndex = 11; + this.ScenarioYmtGridInfoLabel.Text = "Total grid points: 0"; + // + // ScenarioYmtGridScaleTextBox + // + this.ScenarioYmtGridScaleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtGridScaleTextBox.Location = new System.Drawing.Point(94, 131); + this.ScenarioYmtGridScaleTextBox.Name = "ScenarioYmtGridScaleTextBox"; + this.ScenarioYmtGridScaleTextBox.ReadOnly = true; + this.ScenarioYmtGridScaleTextBox.Size = new System.Drawing.Size(277, 20); + this.ScenarioYmtGridScaleTextBox.TabIndex = 10; + // + // label96 + // + this.label96.AutoSize = true; + this.label96.Location = new System.Drawing.Point(6, 134); + this.label96.Name = "label96"; + this.label96.Size = new System.Drawing.Size(59, 13); + this.label96.TabIndex = 9; + this.label96.Text = "Grid Scale:"; + // + // ScenarioYmtProjectPathTextBox + // + this.ScenarioYmtProjectPathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtProjectPathTextBox.Location = new System.Drawing.Point(94, 379); + this.ScenarioYmtProjectPathTextBox.Name = "ScenarioYmtProjectPathTextBox"; + this.ScenarioYmtProjectPathTextBox.ReadOnly = true; + this.ScenarioYmtProjectPathTextBox.Size = new System.Drawing.Size(404, 20); + this.ScenarioYmtProjectPathTextBox.TabIndex = 19; + // + // label66 + // + this.label66.AutoSize = true; + this.label66.Location = new System.Drawing.Point(6, 382); + this.label66.Name = "label66"; + this.label66.Size = new System.Drawing.Size(67, 13); + this.label66.TabIndex = 18; + this.label66.Text = "Project path:"; + // + // ScenarioYmtFileLocationTextBox + // + this.ScenarioYmtFileLocationTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtFileLocationTextBox.Location = new System.Drawing.Point(94, 353); + this.ScenarioYmtFileLocationTextBox.Name = "ScenarioYmtFileLocationTextBox"; + this.ScenarioYmtFileLocationTextBox.ReadOnly = true; + this.ScenarioYmtFileLocationTextBox.Size = new System.Drawing.Size(404, 20); + this.ScenarioYmtFileLocationTextBox.TabIndex = 17; + // + // label72 + // + this.label72.AutoSize = true; + this.label72.Location = new System.Drawing.Point(6, 356); + this.label72.Name = "label72"; + this.label72.Size = new System.Drawing.Size(66, 13); + this.label72.TabIndex = 16; + this.label72.Text = "File location:"; + // + // ScenarioYmtGridMaxTextBox + // + this.ScenarioYmtGridMaxTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtGridMaxTextBox.Location = new System.Drawing.Point(94, 105); + this.ScenarioYmtGridMaxTextBox.Name = "ScenarioYmtGridMaxTextBox"; + this.ScenarioYmtGridMaxTextBox.ReadOnly = true; + this.ScenarioYmtGridMaxTextBox.Size = new System.Drawing.Size(277, 20); + this.ScenarioYmtGridMaxTextBox.TabIndex = 8; + // + // label73 + // + this.label73.AutoSize = true; + this.label73.Location = new System.Drawing.Point(6, 108); + this.label73.Name = "label73"; + this.label73.Size = new System.Drawing.Size(52, 13); + this.label73.TabIndex = 7; + this.label73.Text = "Grid Max:"; + // + // ScenarioYmtGridMinTextBox + // + this.ScenarioYmtGridMinTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtGridMinTextBox.Location = new System.Drawing.Point(94, 79); + this.ScenarioYmtGridMinTextBox.Name = "ScenarioYmtGridMinTextBox"; + this.ScenarioYmtGridMinTextBox.ReadOnly = true; + this.ScenarioYmtGridMinTextBox.Size = new System.Drawing.Size(277, 20); + this.ScenarioYmtGridMinTextBox.TabIndex = 6; + // + // label75 + // + this.label75.AutoSize = true; + this.label75.Location = new System.Drawing.Point(6, 82); + this.label75.Name = "label75"; + this.label75.Size = new System.Drawing.Size(49, 13); + this.label75.TabIndex = 5; + this.label75.Text = "Grid Min:"; + // + // ScenarioYmtVersionTextBox + // + this.ScenarioYmtVersionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtVersionTextBox.Location = new System.Drawing.Point(94, 36); + this.ScenarioYmtVersionTextBox.Name = "ScenarioYmtVersionTextBox"; + this.ScenarioYmtVersionTextBox.Size = new System.Drawing.Size(277, 20); + this.ScenarioYmtVersionTextBox.TabIndex = 4; + this.ScenarioYmtVersionTextBox.TextChanged += new System.EventHandler(this.ScenarioYmtVersionTextBox_TextChanged); + // + // label64 + // + this.label64.AutoSize = true; + this.label64.Location = new System.Drawing.Point(6, 39); + this.label64.Name = "label64"; + this.label64.Size = new System.Drawing.Size(82, 13); + this.label64.TabIndex = 3; + this.label64.Text = "VersionNumber:"; + // + // ScenarioYmtNameTextBox + // + this.ScenarioYmtNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioYmtNameTextBox.Location = new System.Drawing.Point(94, 10); + this.ScenarioYmtNameTextBox.Name = "ScenarioYmtNameTextBox"; + this.ScenarioYmtNameTextBox.ReadOnly = true; + this.ScenarioYmtNameTextBox.Size = new System.Drawing.Size(277, 20); + this.ScenarioYmtNameTextBox.TabIndex = 2; + // + // label63 + // + this.label63.AutoSize = true; + this.label63.Location = new System.Drawing.Point(6, 13); + this.label63.Name = "label63"; + this.label63.Size = new System.Drawing.Size(38, 13); + this.label63.TabIndex = 1; + this.label63.Text = "Name:"; + // + // ScenarioPointTabPage + // + this.ScenarioPointTabPage.Controls.Add(this.ScenarioPointOuterPanel); + this.ScenarioPointTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioPointTabPage.Name = "ScenarioPointTabPage"; + this.ScenarioPointTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ScenarioPointTabPage.Size = new System.Drawing.Size(510, 443); + this.ScenarioPointTabPage.TabIndex = 1; + this.ScenarioPointTabPage.Text = "Point"; + this.ScenarioPointTabPage.UseVisualStyleBackColor = true; + // + // ScenarioPointOuterPanel + // + this.ScenarioPointOuterPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointOuterPanel.Controls.Add(this.ScenarioPointCheckBox); + this.ScenarioPointOuterPanel.Controls.Add(this.ScenarioPointPanel); + this.ScenarioPointOuterPanel.Controls.Add(this.ScenarioPointDeleteButton); + this.ScenarioPointOuterPanel.Controls.Add(this.ScenarioPointAddToProjectButton); + this.ScenarioPointOuterPanel.Location = new System.Drawing.Point(0, 0); + this.ScenarioPointOuterPanel.Name = "ScenarioPointOuterPanel"; + this.ScenarioPointOuterPanel.Size = new System.Drawing.Size(510, 443); + this.ScenarioPointOuterPanel.TabIndex = 1; + // + // ScenarioPointCheckBox + // + this.ScenarioPointCheckBox.AutoSize = true; + this.ScenarioPointCheckBox.Location = new System.Drawing.Point(6, 6); + this.ScenarioPointCheckBox.Name = "ScenarioPointCheckBox"; + this.ScenarioPointCheckBox.Size = new System.Drawing.Size(98, 17); + this.ScenarioPointCheckBox.TabIndex = 1; + this.ScenarioPointCheckBox.Text = "Define MyPoint"; + this.ScenarioPointCheckBox.UseVisualStyleBackColor = true; + this.ScenarioPointCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioPointCheckBox_CheckedChanged); + // + // ScenarioPointPanel + // + this.ScenarioPointPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointImapHashLabel); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointImapTextBox); + this.ScenarioPointPanel.Controls.Add(this.label110); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointGroupHashLabel); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointGroupTextBox); + this.ScenarioPointPanel.Controls.Add(this.label156); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointInteriorHashLabel); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointFlagsCheckedListBox); + this.ScenarioPointPanel.Controls.Add(this.label111); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointDirectionTextBox); + this.ScenarioPointPanel.Controls.Add(this.label97); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointFlagsValueUpDown); + this.ScenarioPointPanel.Controls.Add(this.label109); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointGoToButton); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointWaitTimeUpDown); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointPositionTextBox); + this.ScenarioPointPanel.Controls.Add(this.label62); + this.ScenarioPointPanel.Controls.Add(this.label108); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointRadiusUpDown); + this.ScenarioPointPanel.Controls.Add(this.label107); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointSpOnlyFlagUpDown); + this.ScenarioPointPanel.Controls.Add(this.label106); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointProbabilityUpDown); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointInteriorTextBox); + this.ScenarioPointPanel.Controls.Add(this.label102); + this.ScenarioPointPanel.Controls.Add(this.label101); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointTimeEndUpDown); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointTimeStartUpDown); + this.ScenarioPointPanel.Controls.Add(this.label100); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointModelSetComboBox); + this.ScenarioPointPanel.Controls.Add(this.label99); + this.ScenarioPointPanel.Controls.Add(this.ScenarioPointTypeComboBox); + this.ScenarioPointPanel.Controls.Add(this.label98); + this.ScenarioPointPanel.Enabled = false; + this.ScenarioPointPanel.Location = new System.Drawing.Point(0, 29); + this.ScenarioPointPanel.Name = "ScenarioPointPanel"; + this.ScenarioPointPanel.Size = new System.Drawing.Size(510, 414); + this.ScenarioPointPanel.TabIndex = 0; + // + // ScenarioPointImapHashLabel + // + this.ScenarioPointImapHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointImapHashLabel.AutoSize = true; + this.ScenarioPointImapHashLabel.Location = new System.Drawing.Point(341, 146); + this.ScenarioPointImapHashLabel.Name = "ScenarioPointImapHashLabel"; + this.ScenarioPointImapHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioPointImapHashLabel.TabIndex = 21; + this.ScenarioPointImapHashLabel.Text = "Hash: 0"; + // + // ScenarioPointImapTextBox + // + this.ScenarioPointImapTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointImapTextBox.Location = new System.Drawing.Point(73, 143); + this.ScenarioPointImapTextBox.Name = "ScenarioPointImapTextBox"; + this.ScenarioPointImapTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioPointImapTextBox.TabIndex = 20; + this.ScenarioPointImapTextBox.TextChanged += new System.EventHandler(this.ScenarioPointImapTextBox_TextChanged); + // + // label110 + // + this.label110.AutoSize = true; + this.label110.Location = new System.Drawing.Point(34, 146); + this.label110.Name = "label110"; + this.label110.Size = new System.Drawing.Size(33, 13); + this.label110.TabIndex = 19; + this.label110.Text = "Imap:"; + // + // ScenarioPointGroupHashLabel + // + this.ScenarioPointGroupHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointGroupHashLabel.AutoSize = true; + this.ScenarioPointGroupHashLabel.Location = new System.Drawing.Point(341, 123); + this.ScenarioPointGroupHashLabel.Name = "ScenarioPointGroupHashLabel"; + this.ScenarioPointGroupHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioPointGroupHashLabel.TabIndex = 18; + this.ScenarioPointGroupHashLabel.Text = "Hash: 0"; + // + // ScenarioPointGroupTextBox + // + this.ScenarioPointGroupTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointGroupTextBox.Location = new System.Drawing.Point(73, 120); + this.ScenarioPointGroupTextBox.Name = "ScenarioPointGroupTextBox"; + this.ScenarioPointGroupTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioPointGroupTextBox.TabIndex = 17; + this.ScenarioPointGroupTextBox.TextChanged += new System.EventHandler(this.ScenarioPointGroupTextBox_TextChanged); + // + // label156 + // + this.label156.AutoSize = true; + this.label156.Location = new System.Drawing.Point(28, 123); + this.label156.Name = "label156"; + this.label156.Size = new System.Drawing.Size(39, 13); + this.label156.TabIndex = 16; + this.label156.Text = "Group:"; + // + // ScenarioPointInteriorHashLabel + // + this.ScenarioPointInteriorHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointInteriorHashLabel.AutoSize = true; + this.ScenarioPointInteriorHashLabel.Location = new System.Drawing.Point(341, 100); + this.ScenarioPointInteriorHashLabel.Name = "ScenarioPointInteriorHashLabel"; + this.ScenarioPointInteriorHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioPointInteriorHashLabel.TabIndex = 15; + this.ScenarioPointInteriorHashLabel.Text = "Hash: 0"; + // + // ScenarioPointFlagsCheckedListBox + // + this.ScenarioPointFlagsCheckedListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointFlagsCheckedListBox.CheckOnClick = true; + this.ScenarioPointFlagsCheckedListBox.FormattingEnabled = true; + this.ScenarioPointFlagsCheckedListBox.Items.AddRange(new object[] { + "1 - IgnoreMaxInRange", + "2 - NoSpawn", + "4 - StationaryReactions", + "8 - Unk", + "16 - Unk", + "32 - ActivateVehicleSiren", + "64 - Unk", + "128 - Unk", + "256 - Unk", + "512 - Unk", + "1024 - AerialVehiclePoint", + "2048 - TerritorialScenario", + "4096 - Unk", + "8192 - Unk", + "16384 - Unk", + "32768 - Unk", + "65536 - InWater", + "131072 - Unk", + "262144 - OpenDoor", + "524288 - PreciseUseTime", + "1048576 - Unk", + "2097152 - Unk", + "4194304 - ExtendedRange", + "8388608 - ShortRange", + "16777216 - HighPriority", + "33554432 - IgnoreLoitering", + "67108864 - Unk", + "134217728 - ResetNoCollisionOnCleanUp", + "268435456 - Unk", + "536870912 - Unk", + "1073741824 - Unk"}); + this.ScenarioPointFlagsCheckedListBox.Location = new System.Drawing.Point(195, 167); + this.ScenarioPointFlagsCheckedListBox.Name = "ScenarioPointFlagsCheckedListBox"; + this.ScenarioPointFlagsCheckedListBox.Size = new System.Drawing.Size(214, 244); + this.ScenarioPointFlagsCheckedListBox.TabIndex = 36; + this.ScenarioPointFlagsCheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.ScenarioPointFlagsCheckedListBox_ItemCheck); + // + // label111 + // + this.label111.AutoSize = true; + this.label111.Location = new System.Drawing.Point(32, 390); + this.label111.Name = "label111"; + this.label111.Size = new System.Drawing.Size(35, 13); + this.label111.TabIndex = 34; + this.label111.Text = "Flags:"; + // + // ScenarioPointDirectionTextBox + // + this.ScenarioPointDirectionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointDirectionTextBox.Location = new System.Drawing.Point(73, 26); + this.ScenarioPointDirectionTextBox.Name = "ScenarioPointDirectionTextBox"; + this.ScenarioPointDirectionTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioPointDirectionTextBox.TabIndex = 8; + this.ScenarioPointDirectionTextBox.TextChanged += new System.EventHandler(this.ScenarioPointDirectionTextBox_TextChanged); + // + // label97 + // + this.label97.AutoSize = true; + this.label97.Location = new System.Drawing.Point(15, 29); + this.label97.Name = "label97"; + this.label97.Size = new System.Drawing.Size(52, 13); + this.label97.TabIndex = 7; + this.label97.Text = "Direction:"; + // + // ScenarioPointFlagsValueUpDown + // + this.ScenarioPointFlagsValueUpDown.Location = new System.Drawing.Point(73, 388); + this.ScenarioPointFlagsValueUpDown.Maximum = new decimal(new int[] { + -1, + 0, + 0, + 0}); + this.ScenarioPointFlagsValueUpDown.Name = "ScenarioPointFlagsValueUpDown"; + this.ScenarioPointFlagsValueUpDown.Size = new System.Drawing.Size(116, 20); + this.ScenarioPointFlagsValueUpDown.TabIndex = 35; + this.ScenarioPointFlagsValueUpDown.ValueChanged += new System.EventHandler(this.ScenarioPointFlagsValueUpDown_ValueChanged); + // + // label109 + // + this.label109.AutoSize = true; + this.label109.Location = new System.Drawing.Point(13, 299); + this.label109.Name = "label109"; + this.label109.Size = new System.Drawing.Size(54, 13); + this.label109.TabIndex = 32; + this.label109.Text = "Wait time:"; + // + // ScenarioPointGoToButton + // + this.ScenarioPointGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointGoToButton.Location = new System.Drawing.Point(341, 1); + this.ScenarioPointGoToButton.Name = "ScenarioPointGoToButton"; + this.ScenarioPointGoToButton.Size = new System.Drawing.Size(68, 23); + this.ScenarioPointGoToButton.TabIndex = 6; + this.ScenarioPointGoToButton.Text = "Go to"; + this.ScenarioPointGoToButton.UseVisualStyleBackColor = true; + this.ScenarioPointGoToButton.Click += new System.EventHandler(this.ScenarioPointGoToButton_Click); + // + // ScenarioPointWaitTimeUpDown + // + this.ScenarioPointWaitTimeUpDown.Location = new System.Drawing.Point(73, 297); + this.ScenarioPointWaitTimeUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioPointWaitTimeUpDown.Name = "ScenarioPointWaitTimeUpDown"; + this.ScenarioPointWaitTimeUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioPointWaitTimeUpDown.TabIndex = 33; + this.ScenarioPointWaitTimeUpDown.ValueChanged += new System.EventHandler(this.ScenarioPointWaitTimeUpDown_ValueChanged); + // + // ScenarioPointPositionTextBox + // + this.ScenarioPointPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointPositionTextBox.Location = new System.Drawing.Point(73, 3); + this.ScenarioPointPositionTextBox.Name = "ScenarioPointPositionTextBox"; + this.ScenarioPointPositionTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioPointPositionTextBox.TabIndex = 5; + this.ScenarioPointPositionTextBox.TextChanged += new System.EventHandler(this.ScenarioPointPositionTextBox_TextChanged); + // + // label62 + // + this.label62.AutoSize = true; + this.label62.Location = new System.Drawing.Point(20, 6); + this.label62.Name = "label62"; + this.label62.Size = new System.Drawing.Size(47, 13); + this.label62.TabIndex = 4; + this.label62.Text = "Position:"; + // + // label108 + // + this.label108.AutoSize = true; + this.label108.Location = new System.Drawing.Point(24, 273); + this.label108.Name = "label108"; + this.label108.Size = new System.Drawing.Size(43, 13); + this.label108.TabIndex = 30; + this.label108.Text = "Radius:"; + // + // ScenarioPointRadiusUpDown + // + this.ScenarioPointRadiusUpDown.Location = new System.Drawing.Point(73, 271); + this.ScenarioPointRadiusUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioPointRadiusUpDown.Name = "ScenarioPointRadiusUpDown"; + this.ScenarioPointRadiusUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioPointRadiusUpDown.TabIndex = 31; + this.ScenarioPointRadiusUpDown.ValueChanged += new System.EventHandler(this.ScenarioPointRadiusUpDown_ValueChanged); + // + // label107 + // + this.label107.AutoSize = true; + this.label107.Location = new System.Drawing.Point(3, 247); + this.label107.Name = "label107"; + this.label107.Size = new System.Drawing.Size(64, 13); + this.label107.TabIndex = 28; + this.label107.Text = "SpOnly flag:"; + // + // ScenarioPointSpOnlyFlagUpDown + // + this.ScenarioPointSpOnlyFlagUpDown.Location = new System.Drawing.Point(73, 245); + this.ScenarioPointSpOnlyFlagUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioPointSpOnlyFlagUpDown.Name = "ScenarioPointSpOnlyFlagUpDown"; + this.ScenarioPointSpOnlyFlagUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioPointSpOnlyFlagUpDown.TabIndex = 29; + this.ScenarioPointSpOnlyFlagUpDown.ValueChanged += new System.EventHandler(this.ScenarioPointSpOnlyFlagUpDown_ValueChanged); + // + // label106 + // + this.label106.AutoSize = true; + this.label106.Location = new System.Drawing.Point(9, 221); + this.label106.Name = "label106"; + this.label106.Size = new System.Drawing.Size(58, 13); + this.label106.TabIndex = 26; + this.label106.Text = "Probability:"; + // + // ScenarioPointProbabilityUpDown + // + this.ScenarioPointProbabilityUpDown.Location = new System.Drawing.Point(73, 219); + this.ScenarioPointProbabilityUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioPointProbabilityUpDown.Name = "ScenarioPointProbabilityUpDown"; + this.ScenarioPointProbabilityUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioPointProbabilityUpDown.TabIndex = 27; + this.ScenarioPointProbabilityUpDown.ValueChanged += new System.EventHandler(this.ScenarioPointProbabilityUpDown_ValueChanged); + // + // ScenarioPointInteriorTextBox + // + this.ScenarioPointInteriorTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointInteriorTextBox.Location = new System.Drawing.Point(73, 97); + this.ScenarioPointInteriorTextBox.Name = "ScenarioPointInteriorTextBox"; + this.ScenarioPointInteriorTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioPointInteriorTextBox.TabIndex = 14; + this.ScenarioPointInteriorTextBox.TextChanged += new System.EventHandler(this.ScenarioPointInteriorTextBox_TextChanged); + // + // label102 + // + this.label102.AutoSize = true; + this.label102.Location = new System.Drawing.Point(25, 100); + this.label102.Name = "label102"; + this.label102.Size = new System.Drawing.Size(42, 13); + this.label102.TabIndex = 13; + this.label102.Text = "Interior:"; + // + // label101 + // + this.label101.AutoSize = true; + this.label101.Location = new System.Drawing.Point(13, 195); + this.label101.Name = "label101"; + this.label101.Size = new System.Drawing.Size(54, 13); + this.label101.TabIndex = 24; + this.label101.Text = "Time end:"; + // + // ScenarioPointTimeEndUpDown + // + this.ScenarioPointTimeEndUpDown.Location = new System.Drawing.Point(73, 193); + this.ScenarioPointTimeEndUpDown.Maximum = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.ScenarioPointTimeEndUpDown.Name = "ScenarioPointTimeEndUpDown"; + this.ScenarioPointTimeEndUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioPointTimeEndUpDown.TabIndex = 25; + this.ScenarioPointTimeEndUpDown.ValueChanged += new System.EventHandler(this.ScenarioPointTimeEndUpDown_ValueChanged); + // + // ScenarioPointTimeStartUpDown + // + this.ScenarioPointTimeStartUpDown.Location = new System.Drawing.Point(73, 167); + this.ScenarioPointTimeStartUpDown.Maximum = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.ScenarioPointTimeStartUpDown.Name = "ScenarioPointTimeStartUpDown"; + this.ScenarioPointTimeStartUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioPointTimeStartUpDown.TabIndex = 23; + this.ScenarioPointTimeStartUpDown.ValueChanged += new System.EventHandler(this.ScenarioPointTimeStartUpDown_ValueChanged); + // + // label100 + // + this.label100.AutoSize = true; + this.label100.Location = new System.Drawing.Point(11, 169); + this.label100.Name = "label100"; + this.label100.Size = new System.Drawing.Size(56, 13); + this.label100.TabIndex = 22; + this.label100.Text = "Time start:"; + // + // ScenarioPointModelSetComboBox + // + this.ScenarioPointModelSetComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointModelSetComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioPointModelSetComboBox.FormattingEnabled = true; + this.ScenarioPointModelSetComboBox.Location = new System.Drawing.Point(73, 73); + this.ScenarioPointModelSetComboBox.Name = "ScenarioPointModelSetComboBox"; + this.ScenarioPointModelSetComboBox.Size = new System.Drawing.Size(336, 21); + this.ScenarioPointModelSetComboBox.TabIndex = 12; + this.ScenarioPointModelSetComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioPointModelSetComboBox_SelectedIndexChanged); + // + // label99 + // + this.label99.AutoSize = true; + this.label99.Location = new System.Drawing.Point(9, 76); + this.label99.Name = "label99"; + this.label99.Size = new System.Drawing.Size(58, 13); + this.label99.TabIndex = 11; + this.label99.Text = "Model Set:"; + // + // ScenarioPointTypeComboBox + // + this.ScenarioPointTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioPointTypeComboBox.FormattingEnabled = true; + this.ScenarioPointTypeComboBox.Location = new System.Drawing.Point(73, 49); + this.ScenarioPointTypeComboBox.Name = "ScenarioPointTypeComboBox"; + this.ScenarioPointTypeComboBox.Size = new System.Drawing.Size(336, 21); + this.ScenarioPointTypeComboBox.TabIndex = 10; + this.ScenarioPointTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioPointTypeComboBox_SelectedIndexChanged); + // + // label98 + // + this.label98.AutoSize = true; + this.label98.Location = new System.Drawing.Point(33, 52); + this.label98.Name = "label98"; + this.label98.Size = new System.Drawing.Size(34, 13); + this.label98.TabIndex = 9; + this.label98.Text = "Type:"; + // + // ScenarioPointDeleteButton + // + this.ScenarioPointDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointDeleteButton.Enabled = false; + this.ScenarioPointDeleteButton.Location = new System.Drawing.Point(415, 2); + this.ScenarioPointDeleteButton.Name = "ScenarioPointDeleteButton"; + this.ScenarioPointDeleteButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioPointDeleteButton.TabIndex = 3; + this.ScenarioPointDeleteButton.Text = "Delete Point"; + this.ScenarioPointDeleteButton.UseVisualStyleBackColor = true; + this.ScenarioPointDeleteButton.Click += new System.EventHandler(this.ScenarioPointDeleteButton_Click); + // + // ScenarioPointAddToProjectButton + // + this.ScenarioPointAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioPointAddToProjectButton.Enabled = false; + this.ScenarioPointAddToProjectButton.Location = new System.Drawing.Point(319, 2); + this.ScenarioPointAddToProjectButton.Name = "ScenarioPointAddToProjectButton"; + this.ScenarioPointAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioPointAddToProjectButton.TabIndex = 2; + this.ScenarioPointAddToProjectButton.Text = "Add to Project"; + this.ScenarioPointAddToProjectButton.UseVisualStyleBackColor = true; + this.ScenarioPointAddToProjectButton.Click += new System.EventHandler(this.ScenarioPointAddToProjectButton_Click); + // + // ScenarioEntityTabPage + // + this.ScenarioEntityTabPage.Controls.Add(this.ScenarioEntityDeleteButton); + this.ScenarioEntityTabPage.Controls.Add(this.ScenarioEntityPanel); + this.ScenarioEntityTabPage.Controls.Add(this.ScenarioEntityAddToProjectButton); + this.ScenarioEntityTabPage.Controls.Add(this.ScenarioEntityCheckBox); + this.ScenarioEntityTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioEntityTabPage.Name = "ScenarioEntityTabPage"; + this.ScenarioEntityTabPage.Size = new System.Drawing.Size(510, 443); + this.ScenarioEntityTabPage.TabIndex = 7; + this.ScenarioEntityTabPage.Text = "Entity"; + this.ScenarioEntityTabPage.UseVisualStyleBackColor = true; + // + // ScenarioEntityDeleteButton + // + this.ScenarioEntityDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityDeleteButton.Enabled = false; + this.ScenarioEntityDeleteButton.Location = new System.Drawing.Point(415, 2); + this.ScenarioEntityDeleteButton.Name = "ScenarioEntityDeleteButton"; + this.ScenarioEntityDeleteButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioEntityDeleteButton.TabIndex = 7; + this.ScenarioEntityDeleteButton.Text = "Delete Override"; + this.ScenarioEntityDeleteButton.UseVisualStyleBackColor = true; + this.ScenarioEntityDeleteButton.Click += new System.EventHandler(this.ScenarioEntityDeleteButton_Click); + // + // ScenarioEntityPanel + // + this.ScenarioEntityPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPanel.Controls.Add(this.label160); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityAddPointButton); + this.ScenarioEntityPanel.Controls.Add(this.label161); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityPointsListBox); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityInfoLabel); + this.ScenarioEntityPanel.Controls.Add(this.label114); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityUnk2UpDown); + this.ScenarioEntityPanel.Controls.Add(this.label113); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityUnk1UpDown); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityTypeHashLabel); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityTypeTextBox); + this.ScenarioEntityPanel.Controls.Add(this.label112); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityGoToButton); + this.ScenarioEntityPanel.Controls.Add(this.ScenarioEntityPositionTextBox); + this.ScenarioEntityPanel.Controls.Add(this.label104); + this.ScenarioEntityPanel.Enabled = false; + this.ScenarioEntityPanel.Location = new System.Drawing.Point(0, 29); + this.ScenarioEntityPanel.Name = "ScenarioEntityPanel"; + this.ScenarioEntityPanel.Size = new System.Drawing.Size(510, 414); + this.ScenarioEntityPanel.TabIndex = 8; + // + // ScenarioEntityInfoLabel + // + this.ScenarioEntityInfoLabel.AutoSize = true; + this.ScenarioEntityInfoLabel.Location = new System.Drawing.Point(88, 123); + this.ScenarioEntityInfoLabel.Name = "ScenarioEntityInfoLabel"; + this.ScenarioEntityInfoLabel.Size = new System.Drawing.Size(85, 13); + this.ScenarioEntityInfoLabel.TabIndex = 14; + this.ScenarioEntityInfoLabel.Text = "0 override points"; + // + // label114 + // + this.label114.AutoSize = true; + this.label114.Location = new System.Drawing.Point(46, 83); + this.label114.Name = "label114"; + this.label114.Size = new System.Drawing.Size(39, 13); + this.label114.TabIndex = 12; + this.label114.Text = "Unk 2:"; + // + // ScenarioEntityUnk2UpDown + // + this.ScenarioEntityUnk2UpDown.Location = new System.Drawing.Point(91, 81); + this.ScenarioEntityUnk2UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioEntityUnk2UpDown.Name = "ScenarioEntityUnk2UpDown"; + this.ScenarioEntityUnk2UpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioEntityUnk2UpDown.TabIndex = 13; + this.ScenarioEntityUnk2UpDown.ValueChanged += new System.EventHandler(this.ScenarioEntityUnk2UpDown_ValueChanged); + // + // label113 + // + this.label113.AutoSize = true; + this.label113.Location = new System.Drawing.Point(46, 57); + this.label113.Name = "label113"; + this.label113.Size = new System.Drawing.Size(39, 13); + this.label113.TabIndex = 10; + this.label113.Text = "Unk 1:"; + // + // ScenarioEntityUnk1UpDown + // + this.ScenarioEntityUnk1UpDown.Location = new System.Drawing.Point(91, 55); + this.ScenarioEntityUnk1UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioEntityUnk1UpDown.Name = "ScenarioEntityUnk1UpDown"; + this.ScenarioEntityUnk1UpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioEntityUnk1UpDown.TabIndex = 11; + this.ScenarioEntityUnk1UpDown.ValueChanged += new System.EventHandler(this.ScenarioEntityUnk1UpDown_ValueChanged); + // + // ScenarioEntityTypeHashLabel + // + this.ScenarioEntityTypeHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityTypeHashLabel.AutoSize = true; + this.ScenarioEntityTypeHashLabel.Location = new System.Drawing.Point(341, 32); + this.ScenarioEntityTypeHashLabel.Name = "ScenarioEntityTypeHashLabel"; + this.ScenarioEntityTypeHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioEntityTypeHashLabel.TabIndex = 9; + this.ScenarioEntityTypeHashLabel.Text = "Hash: 0"; + // + // ScenarioEntityTypeTextBox + // + this.ScenarioEntityTypeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityTypeTextBox.Location = new System.Drawing.Point(91, 29); + this.ScenarioEntityTypeTextBox.Name = "ScenarioEntityTypeTextBox"; + this.ScenarioEntityTypeTextBox.Size = new System.Drawing.Size(244, 20); + this.ScenarioEntityTypeTextBox.TabIndex = 8; + this.ScenarioEntityTypeTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityTypeTextBox_TextChanged); + // + // label112 + // + this.label112.AutoSize = true; + this.label112.Location = new System.Drawing.Point(26, 32); + this.label112.Name = "label112"; + this.label112.Size = new System.Drawing.Size(59, 13); + this.label112.TabIndex = 7; + this.label112.Text = "Entity type:"; + // + // ScenarioEntityGoToButton + // + this.ScenarioEntityGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityGoToButton.Location = new System.Drawing.Point(341, 1); + this.ScenarioEntityGoToButton.Name = "ScenarioEntityGoToButton"; + this.ScenarioEntityGoToButton.Size = new System.Drawing.Size(68, 23); + this.ScenarioEntityGoToButton.TabIndex = 6; + this.ScenarioEntityGoToButton.Text = "Go to"; + this.ScenarioEntityGoToButton.UseVisualStyleBackColor = true; + this.ScenarioEntityGoToButton.Click += new System.EventHandler(this.ScenarioEntityGoToButton_Click); + // + // ScenarioEntityPositionTextBox + // + this.ScenarioEntityPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPositionTextBox.Location = new System.Drawing.Point(91, 3); + this.ScenarioEntityPositionTextBox.Name = "ScenarioEntityPositionTextBox"; + this.ScenarioEntityPositionTextBox.Size = new System.Drawing.Size(244, 20); + this.ScenarioEntityPositionTextBox.TabIndex = 5; + this.ScenarioEntityPositionTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPositionTextBox_TextChanged); + // + // label104 + // + this.label104.AutoSize = true; + this.label104.Location = new System.Drawing.Point(10, 6); + this.label104.Name = "label104"; + this.label104.Size = new System.Drawing.Size(75, 13); + this.label104.TabIndex = 4; + this.label104.Text = "Entity position:"; + // + // ScenarioEntityAddToProjectButton + // + this.ScenarioEntityAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityAddToProjectButton.Enabled = false; + this.ScenarioEntityAddToProjectButton.Location = new System.Drawing.Point(319, 2); + this.ScenarioEntityAddToProjectButton.Name = "ScenarioEntityAddToProjectButton"; + this.ScenarioEntityAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioEntityAddToProjectButton.TabIndex = 6; + this.ScenarioEntityAddToProjectButton.Text = "Add to Project"; + this.ScenarioEntityAddToProjectButton.UseVisualStyleBackColor = true; + this.ScenarioEntityAddToProjectButton.Click += new System.EventHandler(this.ScenarioEntityAddToProjectButton_Click); + // + // ScenarioEntityCheckBox + // + this.ScenarioEntityCheckBox.AutoSize = true; + this.ScenarioEntityCheckBox.Location = new System.Drawing.Point(6, 6); + this.ScenarioEntityCheckBox.Name = "ScenarioEntityCheckBox"; + this.ScenarioEntityCheckBox.Size = new System.Drawing.Size(129, 17); + this.ScenarioEntityCheckBox.TabIndex = 5; + this.ScenarioEntityCheckBox.Text = "Define Entity Override"; + this.ScenarioEntityCheckBox.UseVisualStyleBackColor = true; + this.ScenarioEntityCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioEntityCheckBox_CheckedChanged); + // + // ScenarioEntityPointTabPage + // + this.ScenarioEntityPointTabPage.Controls.Add(this.ScenarioEntityPointDeleteButton); + this.ScenarioEntityPointTabPage.Controls.Add(this.ScenarioEntityPointAddToProjectButton); + this.ScenarioEntityPointTabPage.Controls.Add(this.ScenarioEntityPointCheckBox); + this.ScenarioEntityPointTabPage.Controls.Add(this.ScenarioEntityPointPanel); + this.ScenarioEntityPointTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioEntityPointTabPage.Name = "ScenarioEntityPointTabPage"; + this.ScenarioEntityPointTabPage.Size = new System.Drawing.Size(510, 443); + this.ScenarioEntityPointTabPage.TabIndex = 2; + this.ScenarioEntityPointTabPage.Text = "Entity Point"; + this.ScenarioEntityPointTabPage.UseVisualStyleBackColor = true; + // + // ScenarioEntityPointDeleteButton + // + this.ScenarioEntityPointDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointDeleteButton.Enabled = false; + this.ScenarioEntityPointDeleteButton.Location = new System.Drawing.Point(415, 2); + this.ScenarioEntityPointDeleteButton.Name = "ScenarioEntityPointDeleteButton"; + this.ScenarioEntityPointDeleteButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioEntityPointDeleteButton.TabIndex = 3; + this.ScenarioEntityPointDeleteButton.Text = "Delete Point"; + this.ScenarioEntityPointDeleteButton.UseVisualStyleBackColor = true; + this.ScenarioEntityPointDeleteButton.Click += new System.EventHandler(this.ScenarioEntityPointDeleteButton_Click); + // + // ScenarioEntityPointAddToProjectButton + // + this.ScenarioEntityPointAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointAddToProjectButton.Enabled = false; + this.ScenarioEntityPointAddToProjectButton.Location = new System.Drawing.Point(319, 2); + this.ScenarioEntityPointAddToProjectButton.Name = "ScenarioEntityPointAddToProjectButton"; + this.ScenarioEntityPointAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioEntityPointAddToProjectButton.TabIndex = 2; + this.ScenarioEntityPointAddToProjectButton.Text = "Add to Project"; + this.ScenarioEntityPointAddToProjectButton.UseVisualStyleBackColor = true; + this.ScenarioEntityPointAddToProjectButton.Click += new System.EventHandler(this.ScenarioEntityPointAddToProjectButton_Click); + // + // ScenarioEntityPointCheckBox + // + this.ScenarioEntityPointCheckBox.AutoSize = true; + this.ScenarioEntityPointCheckBox.Location = new System.Drawing.Point(6, 6); + this.ScenarioEntityPointCheckBox.Name = "ScenarioEntityPointCheckBox"; + this.ScenarioEntityPointCheckBox.Size = new System.Drawing.Size(156, 17); + this.ScenarioEntityPointCheckBox.TabIndex = 1; + this.ScenarioEntityPointCheckBox.Text = "Define Entity Override Point"; + this.ScenarioEntityPointCheckBox.UseVisualStyleBackColor = true; + this.ScenarioEntityPointCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioEntityPointCheckBox_CheckedChanged); + // + // ScenarioEntityPointPanel + // + this.ScenarioEntityPointPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointNameHashLabel); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointNameTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointFlagsCheckedListBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label135); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointFlagsUpDown); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointShortRangeCheckBox); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointExtendedRangeCheckBox); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointHighPriCheckBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label133); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointEndUpDown); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointStartUpDown); + this.ScenarioEntityPointPanel.Controls.Add(this.label134); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointRadiusTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label132); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointTimeTillPedLeavesTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label131); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointProbabilityTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label130); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointAvailableInMpSpComboBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label129); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointRequiredImapHashLabel); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointRequiredImapTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label128); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointInteriorHashLabel); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointInteriorTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label126); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointGroupHashLabel); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointGroupTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label124); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointPedTypeHashLabel); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointPedTypeTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label122); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointSpawnTypeHashLabel); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointSpawnTypeTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label120); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointRotationTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label118); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointGoToButton); + this.ScenarioEntityPointPanel.Controls.Add(this.ScenarioEntityPointPositionTextBox); + this.ScenarioEntityPointPanel.Controls.Add(this.label117); + this.ScenarioEntityPointPanel.Controls.Add(this.label116); + this.ScenarioEntityPointPanel.Enabled = false; + this.ScenarioEntityPointPanel.Location = new System.Drawing.Point(0, 29); + this.ScenarioEntityPointPanel.Name = "ScenarioEntityPointPanel"; + this.ScenarioEntityPointPanel.Size = new System.Drawing.Size(510, 414); + this.ScenarioEntityPointPanel.TabIndex = 4; + // + // ScenarioEntityPointNameHashLabel + // + this.ScenarioEntityPointNameHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointNameHashLabel.AutoSize = true; + this.ScenarioEntityPointNameHashLabel.Location = new System.Drawing.Point(387, 53); + this.ScenarioEntityPointNameHashLabel.Name = "ScenarioEntityPointNameHashLabel"; + this.ScenarioEntityPointNameHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioEntityPointNameHashLabel.TabIndex = 12; + this.ScenarioEntityPointNameHashLabel.Text = "Hash: 0"; + // + // ScenarioEntityPointNameTextBox + // + this.ScenarioEntityPointNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointNameTextBox.Location = new System.Drawing.Point(109, 50); + this.ScenarioEntityPointNameTextBox.Name = "ScenarioEntityPointNameTextBox"; + this.ScenarioEntityPointNameTextBox.Size = new System.Drawing.Size(272, 20); + this.ScenarioEntityPointNameTextBox.TabIndex = 11; + this.ScenarioEntityPointNameTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointNameTextBox_TextChanged); + // + // ScenarioEntityPointFlagsCheckedListBox + // + this.ScenarioEntityPointFlagsCheckedListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointFlagsCheckedListBox.CheckOnClick = true; + this.ScenarioEntityPointFlagsCheckedListBox.FormattingEnabled = true; + this.ScenarioEntityPointFlagsCheckedListBox.Items.AddRange(new object[] { + "1 - IgnoreMaxInRange", + "2 - NoSpawn", + "4 - StationaryReactions", + "8 - Unk", + "16 - Unk", + "32 - ActivateVehicleSiren", + "64 - Unk", + "128 - Unk", + "256 - Unk", + "512 - Unk", + "1024 - AerialVehiclePoint", + "2048 - TerritorialScenario", + "4096 - Unk", + "8192 - Unk", + "16384 - Unk", + "32768 - Unk", + "65536 - InWater", + "131072 - Unk", + "262144 - OpenDoor", + "524288 - PreciseUseTime", + "1048576 - Unk", + "2097152 - Unk", + "4194304 - ExtendedRange", + "8388608 - ShortRange", + "16777216 - HighPriority", + "33554432 - IgnoreLoitering", + "67108864 - Unk", + "134217728 - ResetNoCollisionOnCleanUp", + "268435456 - Unk", + "536870912 - Unk", + "1073741824 - Unk"}); + this.ScenarioEntityPointFlagsCheckedListBox.Location = new System.Drawing.Point(269, 193); + this.ScenarioEntityPointFlagsCheckedListBox.Name = "ScenarioEntityPointFlagsCheckedListBox"; + this.ScenarioEntityPointFlagsCheckedListBox.Size = new System.Drawing.Size(214, 214); + this.ScenarioEntityPointFlagsCheckedListBox.TabIndex = 45; + this.ScenarioEntityPointFlagsCheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.ScenarioEntityPointFlagsCheckedListBox_ItemCheck); + // + // label135 + // + this.label135.AutoSize = true; + this.label135.Location = new System.Drawing.Point(68, 389); + this.label135.Name = "label135"; + this.label135.Size = new System.Drawing.Size(35, 13); + this.label135.TabIndex = 43; + this.label135.Text = "Flags:"; + // + // ScenarioEntityPointFlagsUpDown + // + this.ScenarioEntityPointFlagsUpDown.Location = new System.Drawing.Point(109, 387); + this.ScenarioEntityPointFlagsUpDown.Maximum = new decimal(new int[] { + -1, + 0, + 0, + 0}); + this.ScenarioEntityPointFlagsUpDown.Name = "ScenarioEntityPointFlagsUpDown"; + this.ScenarioEntityPointFlagsUpDown.Size = new System.Drawing.Size(154, 20); + this.ScenarioEntityPointFlagsUpDown.TabIndex = 44; + this.ScenarioEntityPointFlagsUpDown.ValueChanged += new System.EventHandler(this.ScenarioEntityPointFlagsUpDown_ValueChanged); + // + // ScenarioEntityPointShortRangeCheckBox + // + this.ScenarioEntityPointShortRangeCheckBox.AutoSize = true; + this.ScenarioEntityPointShortRangeCheckBox.Location = new System.Drawing.Point(109, 364); + this.ScenarioEntityPointShortRangeCheckBox.Name = "ScenarioEntityPointShortRangeCheckBox"; + this.ScenarioEntityPointShortRangeCheckBox.Size = new System.Drawing.Size(83, 17); + this.ScenarioEntityPointShortRangeCheckBox.TabIndex = 42; + this.ScenarioEntityPointShortRangeCheckBox.Text = "ShortRange"; + this.ScenarioEntityPointShortRangeCheckBox.UseVisualStyleBackColor = true; + this.ScenarioEntityPointShortRangeCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioEntityPointShortRangeCheckBox_CheckedChanged); + // + // ScenarioEntityPointExtendedRangeCheckBox + // + this.ScenarioEntityPointExtendedRangeCheckBox.AutoSize = true; + this.ScenarioEntityPointExtendedRangeCheckBox.Location = new System.Drawing.Point(109, 346); + this.ScenarioEntityPointExtendedRangeCheckBox.Name = "ScenarioEntityPointExtendedRangeCheckBox"; + this.ScenarioEntityPointExtendedRangeCheckBox.Size = new System.Drawing.Size(103, 17); + this.ScenarioEntityPointExtendedRangeCheckBox.TabIndex = 41; + this.ScenarioEntityPointExtendedRangeCheckBox.Text = "ExtendedRange"; + this.ScenarioEntityPointExtendedRangeCheckBox.UseVisualStyleBackColor = true; + this.ScenarioEntityPointExtendedRangeCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioEntityPointExtendedRangeCheckBox_CheckedChanged); + // + // ScenarioEntityPointHighPriCheckBox + // + this.ScenarioEntityPointHighPriCheckBox.AutoSize = true; + this.ScenarioEntityPointHighPriCheckBox.Location = new System.Drawing.Point(109, 328); + this.ScenarioEntityPointHighPriCheckBox.Name = "ScenarioEntityPointHighPriCheckBox"; + this.ScenarioEntityPointHighPriCheckBox.Size = new System.Drawing.Size(60, 17); + this.ScenarioEntityPointHighPriCheckBox.TabIndex = 40; + this.ScenarioEntityPointHighPriCheckBox.Text = "HighPri"; + this.ScenarioEntityPointHighPriCheckBox.UseVisualStyleBackColor = true; + this.ScenarioEntityPointHighPriCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioEntityPointHighPriCheckBox_CheckedChanged); + // + // label133 + // + this.label133.AutoSize = true; + this.label133.Location = new System.Drawing.Point(74, 306); + this.label133.Name = "label133"; + this.label133.Size = new System.Drawing.Size(29, 13); + this.label133.TabIndex = 38; + this.label133.Text = "End:"; + // + // ScenarioEntityPointEndUpDown + // + this.ScenarioEntityPointEndUpDown.Location = new System.Drawing.Point(109, 304); + this.ScenarioEntityPointEndUpDown.Maximum = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.ScenarioEntityPointEndUpDown.Name = "ScenarioEntityPointEndUpDown"; + this.ScenarioEntityPointEndUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioEntityPointEndUpDown.TabIndex = 39; + this.ScenarioEntityPointEndUpDown.ValueChanged += new System.EventHandler(this.ScenarioEntityPointEndUpDown_ValueChanged); + // + // ScenarioEntityPointStartUpDown + // + this.ScenarioEntityPointStartUpDown.Location = new System.Drawing.Point(109, 281); + this.ScenarioEntityPointStartUpDown.Maximum = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.ScenarioEntityPointStartUpDown.Name = "ScenarioEntityPointStartUpDown"; + this.ScenarioEntityPointStartUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioEntityPointStartUpDown.TabIndex = 37; + this.ScenarioEntityPointStartUpDown.ValueChanged += new System.EventHandler(this.ScenarioEntityPointStartUpDown_ValueChanged); + // + // label134 + // + this.label134.AutoSize = true; + this.label134.Location = new System.Drawing.Point(71, 283); + this.label134.Name = "label134"; + this.label134.Size = new System.Drawing.Size(32, 13); + this.label134.TabIndex = 36; + this.label134.Text = "Start:"; + // + // ScenarioEntityPointRadiusTextBox + // + this.ScenarioEntityPointRadiusTextBox.Location = new System.Drawing.Point(109, 258); + this.ScenarioEntityPointRadiusTextBox.Name = "ScenarioEntityPointRadiusTextBox"; + this.ScenarioEntityPointRadiusTextBox.Size = new System.Drawing.Size(88, 20); + this.ScenarioEntityPointRadiusTextBox.TabIndex = 35; + this.ScenarioEntityPointRadiusTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointRadiusTextBox_TextChanged); + // + // label132 + // + this.label132.AutoSize = true; + this.label132.Location = new System.Drawing.Point(60, 261); + this.label132.Name = "label132"; + this.label132.Size = new System.Drawing.Size(43, 13); + this.label132.TabIndex = 34; + this.label132.Text = "Radius:"; + // + // ScenarioEntityPointTimeTillPedLeavesTextBox + // + this.ScenarioEntityPointTimeTillPedLeavesTextBox.Location = new System.Drawing.Point(109, 235); + this.ScenarioEntityPointTimeTillPedLeavesTextBox.Name = "ScenarioEntityPointTimeTillPedLeavesTextBox"; + this.ScenarioEntityPointTimeTillPedLeavesTextBox.Size = new System.Drawing.Size(88, 20); + this.ScenarioEntityPointTimeTillPedLeavesTextBox.TabIndex = 33; + this.ScenarioEntityPointTimeTillPedLeavesTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointTimeTillPedLeavesTextBox_TextChanged); + // + // label131 + // + this.label131.AutoSize = true; + this.label131.Location = new System.Drawing.Point(3, 238); + this.label131.Name = "label131"; + this.label131.Size = new System.Drawing.Size(100, 13); + this.label131.TabIndex = 32; + this.label131.Text = "TimeTillPedLeaves:"; + // + // ScenarioEntityPointProbabilityTextBox + // + this.ScenarioEntityPointProbabilityTextBox.Location = new System.Drawing.Point(109, 212); + this.ScenarioEntityPointProbabilityTextBox.Name = "ScenarioEntityPointProbabilityTextBox"; + this.ScenarioEntityPointProbabilityTextBox.Size = new System.Drawing.Size(88, 20); + this.ScenarioEntityPointProbabilityTextBox.TabIndex = 31; + this.ScenarioEntityPointProbabilityTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointProbabilityTextBox_TextChanged); + // + // label130 + // + this.label130.AutoSize = true; + this.label130.Location = new System.Drawing.Point(45, 215); + this.label130.Name = "label130"; + this.label130.Size = new System.Drawing.Size(58, 13); + this.label130.TabIndex = 30; + this.label130.Text = "Probability:"; + // + // ScenarioEntityPointAvailableInMpSpComboBox + // + this.ScenarioEntityPointAvailableInMpSpComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioEntityPointAvailableInMpSpComboBox.FormattingEnabled = true; + this.ScenarioEntityPointAvailableInMpSpComboBox.Location = new System.Drawing.Point(109, 188); + this.ScenarioEntityPointAvailableInMpSpComboBox.Name = "ScenarioEntityPointAvailableInMpSpComboBox"; + this.ScenarioEntityPointAvailableInMpSpComboBox.Size = new System.Drawing.Size(88, 21); + this.ScenarioEntityPointAvailableInMpSpComboBox.TabIndex = 29; + this.ScenarioEntityPointAvailableInMpSpComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioEntityPointAvailableInMpSpComboBox_SelectedIndexChanged); + // + // label129 + // + this.label129.AutoSize = true; + this.label129.Location = new System.Drawing.Point(14, 191); + this.label129.Name = "label129"; + this.label129.Size = new System.Drawing.Size(90, 13); + this.label129.TabIndex = 28; + this.label129.Text = "AvailableInMpSp:"; + // + // ScenarioEntityPointRequiredImapHashLabel + // + this.ScenarioEntityPointRequiredImapHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointRequiredImapHashLabel.AutoSize = true; + this.ScenarioEntityPointRequiredImapHashLabel.Location = new System.Drawing.Point(387, 168); + this.ScenarioEntityPointRequiredImapHashLabel.Name = "ScenarioEntityPointRequiredImapHashLabel"; + this.ScenarioEntityPointRequiredImapHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioEntityPointRequiredImapHashLabel.TabIndex = 27; + this.ScenarioEntityPointRequiredImapHashLabel.Text = "Hash: 0"; + // + // ScenarioEntityPointRequiredImapTextBox + // + this.ScenarioEntityPointRequiredImapTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointRequiredImapTextBox.Location = new System.Drawing.Point(109, 165); + this.ScenarioEntityPointRequiredImapTextBox.Name = "ScenarioEntityPointRequiredImapTextBox"; + this.ScenarioEntityPointRequiredImapTextBox.Size = new System.Drawing.Size(272, 20); + this.ScenarioEntityPointRequiredImapTextBox.TabIndex = 26; + this.ScenarioEntityPointRequiredImapTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointRequiredImapTextBox_TextChanged); + // + // label128 + // + this.label128.AutoSize = true; + this.label128.Location = new System.Drawing.Point(24, 168); + this.label128.Name = "label128"; + this.label128.Size = new System.Drawing.Size(79, 13); + this.label128.TabIndex = 25; + this.label128.Text = "Required Imap:"; + // + // ScenarioEntityPointInteriorHashLabel + // + this.ScenarioEntityPointInteriorHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointInteriorHashLabel.AutoSize = true; + this.ScenarioEntityPointInteriorHashLabel.Location = new System.Drawing.Point(387, 145); + this.ScenarioEntityPointInteriorHashLabel.Name = "ScenarioEntityPointInteriorHashLabel"; + this.ScenarioEntityPointInteriorHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioEntityPointInteriorHashLabel.TabIndex = 24; + this.ScenarioEntityPointInteriorHashLabel.Text = "Hash: 0"; + // + // ScenarioEntityPointInteriorTextBox + // + this.ScenarioEntityPointInteriorTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointInteriorTextBox.Location = new System.Drawing.Point(109, 142); + this.ScenarioEntityPointInteriorTextBox.Name = "ScenarioEntityPointInteriorTextBox"; + this.ScenarioEntityPointInteriorTextBox.Size = new System.Drawing.Size(272, 20); + this.ScenarioEntityPointInteriorTextBox.TabIndex = 23; + this.ScenarioEntityPointInteriorTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointInteriorTextBox_TextChanged); + // + // label126 + // + this.label126.AutoSize = true; + this.label126.Location = new System.Drawing.Point(61, 145); + this.label126.Name = "label126"; + this.label126.Size = new System.Drawing.Size(42, 13); + this.label126.TabIndex = 22; + this.label126.Text = "Interior:"; + // + // ScenarioEntityPointGroupHashLabel + // + this.ScenarioEntityPointGroupHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointGroupHashLabel.AutoSize = true; + this.ScenarioEntityPointGroupHashLabel.Location = new System.Drawing.Point(387, 122); + this.ScenarioEntityPointGroupHashLabel.Name = "ScenarioEntityPointGroupHashLabel"; + this.ScenarioEntityPointGroupHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioEntityPointGroupHashLabel.TabIndex = 21; + this.ScenarioEntityPointGroupHashLabel.Text = "Hash: 0"; + // + // ScenarioEntityPointGroupTextBox + // + this.ScenarioEntityPointGroupTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointGroupTextBox.Location = new System.Drawing.Point(109, 119); + this.ScenarioEntityPointGroupTextBox.Name = "ScenarioEntityPointGroupTextBox"; + this.ScenarioEntityPointGroupTextBox.Size = new System.Drawing.Size(272, 20); + this.ScenarioEntityPointGroupTextBox.TabIndex = 20; + this.ScenarioEntityPointGroupTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointGroupTextBox_TextChanged); + // + // label124 + // + this.label124.AutoSize = true; + this.label124.Location = new System.Drawing.Point(64, 122); + this.label124.Name = "label124"; + this.label124.Size = new System.Drawing.Size(39, 13); + this.label124.TabIndex = 19; + this.label124.Text = "Group:"; + // + // ScenarioEntityPointPedTypeHashLabel + // + this.ScenarioEntityPointPedTypeHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointPedTypeHashLabel.AutoSize = true; + this.ScenarioEntityPointPedTypeHashLabel.Location = new System.Drawing.Point(387, 99); + this.ScenarioEntityPointPedTypeHashLabel.Name = "ScenarioEntityPointPedTypeHashLabel"; + this.ScenarioEntityPointPedTypeHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioEntityPointPedTypeHashLabel.TabIndex = 18; + this.ScenarioEntityPointPedTypeHashLabel.Text = "Hash: 0"; + // + // ScenarioEntityPointPedTypeTextBox + // + this.ScenarioEntityPointPedTypeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointPedTypeTextBox.Location = new System.Drawing.Point(109, 96); + this.ScenarioEntityPointPedTypeTextBox.Name = "ScenarioEntityPointPedTypeTextBox"; + this.ScenarioEntityPointPedTypeTextBox.Size = new System.Drawing.Size(272, 20); + this.ScenarioEntityPointPedTypeTextBox.TabIndex = 17; + this.ScenarioEntityPointPedTypeTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointPedTypeTextBox_TextChanged); + // + // label122 + // + this.label122.AutoSize = true; + this.label122.Location = new System.Drawing.Point(51, 99); + this.label122.Name = "label122"; + this.label122.Size = new System.Drawing.Size(52, 13); + this.label122.TabIndex = 16; + this.label122.Text = "Ped type:"; + // + // ScenarioEntityPointSpawnTypeHashLabel + // + this.ScenarioEntityPointSpawnTypeHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointSpawnTypeHashLabel.AutoSize = true; + this.ScenarioEntityPointSpawnTypeHashLabel.Location = new System.Drawing.Point(387, 76); + this.ScenarioEntityPointSpawnTypeHashLabel.Name = "ScenarioEntityPointSpawnTypeHashLabel"; + this.ScenarioEntityPointSpawnTypeHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioEntityPointSpawnTypeHashLabel.TabIndex = 15; + this.ScenarioEntityPointSpawnTypeHashLabel.Text = "Hash: 0"; + // + // ScenarioEntityPointSpawnTypeTextBox + // + this.ScenarioEntityPointSpawnTypeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointSpawnTypeTextBox.Location = new System.Drawing.Point(109, 73); + this.ScenarioEntityPointSpawnTypeTextBox.Name = "ScenarioEntityPointSpawnTypeTextBox"; + this.ScenarioEntityPointSpawnTypeTextBox.Size = new System.Drawing.Size(272, 20); + this.ScenarioEntityPointSpawnTypeTextBox.TabIndex = 14; + this.ScenarioEntityPointSpawnTypeTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointSpawnTypeTextBox_TextChanged); + // + // label120 + // + this.label120.AutoSize = true; + this.label120.Location = new System.Drawing.Point(37, 76); + this.label120.Name = "label120"; + this.label120.Size = new System.Drawing.Size(66, 13); + this.label120.TabIndex = 13; + this.label120.Text = "Spawn type:"; + // + // ScenarioEntityPointRotationTextBox + // + this.ScenarioEntityPointRotationTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointRotationTextBox.Location = new System.Drawing.Point(109, 27); + this.ScenarioEntityPointRotationTextBox.Name = "ScenarioEntityPointRotationTextBox"; + this.ScenarioEntityPointRotationTextBox.Size = new System.Drawing.Size(272, 20); + this.ScenarioEntityPointRotationTextBox.TabIndex = 9; + this.ScenarioEntityPointRotationTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointRotationTextBox_TextChanged); + // + // label118 + // + this.label118.AutoSize = true; + this.label118.Location = new System.Drawing.Point(27, 30); + this.label118.Name = "label118"; + this.label118.Size = new System.Drawing.Size(76, 13); + this.label118.TabIndex = 8; + this.label118.Text = "Offset rotation:"; + // + // ScenarioEntityPointGoToButton + // + this.ScenarioEntityPointGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointGoToButton.Location = new System.Drawing.Point(387, 2); + this.ScenarioEntityPointGoToButton.Name = "ScenarioEntityPointGoToButton"; + this.ScenarioEntityPointGoToButton.Size = new System.Drawing.Size(68, 23); + this.ScenarioEntityPointGoToButton.TabIndex = 7; + this.ScenarioEntityPointGoToButton.Text = "Go to"; + this.ScenarioEntityPointGoToButton.UseVisualStyleBackColor = true; + this.ScenarioEntityPointGoToButton.Click += new System.EventHandler(this.ScenarioEntityPointGoToButton_Click); + // + // ScenarioEntityPointPositionTextBox + // + this.ScenarioEntityPointPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointPositionTextBox.Location = new System.Drawing.Point(109, 4); + this.ScenarioEntityPointPositionTextBox.Name = "ScenarioEntityPointPositionTextBox"; + this.ScenarioEntityPointPositionTextBox.Size = new System.Drawing.Size(272, 20); + this.ScenarioEntityPointPositionTextBox.TabIndex = 6; + this.ScenarioEntityPointPositionTextBox.TextChanged += new System.EventHandler(this.ScenarioEntityPointPositionTextBox_TextChanged); + // + // label117 + // + this.label117.AutoSize = true; + this.label117.Location = new System.Drawing.Point(26, 7); + this.label117.Name = "label117"; + this.label117.Size = new System.Drawing.Size(77, 13); + this.label117.TabIndex = 5; + this.label117.Text = "Offset position:"; + // + // label116 + // + this.label116.AutoSize = true; + this.label116.Location = new System.Drawing.Point(65, 53); + this.label116.Name = "label116"; + this.label116.Size = new System.Drawing.Size(38, 13); + this.label116.TabIndex = 10; + this.label116.Text = "Name:"; + // + // ScenarioChainTabPage + // + this.ScenarioChainTabPage.Controls.Add(this.ScenarioChainDeleteButton); + this.ScenarioChainTabPage.Controls.Add(this.ScenarioChainAddToProjectButton); + this.ScenarioChainTabPage.Controls.Add(this.splitContainer3); + this.ScenarioChainTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioChainTabPage.Name = "ScenarioChainTabPage"; + this.ScenarioChainTabPage.Size = new System.Drawing.Size(510, 443); + this.ScenarioChainTabPage.TabIndex = 3; + this.ScenarioChainTabPage.Text = "Chain"; + this.ScenarioChainTabPage.UseVisualStyleBackColor = true; + // + // ScenarioChainDeleteButton + // + this.ScenarioChainDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainDeleteButton.Enabled = false; + this.ScenarioChainDeleteButton.Location = new System.Drawing.Point(415, 2); + this.ScenarioChainDeleteButton.Name = "ScenarioChainDeleteButton"; + this.ScenarioChainDeleteButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioChainDeleteButton.TabIndex = 9; + this.ScenarioChainDeleteButton.Text = "Delete Chain"; + this.ScenarioChainDeleteButton.UseVisualStyleBackColor = true; + this.ScenarioChainDeleteButton.Click += new System.EventHandler(this.ScenarioChainDeleteButton_Click); + // + // ScenarioChainAddToProjectButton + // + this.ScenarioChainAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainAddToProjectButton.Enabled = false; + this.ScenarioChainAddToProjectButton.Location = new System.Drawing.Point(319, 2); + this.ScenarioChainAddToProjectButton.Name = "ScenarioChainAddToProjectButton"; + this.ScenarioChainAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioChainAddToProjectButton.TabIndex = 8; + this.ScenarioChainAddToProjectButton.Text = "Add to Project"; + this.ScenarioChainAddToProjectButton.UseVisualStyleBackColor = true; + this.ScenarioChainAddToProjectButton.Click += new System.EventHandler(this.ScenarioChainAddToProjectButton_Click); + // + // splitContainer3 + // + this.splitContainer3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer3.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; + this.splitContainer3.Location = new System.Drawing.Point(0, 31); + this.splitContainer3.Name = "splitContainer3"; + // + // splitContainer3.Panel1 + // + this.splitContainer3.Panel1.Controls.Add(this.ScenarioChainMoveEdgeDownButton); + this.splitContainer3.Panel1.Controls.Add(this.ScenarioChainMoveEdgeUpButton); + this.splitContainer3.Panel1.Controls.Add(this.label138); + this.splitContainer3.Panel1.Controls.Add(this.ScenarioChainUnk1UpDown); + this.splitContainer3.Panel1.Controls.Add(this.ScenarioChainRemoveEdgeButton); + this.splitContainer3.Panel1.Controls.Add(this.ScenarioChainAddEdgeButton); + this.splitContainer3.Panel1.Controls.Add(this.ScenarioChainEdgesListBox); + this.splitContainer3.Panel1.Controls.Add(this.ScenarioChainEdgeCountLabel); + // + // splitContainer3.Panel2 + // + this.splitContainer3.Panel2.Controls.Add(this.ScenarioChainEdgePanel); + this.splitContainer3.Size = new System.Drawing.Size(510, 412); + this.splitContainer3.SplitterDistance = 205; + this.splitContainer3.TabIndex = 1; + // + // ScenarioChainMoveEdgeDownButton + // + this.ScenarioChainMoveEdgeDownButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ScenarioChainMoveEdgeDownButton.Location = new System.Drawing.Point(85, 353); + this.ScenarioChainMoveEdgeDownButton.Name = "ScenarioChainMoveEdgeDownButton"; + this.ScenarioChainMoveEdgeDownButton.Size = new System.Drawing.Size(76, 23); + this.ScenarioChainMoveEdgeDownButton.TabIndex = 5; + this.ScenarioChainMoveEdgeDownButton.Text = "Move Down"; + this.ScenarioChainMoveEdgeDownButton.UseVisualStyleBackColor = true; + this.ScenarioChainMoveEdgeDownButton.Click += new System.EventHandler(this.ScenarioChainMoveEdgeDownButton_Click); + // + // ScenarioChainMoveEdgeUpButton + // + this.ScenarioChainMoveEdgeUpButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ScenarioChainMoveEdgeUpButton.Location = new System.Drawing.Point(3, 353); + this.ScenarioChainMoveEdgeUpButton.Name = "ScenarioChainMoveEdgeUpButton"; + this.ScenarioChainMoveEdgeUpButton.Size = new System.Drawing.Size(76, 23); + this.ScenarioChainMoveEdgeUpButton.TabIndex = 4; + this.ScenarioChainMoveEdgeUpButton.Text = "Move Up"; + this.ScenarioChainMoveEdgeUpButton.UseVisualStyleBackColor = true; + this.ScenarioChainMoveEdgeUpButton.Click += new System.EventHandler(this.ScenarioChainMoveEdgeUpButton_Click); + // + // label138 + // + this.label138.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label138.AutoSize = true; + this.label138.Location = new System.Drawing.Point(10, 391); + this.label138.Name = "label138"; + this.label138.Size = new System.Drawing.Size(69, 13); + this.label138.TabIndex = 6; + this.label138.Text = "Chain Unk 1:"; + // + // ScenarioChainUnk1UpDown + // + this.ScenarioChainUnk1UpDown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ScenarioChainUnk1UpDown.Location = new System.Drawing.Point(85, 389); + this.ScenarioChainUnk1UpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioChainUnk1UpDown.Name = "ScenarioChainUnk1UpDown"; + this.ScenarioChainUnk1UpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioChainUnk1UpDown.TabIndex = 7; + this.ScenarioChainUnk1UpDown.ValueChanged += new System.EventHandler(this.ScenarioChainUnk1UpDown_ValueChanged); + // + // ScenarioChainRemoveEdgeButton + // + this.ScenarioChainRemoveEdgeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ScenarioChainRemoveEdgeButton.Location = new System.Drawing.Point(85, 324); + this.ScenarioChainRemoveEdgeButton.Name = "ScenarioChainRemoveEdgeButton"; + this.ScenarioChainRemoveEdgeButton.Size = new System.Drawing.Size(76, 23); + this.ScenarioChainRemoveEdgeButton.TabIndex = 3; + this.ScenarioChainRemoveEdgeButton.Text = "Remove"; + this.ScenarioChainRemoveEdgeButton.UseVisualStyleBackColor = true; + this.ScenarioChainRemoveEdgeButton.Click += new System.EventHandler(this.ScenarioChainRemoveEdgeButton_Click); + // + // ScenarioChainAddEdgeButton + // + this.ScenarioChainAddEdgeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ScenarioChainAddEdgeButton.Location = new System.Drawing.Point(3, 324); + this.ScenarioChainAddEdgeButton.Name = "ScenarioChainAddEdgeButton"; + this.ScenarioChainAddEdgeButton.Size = new System.Drawing.Size(76, 23); + this.ScenarioChainAddEdgeButton.TabIndex = 2; + this.ScenarioChainAddEdgeButton.Text = "Add"; + this.ScenarioChainAddEdgeButton.UseVisualStyleBackColor = true; + this.ScenarioChainAddEdgeButton.Click += new System.EventHandler(this.ScenarioChainAddEdgeButton_Click); + // + // ScenarioChainEdgesListBox + // + this.ScenarioChainEdgesListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainEdgesListBox.FormattingEnabled = true; + this.ScenarioChainEdgesListBox.Location = new System.Drawing.Point(0, 0); + this.ScenarioChainEdgesListBox.Name = "ScenarioChainEdgesListBox"; + this.ScenarioChainEdgesListBox.Size = new System.Drawing.Size(202, 290); + this.ScenarioChainEdgesListBox.TabIndex = 0; + this.ScenarioChainEdgesListBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioChainEdgesListBox_SelectedIndexChanged); + // + // ScenarioChainEdgeCountLabel + // + this.ScenarioChainEdgeCountLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ScenarioChainEdgeCountLabel.AutoSize = true; + this.ScenarioChainEdgeCountLabel.Location = new System.Drawing.Point(3, 308); + this.ScenarioChainEdgeCountLabel.Name = "ScenarioChainEdgeCountLabel"; + this.ScenarioChainEdgeCountLabel.Size = new System.Drawing.Size(75, 13); + this.ScenarioChainEdgeCountLabel.TabIndex = 1; + this.ScenarioChainEdgeCountLabel.Text = "Edge Count: 0"; + // + // ScenarioChainEdgePanel + // + this.ScenarioChainEdgePanel.Controls.Add(this.ScenarioChainEdgeNavSpeedComboBox); + this.ScenarioChainEdgePanel.Controls.Add(this.label137); + this.ScenarioChainEdgePanel.Controls.Add(this.ScenarioChainEdgeNavModeComboBox); + this.ScenarioChainEdgePanel.Controls.Add(this.label136); + this.ScenarioChainEdgePanel.Controls.Add(this.ScenarioChainEdgeActionComboBox); + this.ScenarioChainEdgePanel.Controls.Add(this.label127); + this.ScenarioChainEdgePanel.Controls.Add(this.ScenarioChainEdgeNodeIndexToUpDown); + this.ScenarioChainEdgePanel.Controls.Add(this.ScenarioChainEdgeNodeIndexFromUpDown); + this.ScenarioChainEdgePanel.Controls.Add(this.label125); + this.ScenarioChainEdgePanel.Controls.Add(this.label121); + this.ScenarioChainEdgePanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.ScenarioChainEdgePanel.Enabled = false; + this.ScenarioChainEdgePanel.Location = new System.Drawing.Point(0, 0); + this.ScenarioChainEdgePanel.Name = "ScenarioChainEdgePanel"; + this.ScenarioChainEdgePanel.Size = new System.Drawing.Size(301, 412); + this.ScenarioChainEdgePanel.TabIndex = 0; + // + // ScenarioChainEdgeNavSpeedComboBox + // + this.ScenarioChainEdgeNavSpeedComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioChainEdgeNavSpeedComboBox.FormattingEnabled = true; + this.ScenarioChainEdgeNavSpeedComboBox.Location = new System.Drawing.Point(100, 118); + this.ScenarioChainEdgeNavSpeedComboBox.Name = "ScenarioChainEdgeNavSpeedComboBox"; + this.ScenarioChainEdgeNavSpeedComboBox.Size = new System.Drawing.Size(142, 21); + this.ScenarioChainEdgeNavSpeedComboBox.TabIndex = 10; + this.ScenarioChainEdgeNavSpeedComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioChainEdgeNavSpeedComboBox_SelectedIndexChanged); + // + // label137 + // + this.label137.AutoSize = true; + this.label137.Location = new System.Drawing.Point(33, 121); + this.label137.Name = "label137"; + this.label137.Size = new System.Drawing.Size(61, 13); + this.label137.TabIndex = 9; + this.label137.Text = "NavSpeed:"; + // + // ScenarioChainEdgeNavModeComboBox + // + this.ScenarioChainEdgeNavModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioChainEdgeNavModeComboBox.FormattingEnabled = true; + this.ScenarioChainEdgeNavModeComboBox.Location = new System.Drawing.Point(100, 91); + this.ScenarioChainEdgeNavModeComboBox.Name = "ScenarioChainEdgeNavModeComboBox"; + this.ScenarioChainEdgeNavModeComboBox.Size = new System.Drawing.Size(142, 21); + this.ScenarioChainEdgeNavModeComboBox.TabIndex = 8; + this.ScenarioChainEdgeNavModeComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioChainEdgeNavModeComboBox_SelectedIndexChanged); + // + // label136 + // + this.label136.AutoSize = true; + this.label136.Location = new System.Drawing.Point(37, 94); + this.label136.Name = "label136"; + this.label136.Size = new System.Drawing.Size(57, 13); + this.label136.TabIndex = 7; + this.label136.Text = "NavMode:"; + // + // ScenarioChainEdgeActionComboBox + // + this.ScenarioChainEdgeActionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioChainEdgeActionComboBox.FormattingEnabled = true; + this.ScenarioChainEdgeActionComboBox.Location = new System.Drawing.Point(100, 64); + this.ScenarioChainEdgeActionComboBox.Name = "ScenarioChainEdgeActionComboBox"; + this.ScenarioChainEdgeActionComboBox.Size = new System.Drawing.Size(142, 21); + this.ScenarioChainEdgeActionComboBox.TabIndex = 6; + this.ScenarioChainEdgeActionComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioChainEdgeActionComboBox_SelectedIndexChanged); + // + // label127 + // + this.label127.AutoSize = true; + this.label127.Location = new System.Drawing.Point(54, 67); + this.label127.Name = "label127"; + this.label127.Size = new System.Drawing.Size(40, 13); + this.label127.TabIndex = 5; + this.label127.Text = "Action:"; + // + // ScenarioChainEdgeNodeIndexToUpDown + // + this.ScenarioChainEdgeNodeIndexToUpDown.Location = new System.Drawing.Point(100, 38); + this.ScenarioChainEdgeNodeIndexToUpDown.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.ScenarioChainEdgeNodeIndexToUpDown.Name = "ScenarioChainEdgeNodeIndexToUpDown"; + this.ScenarioChainEdgeNodeIndexToUpDown.Size = new System.Drawing.Size(81, 20); + this.ScenarioChainEdgeNodeIndexToUpDown.TabIndex = 4; + this.ScenarioChainEdgeNodeIndexToUpDown.ValueChanged += new System.EventHandler(this.ScenarioChainEdgeNodeIndexToUpDown_ValueChanged); + // + // ScenarioChainEdgeNodeIndexFromUpDown + // + this.ScenarioChainEdgeNodeIndexFromUpDown.Location = new System.Drawing.Point(100, 12); + this.ScenarioChainEdgeNodeIndexFromUpDown.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.ScenarioChainEdgeNodeIndexFromUpDown.Name = "ScenarioChainEdgeNodeIndexFromUpDown"; + this.ScenarioChainEdgeNodeIndexFromUpDown.Size = new System.Drawing.Size(81, 20); + this.ScenarioChainEdgeNodeIndexFromUpDown.TabIndex = 2; + this.ScenarioChainEdgeNodeIndexFromUpDown.ValueChanged += new System.EventHandler(this.ScenarioChainEdgeNodeIndexFromUpDown_ValueChanged); + // + // label125 + // + this.label125.AutoSize = true; + this.label125.Location = new System.Drawing.Point(19, 40); + this.label125.Name = "label125"; + this.label125.Size = new System.Drawing.Size(75, 13); + this.label125.TabIndex = 3; + this.label125.Text = "NodeIndexTo:"; + // + // label121 + // + this.label121.AutoSize = true; + this.label121.Location = new System.Drawing.Point(9, 14); + this.label121.Name = "label121"; + this.label121.Size = new System.Drawing.Size(85, 13); + this.label121.TabIndex = 1; + this.label121.Text = "NodeIndexFrom:"; + // + // ScenarioChainNodeTabPage + // + this.ScenarioChainNodeTabPage.Controls.Add(this.ScenarioChainNodePanel); + this.ScenarioChainNodeTabPage.Controls.Add(this.ScenarioChainNodeDeleteButton); + this.ScenarioChainNodeTabPage.Controls.Add(this.ScenarioChainNodeCheckBox); + this.ScenarioChainNodeTabPage.Controls.Add(this.ScenarioChainNodeAddToProjectButton); + this.ScenarioChainNodeTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioChainNodeTabPage.Name = "ScenarioChainNodeTabPage"; + this.ScenarioChainNodeTabPage.Size = new System.Drawing.Size(510, 443); + this.ScenarioChainNodeTabPage.TabIndex = 6; + this.ScenarioChainNodeTabPage.Text = "Chain Node"; + this.ScenarioChainNodeTabPage.UseVisualStyleBackColor = true; + // + // ScenarioChainNodePanel + // + this.ScenarioChainNodePanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodePanel.Controls.Add(this.ScenarioChainNodeTypeComboBox); + this.ScenarioChainNodePanel.Controls.Add(this.ScenarioChainNodeIndexTextBox); + this.ScenarioChainNodePanel.Controls.Add(this.label115); + this.ScenarioChainNodePanel.Controls.Add(this.ScenarioChainNodeLastCheckBox); + this.ScenarioChainNodePanel.Controls.Add(this.ScenarioChainNodeFirstCheckBox); + this.ScenarioChainNodePanel.Controls.Add(this.label123); + this.ScenarioChainNodePanel.Controls.Add(this.ScenarioChainNodeUnk1HashLabel); + this.ScenarioChainNodePanel.Controls.Add(this.ScenarioChainNodeUnk1TextBox); + this.ScenarioChainNodePanel.Controls.Add(this.label119); + this.ScenarioChainNodePanel.Controls.Add(this.ScenarioChainNodeGoToButton); + this.ScenarioChainNodePanel.Controls.Add(this.ScenarioChainNodePositionTextBox); + this.ScenarioChainNodePanel.Controls.Add(this.label105); + this.ScenarioChainNodePanel.Enabled = false; + this.ScenarioChainNodePanel.Location = new System.Drawing.Point(0, 29); + this.ScenarioChainNodePanel.Name = "ScenarioChainNodePanel"; + this.ScenarioChainNodePanel.Size = new System.Drawing.Size(510, 201); + this.ScenarioChainNodePanel.TabIndex = 8; + // + // ScenarioChainNodeTypeComboBox + // + this.ScenarioChainNodeTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodeTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioChainNodeTypeComboBox.FormattingEnabled = true; + this.ScenarioChainNodeTypeComboBox.Location = new System.Drawing.Point(73, 55); + this.ScenarioChainNodeTypeComboBox.Name = "ScenarioChainNodeTypeComboBox"; + this.ScenarioChainNodeTypeComboBox.Size = new System.Drawing.Size(336, 21); + this.ScenarioChainNodeTypeComboBox.TabIndex = 12; + this.ScenarioChainNodeTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioChainNodeTypeComboBox_SelectedIndexChanged); + // + // ScenarioChainNodeIndexTextBox + // + this.ScenarioChainNodeIndexTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodeIndexTextBox.Location = new System.Drawing.Point(73, 142); + this.ScenarioChainNodeIndexTextBox.Name = "ScenarioChainNodeIndexTextBox"; + this.ScenarioChainNodeIndexTextBox.ReadOnly = true; + this.ScenarioChainNodeIndexTextBox.Size = new System.Drawing.Size(94, 20); + this.ScenarioChainNodeIndexTextBox.TabIndex = 17; + // + // label115 + // + this.label115.AutoSize = true; + this.label115.Location = new System.Drawing.Point(33, 145); + this.label115.Name = "label115"; + this.label115.Size = new System.Drawing.Size(36, 13); + this.label115.TabIndex = 16; + this.label115.Text = "Index:"; + // + // ScenarioChainNodeLastCheckBox + // + this.ScenarioChainNodeLastCheckBox.AutoSize = true; + this.ScenarioChainNodeLastCheckBox.Location = new System.Drawing.Point(73, 105); + this.ScenarioChainNodeLastCheckBox.Name = "ScenarioChainNodeLastCheckBox"; + this.ScenarioChainNodeLastCheckBox.Size = new System.Drawing.Size(86, 17); + this.ScenarioChainNodeLastCheckBox.TabIndex = 15; + this.ScenarioChainNodeLastCheckBox.Text = "Last in chain"; + this.ScenarioChainNodeLastCheckBox.UseVisualStyleBackColor = true; + this.ScenarioChainNodeLastCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioChainNodeLastCheckBox_CheckedChanged); + // + // ScenarioChainNodeFirstCheckBox + // + this.ScenarioChainNodeFirstCheckBox.AutoSize = true; + this.ScenarioChainNodeFirstCheckBox.Location = new System.Drawing.Point(73, 82); + this.ScenarioChainNodeFirstCheckBox.Name = "ScenarioChainNodeFirstCheckBox"; + this.ScenarioChainNodeFirstCheckBox.Size = new System.Drawing.Size(85, 17); + this.ScenarioChainNodeFirstCheckBox.TabIndex = 14; + this.ScenarioChainNodeFirstCheckBox.Text = "First in chain"; + this.ScenarioChainNodeFirstCheckBox.UseVisualStyleBackColor = true; + this.ScenarioChainNodeFirstCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioChainNodeFirstCheckBox_CheckedChanged); + // + // label123 + // + this.label123.AutoSize = true; + this.label123.Location = new System.Drawing.Point(33, 58); + this.label123.Name = "label123"; + this.label123.Size = new System.Drawing.Size(34, 13); + this.label123.TabIndex = 11; + this.label123.Text = "Type:"; + // + // ScenarioChainNodeUnk1HashLabel + // + this.ScenarioChainNodeUnk1HashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodeUnk1HashLabel.AutoSize = true; + this.ScenarioChainNodeUnk1HashLabel.Location = new System.Drawing.Point(341, 32); + this.ScenarioChainNodeUnk1HashLabel.Name = "ScenarioChainNodeUnk1HashLabel"; + this.ScenarioChainNodeUnk1HashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioChainNodeUnk1HashLabel.TabIndex = 10; + this.ScenarioChainNodeUnk1HashLabel.Text = "Hash: 0"; + // + // ScenarioChainNodeUnk1TextBox + // + this.ScenarioChainNodeUnk1TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodeUnk1TextBox.Location = new System.Drawing.Point(73, 29); + this.ScenarioChainNodeUnk1TextBox.Name = "ScenarioChainNodeUnk1TextBox"; + this.ScenarioChainNodeUnk1TextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioChainNodeUnk1TextBox.TabIndex = 9; + this.ScenarioChainNodeUnk1TextBox.TextChanged += new System.EventHandler(this.ScenarioChainNodeUnk1TextBox_TextChanged); + // + // label119 + // + this.label119.AutoSize = true; + this.label119.Location = new System.Drawing.Point(28, 32); + this.label119.Name = "label119"; + this.label119.Size = new System.Drawing.Size(39, 13); + this.label119.TabIndex = 8; + this.label119.Text = "Unk 1:"; + // + // ScenarioChainNodeGoToButton + // + this.ScenarioChainNodeGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodeGoToButton.Location = new System.Drawing.Point(341, 1); + this.ScenarioChainNodeGoToButton.Name = "ScenarioChainNodeGoToButton"; + this.ScenarioChainNodeGoToButton.Size = new System.Drawing.Size(68, 23); + this.ScenarioChainNodeGoToButton.TabIndex = 7; + this.ScenarioChainNodeGoToButton.Text = "Go to"; + this.ScenarioChainNodeGoToButton.UseVisualStyleBackColor = true; + this.ScenarioChainNodeGoToButton.Click += new System.EventHandler(this.ScenarioChainNodeGoToButton_Click); + // + // ScenarioChainNodePositionTextBox + // + this.ScenarioChainNodePositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodePositionTextBox.Location = new System.Drawing.Point(73, 3); + this.ScenarioChainNodePositionTextBox.Name = "ScenarioChainNodePositionTextBox"; + this.ScenarioChainNodePositionTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioChainNodePositionTextBox.TabIndex = 6; + this.ScenarioChainNodePositionTextBox.TextChanged += new System.EventHandler(this.ScenarioChainNodePositionTextBox_TextChanged); + // + // label105 + // + this.label105.AutoSize = true; + this.label105.Location = new System.Drawing.Point(20, 6); + this.label105.Name = "label105"; + this.label105.Size = new System.Drawing.Size(47, 13); + this.label105.TabIndex = 5; + this.label105.Text = "Position:"; + // + // ScenarioChainNodeDeleteButton + // + this.ScenarioChainNodeDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodeDeleteButton.Enabled = false; + this.ScenarioChainNodeDeleteButton.Location = new System.Drawing.Point(415, 2); + this.ScenarioChainNodeDeleteButton.Name = "ScenarioChainNodeDeleteButton"; + this.ScenarioChainNodeDeleteButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioChainNodeDeleteButton.TabIndex = 7; + this.ScenarioChainNodeDeleteButton.Text = "Delete Node"; + this.ScenarioChainNodeDeleteButton.UseVisualStyleBackColor = true; + this.ScenarioChainNodeDeleteButton.Click += new System.EventHandler(this.ScenarioChainNodeDeleteButton_Click); + // + // ScenarioChainNodeCheckBox + // + this.ScenarioChainNodeCheckBox.AutoSize = true; + this.ScenarioChainNodeCheckBox.Location = new System.Drawing.Point(6, 6); + this.ScenarioChainNodeCheckBox.Name = "ScenarioChainNodeCheckBox"; + this.ScenarioChainNodeCheckBox.Size = new System.Drawing.Size(116, 17); + this.ScenarioChainNodeCheckBox.TabIndex = 5; + this.ScenarioChainNodeCheckBox.Text = "Define Chain Node"; + this.ScenarioChainNodeCheckBox.UseVisualStyleBackColor = true; + this.ScenarioChainNodeCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioChainNodeCheckBox_CheckedChanged); + // + // ScenarioChainNodeAddToProjectButton + // + this.ScenarioChainNodeAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioChainNodeAddToProjectButton.Enabled = false; + this.ScenarioChainNodeAddToProjectButton.Location = new System.Drawing.Point(319, 2); + this.ScenarioChainNodeAddToProjectButton.Name = "ScenarioChainNodeAddToProjectButton"; + this.ScenarioChainNodeAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioChainNodeAddToProjectButton.TabIndex = 6; + this.ScenarioChainNodeAddToProjectButton.Text = "Add to Project"; + this.ScenarioChainNodeAddToProjectButton.UseVisualStyleBackColor = true; + this.ScenarioChainNodeAddToProjectButton.Click += new System.EventHandler(this.ScenarioChainNodeAddToProjectButton_Click); + // + // ScenarioClusterTabPage + // + this.ScenarioClusterTabPage.Controls.Add(this.ScenarioClusterDeleteButton); + this.ScenarioClusterTabPage.Controls.Add(this.ScenarioClusterAddToProjectButton); + this.ScenarioClusterTabPage.Controls.Add(this.ScenarioClusterCheckBox); + this.ScenarioClusterTabPage.Controls.Add(this.ScenarioClusterPanel); + this.ScenarioClusterTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioClusterTabPage.Name = "ScenarioClusterTabPage"; + this.ScenarioClusterTabPage.Size = new System.Drawing.Size(510, 443); + this.ScenarioClusterTabPage.TabIndex = 4; + this.ScenarioClusterTabPage.Text = "Cluster"; + this.ScenarioClusterTabPage.UseVisualStyleBackColor = true; + // + // ScenarioClusterDeleteButton + // + this.ScenarioClusterDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterDeleteButton.Enabled = false; + this.ScenarioClusterDeleteButton.Location = new System.Drawing.Point(415, 2); + this.ScenarioClusterDeleteButton.Name = "ScenarioClusterDeleteButton"; + this.ScenarioClusterDeleteButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioClusterDeleteButton.TabIndex = 3; + this.ScenarioClusterDeleteButton.Text = "Delete Cluster"; + this.ScenarioClusterDeleteButton.UseVisualStyleBackColor = true; + this.ScenarioClusterDeleteButton.Click += new System.EventHandler(this.ScenarioClusterDeleteButton_Click); + // + // ScenarioClusterAddToProjectButton + // + this.ScenarioClusterAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterAddToProjectButton.Enabled = false; + this.ScenarioClusterAddToProjectButton.Location = new System.Drawing.Point(319, 2); + this.ScenarioClusterAddToProjectButton.Name = "ScenarioClusterAddToProjectButton"; + this.ScenarioClusterAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioClusterAddToProjectButton.TabIndex = 2; + this.ScenarioClusterAddToProjectButton.Text = "Add to Project"; + this.ScenarioClusterAddToProjectButton.UseVisualStyleBackColor = true; + this.ScenarioClusterAddToProjectButton.Click += new System.EventHandler(this.ScenarioClusterAddToProjectButton_Click); + // + // ScenarioClusterCheckBox + // + this.ScenarioClusterCheckBox.AutoSize = true; + this.ScenarioClusterCheckBox.Location = new System.Drawing.Point(6, 6); + this.ScenarioClusterCheckBox.Name = "ScenarioClusterCheckBox"; + this.ScenarioClusterCheckBox.Size = new System.Drawing.Size(92, 17); + this.ScenarioClusterCheckBox.TabIndex = 1; + this.ScenarioClusterCheckBox.Text = "Define Cluster"; + this.ScenarioClusterCheckBox.UseVisualStyleBackColor = true; + this.ScenarioClusterCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioClusterCheckBox_CheckedChanged); + // + // ScenarioClusterPanel + // + this.ScenarioClusterPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPanel.Controls.Add(this.label159); + this.ScenarioClusterPanel.Controls.Add(this.ScenarioClusterAddPointButton); + this.ScenarioClusterPanel.Controls.Add(this.label158); + this.ScenarioClusterPanel.Controls.Add(this.ScenarioClusterPointsListBox); + this.ScenarioClusterPanel.Controls.Add(this.ScenarioClusterRadiusTextBox); + this.ScenarioClusterPanel.Controls.Add(this.label157); + this.ScenarioClusterPanel.Controls.Add(this.ScenarioClusterUnk2CheckBox); + this.ScenarioClusterPanel.Controls.Add(this.ScenarioClusterUnk1TextBox); + this.ScenarioClusterPanel.Controls.Add(this.label140); + this.ScenarioClusterPanel.Controls.Add(this.ScenarioClusterGoToButton); + this.ScenarioClusterPanel.Controls.Add(this.ScenarioClusterCenterTextBox); + this.ScenarioClusterPanel.Controls.Add(this.label139); + this.ScenarioClusterPanel.Enabled = false; + this.ScenarioClusterPanel.Location = new System.Drawing.Point(0, 29); + this.ScenarioClusterPanel.Name = "ScenarioClusterPanel"; + this.ScenarioClusterPanel.Size = new System.Drawing.Size(510, 415); + this.ScenarioClusterPanel.TabIndex = 4; + // + // ScenarioClusterRadiusTextBox + // + this.ScenarioClusterRadiusTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterRadiusTextBox.Location = new System.Drawing.Point(100, 29); + this.ScenarioClusterRadiusTextBox.Name = "ScenarioClusterRadiusTextBox"; + this.ScenarioClusterRadiusTextBox.Size = new System.Drawing.Size(163, 20); + this.ScenarioClusterRadiusTextBox.TabIndex = 9; + this.ScenarioClusterRadiusTextBox.TextChanged += new System.EventHandler(this.ScenarioClusterRadiusTextBox_TextChanged); + // + // label157 + // + this.label157.AutoSize = true; + this.label157.Location = new System.Drawing.Point(51, 32); + this.label157.Name = "label157"; + this.label157.Size = new System.Drawing.Size(43, 13); + this.label157.TabIndex = 8; + this.label157.Text = "Radius:"; + // + // ScenarioClusterUnk2CheckBox + // + this.ScenarioClusterUnk2CheckBox.AutoSize = true; + this.ScenarioClusterUnk2CheckBox.Location = new System.Drawing.Point(100, 81); + this.ScenarioClusterUnk2CheckBox.Name = "ScenarioClusterUnk2CheckBox"; + this.ScenarioClusterUnk2CheckBox.Size = new System.Drawing.Size(55, 17); + this.ScenarioClusterUnk2CheckBox.TabIndex = 12; + this.ScenarioClusterUnk2CheckBox.Text = "Unk 2"; + this.ScenarioClusterUnk2CheckBox.UseVisualStyleBackColor = true; + this.ScenarioClusterUnk2CheckBox.CheckedChanged += new System.EventHandler(this.ScenarioClusterUnk2CheckBox_CheckedChanged); + // + // ScenarioClusterUnk1TextBox + // + this.ScenarioClusterUnk1TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterUnk1TextBox.Location = new System.Drawing.Point(100, 55); + this.ScenarioClusterUnk1TextBox.Name = "ScenarioClusterUnk1TextBox"; + this.ScenarioClusterUnk1TextBox.Size = new System.Drawing.Size(163, 20); + this.ScenarioClusterUnk1TextBox.TabIndex = 11; + this.ScenarioClusterUnk1TextBox.TextChanged += new System.EventHandler(this.ScenarioClusterUnk1TextBox_TextChanged); + // + // label140 + // + this.label140.AutoSize = true; + this.label140.Location = new System.Drawing.Point(4, 58); + this.label140.Name = "label140"; + this.label140.Size = new System.Drawing.Size(90, 13); + this.label140.TabIndex = 10; + this.label140.Text = "Probability Unk 1:"; + // + // ScenarioClusterGoToButton + // + this.ScenarioClusterGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterGoToButton.Location = new System.Drawing.Point(341, 1); + this.ScenarioClusterGoToButton.Name = "ScenarioClusterGoToButton"; + this.ScenarioClusterGoToButton.Size = new System.Drawing.Size(68, 23); + this.ScenarioClusterGoToButton.TabIndex = 7; + this.ScenarioClusterGoToButton.Text = "Go to"; + this.ScenarioClusterGoToButton.UseVisualStyleBackColor = true; + this.ScenarioClusterGoToButton.Click += new System.EventHandler(this.ScenarioClusterGoToButton_Click); + // + // ScenarioClusterCenterTextBox + // + this.ScenarioClusterCenterTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterCenterTextBox.Location = new System.Drawing.Point(100, 3); + this.ScenarioClusterCenterTextBox.Name = "ScenarioClusterCenterTextBox"; + this.ScenarioClusterCenterTextBox.Size = new System.Drawing.Size(235, 20); + this.ScenarioClusterCenterTextBox.TabIndex = 6; + this.ScenarioClusterCenterTextBox.TextChanged += new System.EventHandler(this.ScenarioClusterCenterTextBox_TextChanged); + // + // label139 + // + this.label139.AutoSize = true; + this.label139.Location = new System.Drawing.Point(53, 6); + this.label139.Name = "label139"; + this.label139.Size = new System.Drawing.Size(41, 13); + this.label139.TabIndex = 5; + this.label139.Text = "Center:"; + // + // ScenarioClusterPointTabPage + // + this.ScenarioClusterPointTabPage.Controls.Add(this.ScenarioClusterPointDeleteButton); + this.ScenarioClusterPointTabPage.Controls.Add(this.ScenarioClusterPointAddToProjectButton); + this.ScenarioClusterPointTabPage.Controls.Add(this.ScenarioClusterPointPanel); + this.ScenarioClusterPointTabPage.Controls.Add(this.ScenarioClusterPointCheckBox); + this.ScenarioClusterPointTabPage.Location = new System.Drawing.Point(4, 22); + this.ScenarioClusterPointTabPage.Name = "ScenarioClusterPointTabPage"; + this.ScenarioClusterPointTabPage.Size = new System.Drawing.Size(510, 443); + this.ScenarioClusterPointTabPage.TabIndex = 5; + this.ScenarioClusterPointTabPage.Text = "Cluster Point"; + this.ScenarioClusterPointTabPage.UseVisualStyleBackColor = true; + // + // ScenarioClusterPointDeleteButton + // + this.ScenarioClusterPointDeleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointDeleteButton.Enabled = false; + this.ScenarioClusterPointDeleteButton.Location = new System.Drawing.Point(415, 2); + this.ScenarioClusterPointDeleteButton.Name = "ScenarioClusterPointDeleteButton"; + this.ScenarioClusterPointDeleteButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioClusterPointDeleteButton.TabIndex = 7; + this.ScenarioClusterPointDeleteButton.Text = "Delete Point"; + this.ScenarioClusterPointDeleteButton.UseVisualStyleBackColor = true; + this.ScenarioClusterPointDeleteButton.Click += new System.EventHandler(this.ScenarioClusterPointDeleteButton_Click); + // + // ScenarioClusterPointAddToProjectButton + // + this.ScenarioClusterPointAddToProjectButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointAddToProjectButton.Enabled = false; + this.ScenarioClusterPointAddToProjectButton.Location = new System.Drawing.Point(319, 2); + this.ScenarioClusterPointAddToProjectButton.Name = "ScenarioClusterPointAddToProjectButton"; + this.ScenarioClusterPointAddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioClusterPointAddToProjectButton.TabIndex = 6; + this.ScenarioClusterPointAddToProjectButton.Text = "Add to Project"; + this.ScenarioClusterPointAddToProjectButton.UseVisualStyleBackColor = true; + this.ScenarioClusterPointAddToProjectButton.Click += new System.EventHandler(this.ScenarioClusterPointAddToProjectButton_Click); + // + // ScenarioClusterPointPanel + // + this.ScenarioClusterPointPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointImapHashLabel); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointImapTextBox); + this.ScenarioClusterPointPanel.Controls.Add(this.label143); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointGroupHashLabel); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointGroupTextBox); + this.ScenarioClusterPointPanel.Controls.Add(this.label141); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointInteriorHashLabel); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointFlagsCheckedListBox); + this.ScenarioClusterPointPanel.Controls.Add(this.label142); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointDirectionTextBox); + this.ScenarioClusterPointPanel.Controls.Add(this.label144); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointFlagsUpDown); + this.ScenarioClusterPointPanel.Controls.Add(this.label145); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointGoToButton); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointWaitTimeUpDown); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointPositionTextBox); + this.ScenarioClusterPointPanel.Controls.Add(this.label146); + this.ScenarioClusterPointPanel.Controls.Add(this.label147); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointRadiusUpDown); + this.ScenarioClusterPointPanel.Controls.Add(this.label148); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointAnimalFlagUpDown); + this.ScenarioClusterPointPanel.Controls.Add(this.label149); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointProbabilityUpDown); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointInteriorTextBox); + this.ScenarioClusterPointPanel.Controls.Add(this.label151); + this.ScenarioClusterPointPanel.Controls.Add(this.label152); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointTimeEndUpDown); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointTimeStartUpDown); + this.ScenarioClusterPointPanel.Controls.Add(this.label153); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointModelSetComboBox); + this.ScenarioClusterPointPanel.Controls.Add(this.label154); + this.ScenarioClusterPointPanel.Controls.Add(this.ScenarioClusterPointTypeComboBox); + this.ScenarioClusterPointPanel.Controls.Add(this.label155); + this.ScenarioClusterPointPanel.Enabled = false; + this.ScenarioClusterPointPanel.Location = new System.Drawing.Point(0, 29); + this.ScenarioClusterPointPanel.Name = "ScenarioClusterPointPanel"; + this.ScenarioClusterPointPanel.Size = new System.Drawing.Size(510, 414); + this.ScenarioClusterPointPanel.TabIndex = 8; + // + // ScenarioClusterPointImapHashLabel + // + this.ScenarioClusterPointImapHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointImapHashLabel.AutoSize = true; + this.ScenarioClusterPointImapHashLabel.Location = new System.Drawing.Point(341, 146); + this.ScenarioClusterPointImapHashLabel.Name = "ScenarioClusterPointImapHashLabel"; + this.ScenarioClusterPointImapHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioClusterPointImapHashLabel.TabIndex = 22; + this.ScenarioClusterPointImapHashLabel.Text = "Hash: 0"; + // + // ScenarioClusterPointImapTextBox + // + this.ScenarioClusterPointImapTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointImapTextBox.Location = new System.Drawing.Point(73, 143); + this.ScenarioClusterPointImapTextBox.Name = "ScenarioClusterPointImapTextBox"; + this.ScenarioClusterPointImapTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioClusterPointImapTextBox.TabIndex = 21; + this.ScenarioClusterPointImapTextBox.TextChanged += new System.EventHandler(this.ScenarioClusterPointImapTextBox_TextChanged); + // + // label143 + // + this.label143.AutoSize = true; + this.label143.Location = new System.Drawing.Point(34, 146); + this.label143.Name = "label143"; + this.label143.Size = new System.Drawing.Size(33, 13); + this.label143.TabIndex = 20; + this.label143.Text = "Imap:"; + // + // ScenarioClusterPointGroupHashLabel + // + this.ScenarioClusterPointGroupHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointGroupHashLabel.AutoSize = true; + this.ScenarioClusterPointGroupHashLabel.Location = new System.Drawing.Point(341, 123); + this.ScenarioClusterPointGroupHashLabel.Name = "ScenarioClusterPointGroupHashLabel"; + this.ScenarioClusterPointGroupHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioClusterPointGroupHashLabel.TabIndex = 19; + this.ScenarioClusterPointGroupHashLabel.Text = "Hash: 0"; + // + // ScenarioClusterPointGroupTextBox + // + this.ScenarioClusterPointGroupTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointGroupTextBox.Location = new System.Drawing.Point(73, 120); + this.ScenarioClusterPointGroupTextBox.Name = "ScenarioClusterPointGroupTextBox"; + this.ScenarioClusterPointGroupTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioClusterPointGroupTextBox.TabIndex = 18; + this.ScenarioClusterPointGroupTextBox.TextChanged += new System.EventHandler(this.ScenarioClusterPointGroupTextBox_TextChanged); + // + // label141 + // + this.label141.AutoSize = true; + this.label141.Location = new System.Drawing.Point(28, 123); + this.label141.Name = "label141"; + this.label141.Size = new System.Drawing.Size(39, 13); + this.label141.TabIndex = 17; + this.label141.Text = "Group:"; + // + // ScenarioClusterPointInteriorHashLabel + // + this.ScenarioClusterPointInteriorHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointInteriorHashLabel.AutoSize = true; + this.ScenarioClusterPointInteriorHashLabel.Location = new System.Drawing.Point(341, 100); + this.ScenarioClusterPointInteriorHashLabel.Name = "ScenarioClusterPointInteriorHashLabel"; + this.ScenarioClusterPointInteriorHashLabel.Size = new System.Drawing.Size(44, 13); + this.ScenarioClusterPointInteriorHashLabel.TabIndex = 16; + this.ScenarioClusterPointInteriorHashLabel.Text = "Hash: 0"; + // + // ScenarioClusterPointFlagsCheckedListBox + // + this.ScenarioClusterPointFlagsCheckedListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointFlagsCheckedListBox.CheckOnClick = true; + this.ScenarioClusterPointFlagsCheckedListBox.FormattingEnabled = true; + this.ScenarioClusterPointFlagsCheckedListBox.Items.AddRange(new object[] { + "1 - IgnoreMaxInRange", + "2 - NoSpawn", + "4 - StationaryReactions", + "8 - Unk", + "16 - Unk", + "32 - ActivateVehicleSiren", + "64 - Unk", + "128 - Unk", + "256 - Unk", + "512 - Unk", + "1024 - AerialVehiclePoint", + "2048 - TerritorialScenario", + "4096 - Unk", + "8192 - Unk", + "16384 - Unk", + "32768 - Unk", + "65536 - InWater", + "131072 - Unk", + "262144 - OpenDoor", + "524288 - PreciseUseTime", + "1048576 - Unk", + "2097152 - Unk", + "4194304 - ExtendedRange", + "8388608 - ShortRange", + "16777216 - HighPriority", + "33554432 - IgnoreLoitering", + "67108864 - Unk", + "134217728 - ResetNoCollisionOnCleanUp", + "268435456 - Unk", + "536870912 - Unk", + "1073741824 - Unk"}); + this.ScenarioClusterPointFlagsCheckedListBox.Location = new System.Drawing.Point(195, 167); + this.ScenarioClusterPointFlagsCheckedListBox.Name = "ScenarioClusterPointFlagsCheckedListBox"; + this.ScenarioClusterPointFlagsCheckedListBox.Size = new System.Drawing.Size(214, 244); + this.ScenarioClusterPointFlagsCheckedListBox.TabIndex = 37; + this.ScenarioClusterPointFlagsCheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.ScenarioClusterPointFlagsCheckedListBox_ItemCheck); + // + // label142 + // + this.label142.AutoSize = true; + this.label142.Location = new System.Drawing.Point(32, 390); + this.label142.Name = "label142"; + this.label142.Size = new System.Drawing.Size(35, 13); + this.label142.TabIndex = 35; + this.label142.Text = "Flags:"; + // + // ScenarioClusterPointDirectionTextBox + // + this.ScenarioClusterPointDirectionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointDirectionTextBox.Location = new System.Drawing.Point(73, 26); + this.ScenarioClusterPointDirectionTextBox.Name = "ScenarioClusterPointDirectionTextBox"; + this.ScenarioClusterPointDirectionTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioClusterPointDirectionTextBox.TabIndex = 9; + this.ScenarioClusterPointDirectionTextBox.TextChanged += new System.EventHandler(this.ScenarioClusterPointDirectionTextBox_TextChanged); + // + // label144 + // + this.label144.AutoSize = true; + this.label144.Location = new System.Drawing.Point(15, 29); + this.label144.Name = "label144"; + this.label144.Size = new System.Drawing.Size(52, 13); + this.label144.TabIndex = 8; + this.label144.Text = "Direction:"; + // + // ScenarioClusterPointFlagsUpDown + // + this.ScenarioClusterPointFlagsUpDown.Location = new System.Drawing.Point(73, 388); + this.ScenarioClusterPointFlagsUpDown.Maximum = new decimal(new int[] { + -1, + 0, + 0, + 0}); + this.ScenarioClusterPointFlagsUpDown.Name = "ScenarioClusterPointFlagsUpDown"; + this.ScenarioClusterPointFlagsUpDown.Size = new System.Drawing.Size(116, 20); + this.ScenarioClusterPointFlagsUpDown.TabIndex = 36; + this.ScenarioClusterPointFlagsUpDown.ValueChanged += new System.EventHandler(this.ScenarioClusterPointFlagsUpDown_ValueChanged); + // + // label145 + // + this.label145.AutoSize = true; + this.label145.Location = new System.Drawing.Point(13, 299); + this.label145.Name = "label145"; + this.label145.Size = new System.Drawing.Size(54, 13); + this.label145.TabIndex = 33; + this.label145.Text = "Wait time:"; + // + // ScenarioClusterPointGoToButton + // + this.ScenarioClusterPointGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointGoToButton.Location = new System.Drawing.Point(341, 1); + this.ScenarioClusterPointGoToButton.Name = "ScenarioClusterPointGoToButton"; + this.ScenarioClusterPointGoToButton.Size = new System.Drawing.Size(68, 23); + this.ScenarioClusterPointGoToButton.TabIndex = 7; + this.ScenarioClusterPointGoToButton.Text = "Go to"; + this.ScenarioClusterPointGoToButton.UseVisualStyleBackColor = true; + this.ScenarioClusterPointGoToButton.Click += new System.EventHandler(this.ScenarioClusterPointGoToButton_Click); + // + // ScenarioClusterPointWaitTimeUpDown + // + this.ScenarioClusterPointWaitTimeUpDown.Location = new System.Drawing.Point(73, 297); + this.ScenarioClusterPointWaitTimeUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioClusterPointWaitTimeUpDown.Name = "ScenarioClusterPointWaitTimeUpDown"; + this.ScenarioClusterPointWaitTimeUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioClusterPointWaitTimeUpDown.TabIndex = 34; + this.ScenarioClusterPointWaitTimeUpDown.ValueChanged += new System.EventHandler(this.ScenarioClusterPointWaitTimeUpDown_ValueChanged); + // + // ScenarioClusterPointPositionTextBox + // + this.ScenarioClusterPointPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointPositionTextBox.Location = new System.Drawing.Point(73, 3); + this.ScenarioClusterPointPositionTextBox.Name = "ScenarioClusterPointPositionTextBox"; + this.ScenarioClusterPointPositionTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioClusterPointPositionTextBox.TabIndex = 6; + this.ScenarioClusterPointPositionTextBox.TextChanged += new System.EventHandler(this.ScenarioClusterPointPositionTextBox_TextChanged); + // + // label146 + // + this.label146.AutoSize = true; + this.label146.Location = new System.Drawing.Point(20, 6); + this.label146.Name = "label146"; + this.label146.Size = new System.Drawing.Size(47, 13); + this.label146.TabIndex = 5; + this.label146.Text = "Position:"; + // + // label147 + // + this.label147.AutoSize = true; + this.label147.Location = new System.Drawing.Point(24, 273); + this.label147.Name = "label147"; + this.label147.Size = new System.Drawing.Size(43, 13); + this.label147.TabIndex = 31; + this.label147.Text = "Radius:"; + // + // ScenarioClusterPointRadiusUpDown + // + this.ScenarioClusterPointRadiusUpDown.Location = new System.Drawing.Point(73, 271); + this.ScenarioClusterPointRadiusUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioClusterPointRadiusUpDown.Name = "ScenarioClusterPointRadiusUpDown"; + this.ScenarioClusterPointRadiusUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioClusterPointRadiusUpDown.TabIndex = 32; + this.ScenarioClusterPointRadiusUpDown.ValueChanged += new System.EventHandler(this.ScenarioClusterPointRadiusUpDown_ValueChanged); + // + // label148 + // + this.label148.AutoSize = true; + this.label148.Location = new System.Drawing.Point(6, 247); + this.label148.Name = "label148"; + this.label148.Size = new System.Drawing.Size(61, 13); + this.label148.TabIndex = 29; + this.label148.Text = "Animal flag:"; + // + // ScenarioClusterPointAnimalFlagUpDown + // + this.ScenarioClusterPointAnimalFlagUpDown.Location = new System.Drawing.Point(73, 245); + this.ScenarioClusterPointAnimalFlagUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioClusterPointAnimalFlagUpDown.Name = "ScenarioClusterPointAnimalFlagUpDown"; + this.ScenarioClusterPointAnimalFlagUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioClusterPointAnimalFlagUpDown.TabIndex = 30; + this.ScenarioClusterPointAnimalFlagUpDown.ValueChanged += new System.EventHandler(this.ScenarioClusterPointAnimalFlagUpDown_ValueChanged); + // + // label149 + // + this.label149.AutoSize = true; + this.label149.Location = new System.Drawing.Point(9, 221); + this.label149.Name = "label149"; + this.label149.Size = new System.Drawing.Size(58, 13); + this.label149.TabIndex = 27; + this.label149.Text = "Probability:"; + // + // ScenarioClusterPointProbabilityUpDown + // + this.ScenarioClusterPointProbabilityUpDown.Location = new System.Drawing.Point(73, 219); + this.ScenarioClusterPointProbabilityUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.ScenarioClusterPointProbabilityUpDown.Name = "ScenarioClusterPointProbabilityUpDown"; + this.ScenarioClusterPointProbabilityUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioClusterPointProbabilityUpDown.TabIndex = 28; + this.ScenarioClusterPointProbabilityUpDown.ValueChanged += new System.EventHandler(this.ScenarioClusterPointProbabilityUpDown_ValueChanged); + // + // ScenarioClusterPointInteriorTextBox + // + this.ScenarioClusterPointInteriorTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointInteriorTextBox.Location = new System.Drawing.Point(73, 97); + this.ScenarioClusterPointInteriorTextBox.Name = "ScenarioClusterPointInteriorTextBox"; + this.ScenarioClusterPointInteriorTextBox.Size = new System.Drawing.Size(262, 20); + this.ScenarioClusterPointInteriorTextBox.TabIndex = 15; + this.ScenarioClusterPointInteriorTextBox.TextChanged += new System.EventHandler(this.ScenarioClusterPointInteriorTextBox_TextChanged); + // + // label151 + // + this.label151.AutoSize = true; + this.label151.Location = new System.Drawing.Point(25, 100); + this.label151.Name = "label151"; + this.label151.Size = new System.Drawing.Size(42, 13); + this.label151.TabIndex = 14; + this.label151.Text = "Interior:"; + // + // label152 + // + this.label152.AutoSize = true; + this.label152.Location = new System.Drawing.Point(13, 195); + this.label152.Name = "label152"; + this.label152.Size = new System.Drawing.Size(54, 13); + this.label152.TabIndex = 25; + this.label152.Text = "Time end:"; + // + // ScenarioClusterPointTimeEndUpDown + // + this.ScenarioClusterPointTimeEndUpDown.Location = new System.Drawing.Point(73, 193); + this.ScenarioClusterPointTimeEndUpDown.Maximum = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.ScenarioClusterPointTimeEndUpDown.Name = "ScenarioClusterPointTimeEndUpDown"; + this.ScenarioClusterPointTimeEndUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioClusterPointTimeEndUpDown.TabIndex = 26; + this.ScenarioClusterPointTimeEndUpDown.ValueChanged += new System.EventHandler(this.ScenarioClusterPointTimeEndUpDown_ValueChanged); + // + // ScenarioClusterPointTimeStartUpDown + // + this.ScenarioClusterPointTimeStartUpDown.Location = new System.Drawing.Point(73, 167); + this.ScenarioClusterPointTimeStartUpDown.Maximum = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.ScenarioClusterPointTimeStartUpDown.Name = "ScenarioClusterPointTimeStartUpDown"; + this.ScenarioClusterPointTimeStartUpDown.Size = new System.Drawing.Size(57, 20); + this.ScenarioClusterPointTimeStartUpDown.TabIndex = 24; + this.ScenarioClusterPointTimeStartUpDown.ValueChanged += new System.EventHandler(this.ScenarioClusterPointTimeStartUpDown_ValueChanged); + // + // label153 + // + this.label153.AutoSize = true; + this.label153.Location = new System.Drawing.Point(11, 169); + this.label153.Name = "label153"; + this.label153.Size = new System.Drawing.Size(56, 13); + this.label153.TabIndex = 23; + this.label153.Text = "Time start:"; + // + // ScenarioClusterPointModelSetComboBox + // + this.ScenarioClusterPointModelSetComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointModelSetComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioClusterPointModelSetComboBox.FormattingEnabled = true; + this.ScenarioClusterPointModelSetComboBox.Location = new System.Drawing.Point(73, 73); + this.ScenarioClusterPointModelSetComboBox.Name = "ScenarioClusterPointModelSetComboBox"; + this.ScenarioClusterPointModelSetComboBox.Size = new System.Drawing.Size(336, 21); + this.ScenarioClusterPointModelSetComboBox.TabIndex = 13; + this.ScenarioClusterPointModelSetComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioClusterPointModelSetComboBox_SelectedIndexChanged); + // + // label154 + // + this.label154.AutoSize = true; + this.label154.Location = new System.Drawing.Point(9, 76); + this.label154.Name = "label154"; + this.label154.Size = new System.Drawing.Size(58, 13); + this.label154.TabIndex = 12; + this.label154.Text = "Model Set:"; + // + // ScenarioClusterPointTypeComboBox + // + this.ScenarioClusterPointTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ScenarioClusterPointTypeComboBox.FormattingEnabled = true; + this.ScenarioClusterPointTypeComboBox.Location = new System.Drawing.Point(73, 49); + this.ScenarioClusterPointTypeComboBox.Name = "ScenarioClusterPointTypeComboBox"; + this.ScenarioClusterPointTypeComboBox.Size = new System.Drawing.Size(336, 21); + this.ScenarioClusterPointTypeComboBox.TabIndex = 11; + this.ScenarioClusterPointTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.ScenarioClusterPointTypeComboBox_SelectedIndexChanged); + // + // label155 + // + this.label155.AutoSize = true; + this.label155.Location = new System.Drawing.Point(33, 52); + this.label155.Name = "label155"; + this.label155.Size = new System.Drawing.Size(34, 13); + this.label155.TabIndex = 10; + this.label155.Text = "Type:"; + // + // ScenarioClusterPointCheckBox + // + this.ScenarioClusterPointCheckBox.AutoSize = true; + this.ScenarioClusterPointCheckBox.Location = new System.Drawing.Point(6, 6); + this.ScenarioClusterPointCheckBox.Name = "ScenarioClusterPointCheckBox"; + this.ScenarioClusterPointCheckBox.Size = new System.Drawing.Size(119, 17); + this.ScenarioClusterPointCheckBox.TabIndex = 5; + this.ScenarioClusterPointCheckBox.Text = "Define Cluster Point"; + this.ScenarioClusterPointCheckBox.UseVisualStyleBackColor = true; + this.ScenarioClusterPointCheckBox.CheckedChanged += new System.EventHandler(this.ScenarioClusterPointCheckBox_CheckedChanged); + // + // TopMenuStrip + // + this.TopMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileMenu, + this.YmapMenu, + this.YndMenu, + this.YnvMenu, + this.TrainsMenu, + this.ScenarioMenu}); + this.TopMenuStrip.Location = new System.Drawing.Point(0, 0); + this.TopMenuStrip.Name = "TopMenuStrip"; + this.TopMenuStrip.Size = new System.Drawing.Size(776, 24); + this.TopMenuStrip.TabIndex = 1; + this.TopMenuStrip.Text = "menuStrip1"; + // + // FileMenu + // + this.FileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileNewMenu, + this.FileOpenMenu, + this.toolStripSeparator1, + this.FileCloseProjectMenu, + this.toolStripSeparator2, + this.FileSaveProjectMenu, + this.FileSaveProjectAsMenu, + this.FileSaveItemMenu, + this.FileSaveItemAsMenu}); + this.FileMenu.Name = "FileMenu"; + this.FileMenu.Size = new System.Drawing.Size(37, 20); + this.FileMenu.Text = "File"; + // + // FileNewMenu + // + this.FileNewMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileNewProjectMenu, + this.FileNewYmapMenu, + this.FileNewYndMenu, + this.FileNewYnvMenu, + this.FileNewTrainsMenu, + this.FileNewScenarioMenu}); + this.FileNewMenu.Name = "FileNewMenu"; + this.FileNewMenu.Size = new System.Drawing.Size(163, 22); + this.FileNewMenu.Text = "New"; + // + // FileNewProjectMenu + // + this.FileNewProjectMenu.Name = "FileNewProjectMenu"; + this.FileNewProjectMenu.Size = new System.Drawing.Size(138, 22); + this.FileNewProjectMenu.Text = "Project..."; + this.FileNewProjectMenu.Click += new System.EventHandler(this.FileNewProjectMenu_Click); + // + // FileNewYmapMenu + // + this.FileNewYmapMenu.Name = "FileNewYmapMenu"; + this.FileNewYmapMenu.Size = new System.Drawing.Size(138, 22); + this.FileNewYmapMenu.Text = "Ymap file"; + this.FileNewYmapMenu.Click += new System.EventHandler(this.FileNewYmapMenu_Click); + // + // FileNewYndMenu + // + this.FileNewYndMenu.Name = "FileNewYndMenu"; + this.FileNewYndMenu.Size = new System.Drawing.Size(138, 22); + this.FileNewYndMenu.Text = "Ynd file"; + this.FileNewYndMenu.Click += new System.EventHandler(this.FileNewYndMenu_Click); + // + // FileNewYnvMenu + // + this.FileNewYnvMenu.Name = "FileNewYnvMenu"; + this.FileNewYnvMenu.Size = new System.Drawing.Size(138, 22); + this.FileNewYnvMenu.Text = "Ynv file"; + this.FileNewYnvMenu.Visible = false; + this.FileNewYnvMenu.Click += new System.EventHandler(this.FileNewYnvMenu_Click); + // + // FileNewTrainsMenu + // + this.FileNewTrainsMenu.Name = "FileNewTrainsMenu"; + this.FileNewTrainsMenu.Size = new System.Drawing.Size(138, 22); + this.FileNewTrainsMenu.Text = "Trains file"; + this.FileNewTrainsMenu.Click += new System.EventHandler(this.FileNewTrainsMenu_Click); + // + // FileNewScenarioMenu + // + this.FileNewScenarioMenu.Name = "FileNewScenarioMenu"; + this.FileNewScenarioMenu.Size = new System.Drawing.Size(138, 22); + this.FileNewScenarioMenu.Text = "Scenario file"; + this.FileNewScenarioMenu.Click += new System.EventHandler(this.FileNewScenarioMenu_Click); + // + // FileOpenMenu + // + this.FileOpenMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileOpenProjectMenu, + this.FileOpenYmapMenu, + this.FileOpenYndMenu, + this.FileOpenYnvMenu, + this.FileOpenTrainsMenu, + this.FileOpenScenarioMenu}); + this.FileOpenMenu.Name = "FileOpenMenu"; + this.FileOpenMenu.Size = new System.Drawing.Size(163, 22); + this.FileOpenMenu.Text = "Open"; + // + // FileOpenProjectMenu + // + this.FileOpenProjectMenu.Name = "FileOpenProjectMenu"; + this.FileOpenProjectMenu.Size = new System.Drawing.Size(147, 22); + this.FileOpenProjectMenu.Text = "Project..."; + this.FileOpenProjectMenu.Click += new System.EventHandler(this.FileOpenProjectMenu_Click); + // + // FileOpenYmapMenu + // + this.FileOpenYmapMenu.Name = "FileOpenYmapMenu"; + this.FileOpenYmapMenu.Size = new System.Drawing.Size(147, 22); + this.FileOpenYmapMenu.Text = "Ymap file..."; + this.FileOpenYmapMenu.Click += new System.EventHandler(this.FileOpenYmapMenu_Click); + // + // FileOpenYndMenu + // + this.FileOpenYndMenu.Name = "FileOpenYndMenu"; + this.FileOpenYndMenu.Size = new System.Drawing.Size(147, 22); + this.FileOpenYndMenu.Text = "Ynd file..."; + this.FileOpenYndMenu.Click += new System.EventHandler(this.FileOpenYndMenu_Click); + // + // FileOpenYnvMenu + // + this.FileOpenYnvMenu.Name = "FileOpenYnvMenu"; + this.FileOpenYnvMenu.Size = new System.Drawing.Size(147, 22); + this.FileOpenYnvMenu.Text = "Ynv file..."; + this.FileOpenYnvMenu.Visible = false; + this.FileOpenYnvMenu.Click += new System.EventHandler(this.FileOpenYnvMenu_Click); + // + // FileOpenTrainsMenu + // + this.FileOpenTrainsMenu.Name = "FileOpenTrainsMenu"; + this.FileOpenTrainsMenu.Size = new System.Drawing.Size(147, 22); + this.FileOpenTrainsMenu.Text = "Trains file..."; + this.FileOpenTrainsMenu.Click += new System.EventHandler(this.FileOpenTrainsMenu_Click); + // + // FileOpenScenarioMenu + // + this.FileOpenScenarioMenu.Name = "FileOpenScenarioMenu"; + this.FileOpenScenarioMenu.Size = new System.Drawing.Size(147, 22); + this.FileOpenScenarioMenu.Text = "Scenario file..."; + this.FileOpenScenarioMenu.Click += new System.EventHandler(this.FileOpenScenarioMenu_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(160, 6); + // + // FileCloseProjectMenu + // + this.FileCloseProjectMenu.Enabled = false; + this.FileCloseProjectMenu.Name = "FileCloseProjectMenu"; + this.FileCloseProjectMenu.Size = new System.Drawing.Size(163, 22); + this.FileCloseProjectMenu.Text = "Close Project"; + this.FileCloseProjectMenu.Click += new System.EventHandler(this.FileCloseProjectMenu_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(160, 6); + // + // FileSaveProjectMenu + // + this.FileSaveProjectMenu.Enabled = false; + this.FileSaveProjectMenu.Name = "FileSaveProjectMenu"; + this.FileSaveProjectMenu.Size = new System.Drawing.Size(163, 22); + this.FileSaveProjectMenu.Text = "Save Project"; + this.FileSaveProjectMenu.Click += new System.EventHandler(this.FileSaveProjectMenu_Click); + // + // FileSaveProjectAsMenu + // + this.FileSaveProjectAsMenu.Enabled = false; + this.FileSaveProjectAsMenu.Name = "FileSaveProjectAsMenu"; + this.FileSaveProjectAsMenu.Size = new System.Drawing.Size(163, 22); + this.FileSaveProjectAsMenu.Text = "Save Project As..."; + this.FileSaveProjectAsMenu.Click += new System.EventHandler(this.FileSaveProjectAsMenu_Click); + // + // FileSaveItemMenu + // + this.FileSaveItemMenu.Enabled = false; + this.FileSaveItemMenu.Name = "FileSaveItemMenu"; + this.FileSaveItemMenu.Size = new System.Drawing.Size(163, 22); + this.FileSaveItemMenu.Text = "Save Item"; + this.FileSaveItemMenu.Visible = false; + this.FileSaveItemMenu.Click += new System.EventHandler(this.FileSaveItemMenu_Click); + // + // FileSaveItemAsMenu + // + this.FileSaveItemAsMenu.Enabled = false; + this.FileSaveItemAsMenu.Name = "FileSaveItemAsMenu"; + this.FileSaveItemAsMenu.Size = new System.Drawing.Size(163, 22); + this.FileSaveItemAsMenu.Text = "Save Item As..."; + this.FileSaveItemAsMenu.Visible = false; + this.FileSaveItemAsMenu.Click += new System.EventHandler(this.FileSaveItemAsMenu_Click); + // + // YmapMenu + // + this.YmapMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.YmapNameMenu, + this.toolStripSeparator3, + this.YmapNewEntityMenu, + this.YmapNewCarGenMenu, + this.toolStripSeparator5, + this.YmapAddToProjectMenu, + this.YmapRemoveFromProjectMenu}); + this.YmapMenu.Name = "YmapMenu"; + this.YmapMenu.Size = new System.Drawing.Size(49, 20); + this.YmapMenu.Text = "Ymap"; + // + // YmapNameMenu + // + this.YmapNameMenu.Enabled = false; + this.YmapNameMenu.Name = "YmapNameMenu"; + this.YmapNameMenu.Size = new System.Drawing.Size(199, 22); + this.YmapNameMenu.Text = "(No .ymap file selected)"; + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(196, 6); + // + // YmapNewEntityMenu + // + this.YmapNewEntityMenu.Enabled = false; + this.YmapNewEntityMenu.Name = "YmapNewEntityMenu"; + this.YmapNewEntityMenu.Size = new System.Drawing.Size(199, 22); + this.YmapNewEntityMenu.Text = "New Entity"; + this.YmapNewEntityMenu.Click += new System.EventHandler(this.YmapNewEntityMenu_Click); + // + // YmapNewCarGenMenu + // + this.YmapNewCarGenMenu.Enabled = false; + this.YmapNewCarGenMenu.Name = "YmapNewCarGenMenu"; + this.YmapNewCarGenMenu.Size = new System.Drawing.Size(199, 22); + this.YmapNewCarGenMenu.Text = "New Car Generator"; + this.YmapNewCarGenMenu.Click += new System.EventHandler(this.YmapNewCarGenMenu_Click); + // + // toolStripSeparator5 + // + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new System.Drawing.Size(196, 6); + // + // YmapAddToProjectMenu + // + this.YmapAddToProjectMenu.Enabled = false; + this.YmapAddToProjectMenu.Name = "YmapAddToProjectMenu"; + this.YmapAddToProjectMenu.Size = new System.Drawing.Size(199, 22); + this.YmapAddToProjectMenu.Text = "Add to Project"; + this.YmapAddToProjectMenu.Click += new System.EventHandler(this.YmapAddToProjectMenu_Click); + // + // YmapRemoveFromProjectMenu + // + this.YmapRemoveFromProjectMenu.Enabled = false; + this.YmapRemoveFromProjectMenu.Name = "YmapRemoveFromProjectMenu"; + this.YmapRemoveFromProjectMenu.Size = new System.Drawing.Size(199, 22); + this.YmapRemoveFromProjectMenu.Text = "Remove from Project"; + this.YmapRemoveFromProjectMenu.Click += new System.EventHandler(this.YmapRemoveFromProjectMenu_Click); + // + // YndMenu + // + this.YndMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.YndNameMenu, + this.toolStripSeparator4, + this.YndNewNodeMenu, + this.toolStripSeparator6, + this.YndAddToProjectMenu, + this.YndRemoveFromProjectMenu}); + this.YndMenu.Name = "YndMenu"; + this.YndMenu.Size = new System.Drawing.Size(39, 20); + this.YndMenu.Text = "Ynd"; + // + // YndNameMenu + // + this.YndNameMenu.Enabled = false; + this.YndNameMenu.Name = "YndNameMenu"; + this.YndNameMenu.Size = new System.Drawing.Size(189, 22); + this.YndNameMenu.Text = "(No .ynd file selected)"; + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(186, 6); + // + // YndNewNodeMenu + // + this.YndNewNodeMenu.Enabled = false; + this.YndNewNodeMenu.Name = "YndNewNodeMenu"; + this.YndNewNodeMenu.Size = new System.Drawing.Size(189, 22); + this.YndNewNodeMenu.Text = "New Node"; + this.YndNewNodeMenu.Click += new System.EventHandler(this.YndNewNodeMenu_Click); + // + // toolStripSeparator6 + // + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new System.Drawing.Size(186, 6); + // + // YndAddToProjectMenu + // + this.YndAddToProjectMenu.Enabled = false; + this.YndAddToProjectMenu.Name = "YndAddToProjectMenu"; + this.YndAddToProjectMenu.Size = new System.Drawing.Size(189, 22); + this.YndAddToProjectMenu.Text = "Add to Project"; + this.YndAddToProjectMenu.Click += new System.EventHandler(this.YndAddToProjectMenu_Click); + // + // YndRemoveFromProjectMenu + // + this.YndRemoveFromProjectMenu.Enabled = false; + this.YndRemoveFromProjectMenu.Name = "YndRemoveFromProjectMenu"; + this.YndRemoveFromProjectMenu.Size = new System.Drawing.Size(189, 22); + this.YndRemoveFromProjectMenu.Text = "Remove from Project"; + this.YndRemoveFromProjectMenu.Click += new System.EventHandler(this.YndRemoveFromProjectMenu_Click); + // + // YnvMenu + // + this.YnvMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.YnvNameMenu, + this.toolStripSeparator9, + this.YnvNewPolygonMenu, + this.toolStripSeparator10, + this.YnvAddToProjectMenu, + this.YnvRemoveFromProjectMenu}); + this.YnvMenu.Name = "YnvMenu"; + this.YnvMenu.Size = new System.Drawing.Size(38, 20); + this.YnvMenu.Text = "Ynv"; + this.YnvMenu.Visible = false; + // + // YnvNameMenu + // + this.YnvNameMenu.Enabled = false; + this.YnvNameMenu.Name = "YnvNameMenu"; + this.YnvNameMenu.Size = new System.Drawing.Size(188, 22); + this.YnvNameMenu.Text = "(No .ynv file selected)"; + // + // toolStripSeparator9 + // + this.toolStripSeparator9.Name = "toolStripSeparator9"; + this.toolStripSeparator9.Size = new System.Drawing.Size(185, 6); + // + // YnvNewPolygonMenu + // + this.YnvNewPolygonMenu.Enabled = false; + this.YnvNewPolygonMenu.Name = "YnvNewPolygonMenu"; + this.YnvNewPolygonMenu.Size = new System.Drawing.Size(188, 22); + this.YnvNewPolygonMenu.Text = "New Polygon"; + this.YnvNewPolygonMenu.Click += new System.EventHandler(this.YnvNewPolygonMenu_Click); + // + // toolStripSeparator10 + // + this.toolStripSeparator10.Name = "toolStripSeparator10"; + this.toolStripSeparator10.Size = new System.Drawing.Size(185, 6); + // + // YnvAddToProjectMenu + // + this.YnvAddToProjectMenu.Enabled = false; + this.YnvAddToProjectMenu.Name = "YnvAddToProjectMenu"; + this.YnvAddToProjectMenu.Size = new System.Drawing.Size(188, 22); + this.YnvAddToProjectMenu.Text = "Add to Project"; + this.YnvAddToProjectMenu.Click += new System.EventHandler(this.YnvAddToProjectMenu_Click); + // + // YnvRemoveFromProjectMenu + // + this.YnvRemoveFromProjectMenu.Enabled = false; + this.YnvRemoveFromProjectMenu.Name = "YnvRemoveFromProjectMenu"; + this.YnvRemoveFromProjectMenu.Size = new System.Drawing.Size(188, 22); + this.YnvRemoveFromProjectMenu.Text = "Remove from Project"; + this.YnvRemoveFromProjectMenu.Click += new System.EventHandler(this.YnvRemoveFromProjectMenu_Click); + // + // TrainsMenu + // + this.TrainsMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.TrainsNameMenu, + this.toolStripSeparator7, + this.TrainsNewNodeMenu, + this.toolStripSeparator8, + this.TrainsAddToProjectMenu, + this.TrainsRemoveFromProjectMenu}); + this.TrainsMenu.Name = "TrainsMenu"; + this.TrainsMenu.Size = new System.Drawing.Size(50, 20); + this.TrainsMenu.Text = "Trains"; + // + // TrainsNameMenu + // + this.TrainsNameMenu.Enabled = false; + this.TrainsNameMenu.Name = "TrainsNameMenu"; + this.TrainsNameMenu.Size = new System.Drawing.Size(200, 22); + this.TrainsNameMenu.Text = "(No train track selected)"; + // + // toolStripSeparator7 + // + this.toolStripSeparator7.Name = "toolStripSeparator7"; + this.toolStripSeparator7.Size = new System.Drawing.Size(197, 6); + // + // TrainsNewNodeMenu + // + this.TrainsNewNodeMenu.Enabled = false; + this.TrainsNewNodeMenu.Name = "TrainsNewNodeMenu"; + this.TrainsNewNodeMenu.Size = new System.Drawing.Size(200, 22); + this.TrainsNewNodeMenu.Text = "New Node"; + this.TrainsNewNodeMenu.Click += new System.EventHandler(this.TrainsNewNodeMenu_Click); + // + // toolStripSeparator8 + // + this.toolStripSeparator8.Name = "toolStripSeparator8"; + this.toolStripSeparator8.Size = new System.Drawing.Size(197, 6); + // + // TrainsAddToProjectMenu + // + this.TrainsAddToProjectMenu.Enabled = false; + this.TrainsAddToProjectMenu.Name = "TrainsAddToProjectMenu"; + this.TrainsAddToProjectMenu.Size = new System.Drawing.Size(200, 22); + this.TrainsAddToProjectMenu.Text = "Add to Project"; + this.TrainsAddToProjectMenu.Click += new System.EventHandler(this.TrainsAddToProjectMenu_Click); + // + // TrainsRemoveFromProjectMenu + // + this.TrainsRemoveFromProjectMenu.Enabled = false; + this.TrainsRemoveFromProjectMenu.Name = "TrainsRemoveFromProjectMenu"; + this.TrainsRemoveFromProjectMenu.Size = new System.Drawing.Size(200, 22); + this.TrainsRemoveFromProjectMenu.Text = "Remove from Project"; + this.TrainsRemoveFromProjectMenu.Click += new System.EventHandler(this.TrainsRemoveFromProjectMenu_Click); + // + // ScenarioMenu + // + this.ScenarioMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ScenarioNameMenu, + this.toolStripSeparator11, + this.ScenarioNewPointMenu, + this.ScenarioNewPointFromSelectedMenu, + this.ScenarioNewEntityOverrideMenu, + this.ScenarioNewChainMenu, + this.ScenarioNewClusterMenu, + this.toolStripSeparator12, + this.ScenarioAddToProjectMenu, + this.ScenarioRemoveFromProjectMenu}); + this.ScenarioMenu.Name = "ScenarioMenu"; + this.ScenarioMenu.Size = new System.Drawing.Size(64, 20); + this.ScenarioMenu.Text = "Scenario"; + // + // ScenarioNameMenu + // + this.ScenarioNameMenu.Enabled = false; + this.ScenarioNameMenu.Name = "ScenarioNameMenu"; + this.ScenarioNameMenu.Size = new System.Drawing.Size(228, 22); + this.ScenarioNameMenu.Text = "(No scenario region selected)"; + // + // toolStripSeparator11 + // + this.toolStripSeparator11.Name = "toolStripSeparator11"; + this.toolStripSeparator11.Size = new System.Drawing.Size(225, 6); + // + // ScenarioNewPointMenu + // + this.ScenarioNewPointMenu.Enabled = false; + this.ScenarioNewPointMenu.Name = "ScenarioNewPointMenu"; + this.ScenarioNewPointMenu.Size = new System.Drawing.Size(228, 22); + this.ScenarioNewPointMenu.Text = "New Point (Blank)"; + this.ScenarioNewPointMenu.Click += new System.EventHandler(this.ScenarioNewPointMenu_Click); + // + // ScenarioNewPointFromSelectedMenu + // + this.ScenarioNewPointFromSelectedMenu.Enabled = false; + this.ScenarioNewPointFromSelectedMenu.Name = "ScenarioNewPointFromSelectedMenu"; + this.ScenarioNewPointFromSelectedMenu.Size = new System.Drawing.Size(228, 22); + this.ScenarioNewPointFromSelectedMenu.Text = "New Point (from Selected)"; + this.ScenarioNewPointFromSelectedMenu.Click += new System.EventHandler(this.ScenarioNewPointFromSelectedMenu_Click); + // + // ScenarioNewEntityOverrideMenu + // + this.ScenarioNewEntityOverrideMenu.Enabled = false; + this.ScenarioNewEntityOverrideMenu.Name = "ScenarioNewEntityOverrideMenu"; + this.ScenarioNewEntityOverrideMenu.Size = new System.Drawing.Size(228, 22); + this.ScenarioNewEntityOverrideMenu.Text = "New Entity Override"; + this.ScenarioNewEntityOverrideMenu.Click += new System.EventHandler(this.ScenarioNewEntityOverrideMenu_Click); + // + // ScenarioNewChainMenu + // + this.ScenarioNewChainMenu.Enabled = false; + this.ScenarioNewChainMenu.Name = "ScenarioNewChainMenu"; + this.ScenarioNewChainMenu.Size = new System.Drawing.Size(228, 22); + this.ScenarioNewChainMenu.Text = "New Chain"; + this.ScenarioNewChainMenu.Click += new System.EventHandler(this.ScenarioNewChainMenu_Click); + // + // ScenarioNewClusterMenu + // + this.ScenarioNewClusterMenu.Enabled = false; + this.ScenarioNewClusterMenu.Name = "ScenarioNewClusterMenu"; + this.ScenarioNewClusterMenu.Size = new System.Drawing.Size(228, 22); + this.ScenarioNewClusterMenu.Text = "New Cluster"; + this.ScenarioNewClusterMenu.Click += new System.EventHandler(this.ScenarioNewClusterMenu_Click); + // + // toolStripSeparator12 + // + this.toolStripSeparator12.Name = "toolStripSeparator12"; + this.toolStripSeparator12.Size = new System.Drawing.Size(225, 6); + // + // ScenarioAddToProjectMenu + // + this.ScenarioAddToProjectMenu.Enabled = false; + this.ScenarioAddToProjectMenu.Name = "ScenarioAddToProjectMenu"; + this.ScenarioAddToProjectMenu.Size = new System.Drawing.Size(228, 22); + this.ScenarioAddToProjectMenu.Text = "Add to Project"; + this.ScenarioAddToProjectMenu.Click += new System.EventHandler(this.ScenarioAddToProjectMenu_Click); + // + // ScenarioRemoveFromProjectMenu + // + this.ScenarioRemoveFromProjectMenu.Enabled = false; + this.ScenarioRemoveFromProjectMenu.Name = "ScenarioRemoveFromProjectMenu"; + this.ScenarioRemoveFromProjectMenu.Size = new System.Drawing.Size(228, 22); + this.ScenarioRemoveFromProjectMenu.Text = "Remove from Project"; + this.ScenarioRemoveFromProjectMenu.Click += new System.EventHandler(this.ScenarioRemoveFromProjectMenu_Click); + // + // SaveFileDialog + // + this.SaveFileDialog.Filter = "CodeWalker Projects|*.cwproj"; + // + // OpenFileDialog + // + this.OpenFileDialog.Filter = "CodeWalker Projects|*.cwproj"; + // + // ScenarioClusterPointsListBox + // + this.ScenarioClusterPointsListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioClusterPointsListBox.FormattingEnabled = true; + this.ScenarioClusterPointsListBox.Location = new System.Drawing.Point(100, 148); + this.ScenarioClusterPointsListBox.Name = "ScenarioClusterPointsListBox"; + this.ScenarioClusterPointsListBox.Size = new System.Drawing.Size(235, 173); + this.ScenarioClusterPointsListBox.TabIndex = 13; + this.ScenarioClusterPointsListBox.DoubleClick += new System.EventHandler(this.ScenarioClusterPointsListBox_DoubleClick); + // + // label158 + // + this.label158.AutoSize = true; + this.label158.Location = new System.Drawing.Point(51, 150); + this.label158.Name = "label158"; + this.label158.Size = new System.Drawing.Size(39, 13); + this.label158.TabIndex = 14; + this.label158.Text = "Points:"; + // + // ScenarioClusterAddPointButton + // + this.ScenarioClusterAddPointButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ScenarioClusterAddPointButton.Location = new System.Drawing.Point(100, 337); + this.ScenarioClusterAddPointButton.Name = "ScenarioClusterAddPointButton"; + this.ScenarioClusterAddPointButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioClusterAddPointButton.TabIndex = 15; + this.ScenarioClusterAddPointButton.Text = "Add Point"; + this.ScenarioClusterAddPointButton.UseVisualStyleBackColor = true; + this.ScenarioClusterAddPointButton.Click += new System.EventHandler(this.ScenarioClusterAddPointButton_Click); + // + // label159 + // + this.label159.AutoSize = true; + this.label159.Location = new System.Drawing.Point(341, 150); + this.label159.Name = "label159"; + this.label159.Size = new System.Drawing.Size(141, 13); + this.label159.TabIndex = 16; + this.label159.Text = "(Double-click to select point)"; + // + // label160 + // + this.label160.AutoSize = true; + this.label160.Location = new System.Drawing.Point(332, 160); + this.label160.Name = "label160"; + this.label160.Size = new System.Drawing.Size(141, 13); + this.label160.TabIndex = 20; + this.label160.Text = "(Double-click to select point)"; + // + // ScenarioEntityAddPointButton + // + this.ScenarioEntityAddPointButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ScenarioEntityAddPointButton.Location = new System.Drawing.Point(91, 347); + this.ScenarioEntityAddPointButton.Name = "ScenarioEntityAddPointButton"; + this.ScenarioEntityAddPointButton.Size = new System.Drawing.Size(90, 23); + this.ScenarioEntityAddPointButton.TabIndex = 19; + this.ScenarioEntityAddPointButton.Text = "Add Point"; + this.ScenarioEntityAddPointButton.UseVisualStyleBackColor = true; + this.ScenarioEntityAddPointButton.Click += new System.EventHandler(this.ScenarioEntityAddPointButton_Click); + // + // label161 + // + this.label161.AutoSize = true; + this.label161.Location = new System.Drawing.Point(42, 160); + this.label161.Name = "label161"; + this.label161.Size = new System.Drawing.Size(39, 13); + this.label161.TabIndex = 18; + this.label161.Text = "Points:"; + // + // ScenarioEntityPointsListBox + // + this.ScenarioEntityPointsListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ScenarioEntityPointsListBox.FormattingEnabled = true; + this.ScenarioEntityPointsListBox.Location = new System.Drawing.Point(91, 158); + this.ScenarioEntityPointsListBox.Name = "ScenarioEntityPointsListBox"; + this.ScenarioEntityPointsListBox.Size = new System.Drawing.Size(235, 173); + this.ScenarioEntityPointsListBox.TabIndex = 17; + this.ScenarioEntityPointsListBox.DoubleClick += new System.EventHandler(this.ScenarioEntityPointsListBox_DoubleClick); + // + // ProjectForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(776, 531); + this.Controls.Add(this.splitContainer1); + this.Controls.Add(this.TopMenuStrip); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.TopMenuStrip; + this.Name = "ProjectForm"; + this.Text = "Project - CodeWalker by dexyfex"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ProjectForm_FormClosing); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ProjectForm_FormClosed); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.MainTabControl.ResumeLayout(false); + this.ProjectTabPage.ResumeLayout(false); + this.ProjectPanel.ResumeLayout(false); + this.ProjectPanel.PerformLayout(); + this.YmapTabPage.ResumeLayout(false); + this.YmapTabControl.ResumeLayout(false); + this.YmapYmapTabPage.ResumeLayout(false); + this.YmapPanel.ResumeLayout(false); + this.YmapPanel.PerformLayout(); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.tabPage2.PerformLayout(); + this.YmapEntityTabPage.ResumeLayout(false); + this.EntityPanel.ResumeLayout(false); + this.EntityTabControl.ResumeLayout(false); + this.EntityGeneralTabPage.ResumeLayout(false); + this.EntityGeneralTabPage.PerformLayout(); + this.EntityLodTabPage.ResumeLayout(false); + this.EntityLodTabPage.PerformLayout(); + this.EntityPivotTabPage.ResumeLayout(false); + this.EntityPivotTabPage.PerformLayout(); + this.YmapCarGenTabPage.ResumeLayout(false); + this.CarGenPanel.ResumeLayout(false); + this.CarGenPanel.PerformLayout(); + this.YndTabPage.ResumeLayout(false); + this.YndTabControl.ResumeLayout(false); + this.YndYndTabPage.ResumeLayout(false); + this.YndPanel.ResumeLayout(false); + this.YndPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.YndAreaIDYUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.YndAreaIDXUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.YndPedNodesUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.YndVehicleNodesUpDown)).EndInit(); + this.YndNodeTabPage.ResumeLayout(false); + this.YndNodePanel.ResumeLayout(false); + this.PathNodeTabControl.ResumeLayout(false); + this.PathNodePropertiesTabPage.ResumeLayout(false); + this.PathNodePropertiesTabPage.PerformLayout(); + this.PathNodeFlags5GroupBox.ResumeLayout(false); + this.PathNodeFlags5GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags5UpDown)).EndInit(); + this.PathNodeFlags4GroupBox.ResumeLayout(false); + this.PathNodeFlags4GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags42UpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags4UpDown)).EndInit(); + this.PathNodeFlags3GroupBox.ResumeLayout(false); + this.PathNodeFlags3GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags32UpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags3UpDown)).EndInit(); + this.PathNodeFlags2GroupBox.ResumeLayout(false); + this.PathNodeFlags2GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags2UpDown)).EndInit(); + this.PathNodeFlags1GroupBox.ResumeLayout(false); + this.PathNodeFlags1GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags1UpDown)).EndInit(); + this.PathNodeFlags0GroupBox.ResumeLayout(false); + this.PathNodeFlags0GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeFlags0UpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeAreaIDUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeNodeIDUpDown)).EndInit(); + this.PathNodeLinksTabPage.ResumeLayout(false); + this.splitContainer2.Panel1.ResumeLayout(false); + this.splitContainer2.Panel1.PerformLayout(); + this.splitContainer2.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); + this.splitContainer2.ResumeLayout(false); + this.PathNodeLinkPanel.ResumeLayout(false); + this.PathNodeLinkPanel.PerformLayout(); + this.PathLinkFlags2GroupBox.ResumeLayout(false); + this.PathLinkFlags2GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFwdLanesUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkBackLanesUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags2UpDown)).EndInit(); + this.PathLinkFlags1GroupBox.ResumeLayout(false); + this.PathLinkFlags1GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkOffsetSizeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags1UpDown)).EndInit(); + this.PathLinkFlags0GroupBox.ResumeLayout(false); + this.PathLinkFlags0GroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags04UpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags03UpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkFlags0UpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkLengthUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkNodeIDUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeLinkAreaIDUpDown)).EndInit(); + this.PathNodeJunctionTabPage.ResumeLayout(false); + this.PathNodeJunctionTabPage.PerformLayout(); + this.PathNodeJunctionPanel.ResumeLayout(false); + this.PathNodeJunctionPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionPosYUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionPosXUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionHeightmapDimYUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionHeightmapDimXUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionMinZUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PathNodeJunctionMaxZUpDown)).EndInit(); + this.YnvTabPage.ResumeLayout(false); + this.YnvTabControl.ResumeLayout(false); + this.YnvYnvTabPage.ResumeLayout(false); + this.YnvPanel.ResumeLayout(false); + this.YnvPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.YnvAreaIDYUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.YnvAreaIDXUpDown)).EndInit(); + this.YnvPolyTabPage.ResumeLayout(false); + this.YnvPortalTabPage.ResumeLayout(false); + this.TrainsTabPage.ResumeLayout(false); + this.TrainsTabControl.ResumeLayout(false); + this.TrainTrackTabPage.ResumeLayout(false); + this.TrainTrackFilePanel.ResumeLayout(false); + this.TrainTrackFilePanel.PerformLayout(); + this.TrainNodeTabPage.ResumeLayout(false); + this.TrainNodePanel.ResumeLayout(false); + this.TrainNodePanel.PerformLayout(); + this.ScenarioTabPage.ResumeLayout(false); + this.ScenarioTabControl.ResumeLayout(false); + this.ScenarioYmtTabPage.ResumeLayout(false); + this.ScenarioYmtPanel.ResumeLayout(false); + this.ScenarioYmtPanel.PerformLayout(); + this.ScenarioPointTabPage.ResumeLayout(false); + this.ScenarioPointOuterPanel.ResumeLayout(false); + this.ScenarioPointOuterPanel.PerformLayout(); + this.ScenarioPointPanel.ResumeLayout(false); + this.ScenarioPointPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointFlagsValueUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointWaitTimeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointRadiusUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointSpOnlyFlagUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointProbabilityUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointTimeEndUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioPointTimeStartUpDown)).EndInit(); + this.ScenarioEntityTabPage.ResumeLayout(false); + this.ScenarioEntityTabPage.PerformLayout(); + this.ScenarioEntityPanel.ResumeLayout(false); + this.ScenarioEntityPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityUnk2UpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityUnk1UpDown)).EndInit(); + this.ScenarioEntityPointTabPage.ResumeLayout(false); + this.ScenarioEntityPointTabPage.PerformLayout(); + this.ScenarioEntityPointPanel.ResumeLayout(false); + this.ScenarioEntityPointPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityPointFlagsUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityPointEndUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioEntityPointStartUpDown)).EndInit(); + this.ScenarioChainTabPage.ResumeLayout(false); + this.splitContainer3.Panel1.ResumeLayout(false); + this.splitContainer3.Panel1.PerformLayout(); + this.splitContainer3.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); + this.splitContainer3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioChainUnk1UpDown)).EndInit(); + this.ScenarioChainEdgePanel.ResumeLayout(false); + this.ScenarioChainEdgePanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioChainEdgeNodeIndexToUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioChainEdgeNodeIndexFromUpDown)).EndInit(); + this.ScenarioChainNodeTabPage.ResumeLayout(false); + this.ScenarioChainNodeTabPage.PerformLayout(); + this.ScenarioChainNodePanel.ResumeLayout(false); + this.ScenarioChainNodePanel.PerformLayout(); + this.ScenarioClusterTabPage.ResumeLayout(false); + this.ScenarioClusterTabPage.PerformLayout(); + this.ScenarioClusterPanel.ResumeLayout(false); + this.ScenarioClusterPanel.PerformLayout(); + this.ScenarioClusterPointTabPage.ResumeLayout(false); + this.ScenarioClusterPointTabPage.PerformLayout(); + this.ScenarioClusterPointPanel.ResumeLayout(false); + this.ScenarioClusterPointPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointFlagsUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointWaitTimeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointRadiusUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointAnimalFlagUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointProbabilityUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointTimeEndUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.ScenarioClusterPointTimeStartUpDown)).EndInit(); + this.TopMenuStrip.ResumeLayout(false); + this.TopMenuStrip.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.TreeView ProjectTreeView; + private CodeWalker.WinForms.MenuStripFix TopMenuStrip; + private System.Windows.Forms.ToolStripMenuItem FileMenu; + private System.Windows.Forms.ToolStripMenuItem FileNewMenu; + private System.Windows.Forms.ToolStripMenuItem FileNewProjectMenu; + private System.Windows.Forms.ToolStripMenuItem FileNewYmapMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenProjectMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenYmapMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem FileCloseProjectMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem FileSaveProjectMenu; + private System.Windows.Forms.ToolStripMenuItem FileSaveProjectAsMenu; + private System.Windows.Forms.SaveFileDialog SaveFileDialog; + private System.Windows.Forms.OpenFileDialog OpenFileDialog; + private System.Windows.Forms.TabControl MainTabControl; + private System.Windows.Forms.TabPage ProjectTabPage; + private System.Windows.Forms.TabPage YmapTabPage; + private System.Windows.Forms.Label ProjectVersionLabel; + private System.Windows.Forms.TextBox ProjectNameTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox YmapNameTextBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Panel YmapPanel; + private System.Windows.Forms.Panel ProjectPanel; + private System.Windows.Forms.TextBox YmapParentTextBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label YmapParentHashLabel; + private System.Windows.Forms.Label YmapNameHashLabel; + private System.Windows.Forms.TextBox YmapContentFlagsTextBox; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox YmapFlagsTextBox; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox YmapStreamingExtentsMaxTextBox; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.TextBox YmapStreamingExtentsMinTextBox; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TextBox YmapEntitiesExtentsMaxTextBox; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox YmapEntitiesExtentsMinTextBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.ToolStripMenuItem FileSaveItemMenu; + private System.Windows.Forms.ToolStripMenuItem FileSaveItemAsMenu; + private System.Windows.Forms.Label EntityArchetypeHashLabel; + private System.Windows.Forms.TextBox EntityArchetypeTextBox; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.TextBox EntityGuidTextBox; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.TextBox EntityFlagsTextBox; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.TextBox EntityRotationTextBox; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.TextBox EntityPositionTextBox; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.Panel EntityPanel; + private System.Windows.Forms.TextBox EntityScaleZTextBox; + private System.Windows.Forms.Label label19; + private System.Windows.Forms.TextBox EntityScaleXYTextBox; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.TextBox EntityParentIndexTextBox; + private System.Windows.Forms.Label label22; + private System.Windows.Forms.TextBox EntityChildLodDistTextBox; + private System.Windows.Forms.Label label21; + private System.Windows.Forms.TextBox EntityLodDistTextBox; + private System.Windows.Forms.ComboBox EntityLodLevelComboBox; + private System.Windows.Forms.Label label23; + private System.Windows.Forms.ComboBox EntityPriorityLevelComboBox; + private System.Windows.Forms.Label label24; + private System.Windows.Forms.Label label25; + private System.Windows.Forms.TextBox EntityNumChildrenTextBox; + private System.Windows.Forms.Label label26; + private System.Windows.Forms.TextBox EntityAOMultiplierTextBox; + private System.Windows.Forms.Label label28; + private System.Windows.Forms.TextBox EntityTintValueTextBox; + private System.Windows.Forms.Label label27; + private System.Windows.Forms.TextBox EntityArtificialAOTextBox; + private System.Windows.Forms.CheckBox ProjectShowEntitiesCheckBox; + private System.Windows.Forms.CheckBox ProjectHideMapCheckBox; + private System.Windows.Forms.Button EntityGoToButton; + private System.Windows.Forms.ToolStripMenuItem YmapMenu; + private System.Windows.Forms.ToolStripMenuItem YmapNewEntityMenu; + private System.Windows.Forms.ToolStripMenuItem YmapNameMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.Button YmapCalculateExtentsButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.ToolStripMenuItem YmapRemoveFromProjectMenu; + private System.Windows.Forms.Button EntityNormalizeRotationButton; + private System.Windows.Forms.TextBox YmapProjectPathTextBox; + private System.Windows.Forms.Label label30; + private System.Windows.Forms.TextBox YmapFileLocationTextBox; + private System.Windows.Forms.Label label29; + private System.Windows.Forms.Panel CarGenPanel; + private System.Windows.Forms.Button CarGoToButton; + private System.Windows.Forms.TextBox CarPositionTextBox; + private System.Windows.Forms.Label label31; + private System.Windows.Forms.TextBox CarModelTextBox; + private System.Windows.Forms.Label label32; + private System.Windows.Forms.Label CarModelHashLabel; + private System.Windows.Forms.TextBox CarOrientYTextBox; + private System.Windows.Forms.Label label34; + private System.Windows.Forms.TextBox CarOrientXTextBox; + private System.Windows.Forms.Label label35; + private System.Windows.Forms.TextBox CarPerpendicularLengthTextBox; + private System.Windows.Forms.Label label36; + private System.Windows.Forms.Label label37; + private System.Windows.Forms.TextBox CarFlagsTextBox; + private System.Windows.Forms.Label label38; + private System.Windows.Forms.TextBox CarBodyColorRemap1TextBox; + private System.Windows.Forms.Label label43; + private System.Windows.Forms.TextBox CarBodyColorRemap4TextBox; + private System.Windows.Forms.Label label42; + private System.Windows.Forms.TextBox CarBodyColorRemap3TextBox; + private System.Windows.Forms.Label label41; + private System.Windows.Forms.TextBox CarBodyColorRemap2TextBox; + private System.Windows.Forms.TextBox CarPopGroupTextBox; + private System.Windows.Forms.Label label39; + private System.Windows.Forms.Label CarPopGroupHashLabel; + private System.Windows.Forms.Label label44; + private System.Windows.Forms.TextBox CarLiveryTextBox; + private System.Windows.Forms.Button EntityDeleteButton; + private System.Windows.Forms.Button EntityAddToProjectButton; + private System.Windows.Forms.ToolStripMenuItem YmapNewCarGenMenu; + private System.Windows.Forms.ToolStripMenuItem YmapAddToProjectMenu; + private System.Windows.Forms.Button CarDeleteButton; + private System.Windows.Forms.Button CarAddToProjectButton; + private System.Windows.Forms.TabControl YmapTabControl; + private System.Windows.Forms.TabPage YmapYmapTabPage; + private System.Windows.Forms.TabPage YmapEntityTabPage; + private System.Windows.Forms.TabPage YmapCarGenTabPage; + private System.Windows.Forms.TabPage YndTabPage; + private System.Windows.Forms.Panel YndPanel; + private System.Windows.Forms.TextBox YndRpfPathTextBox; + private System.Windows.Forms.TabControl YndTabControl; + private System.Windows.Forms.TabPage YndYndTabPage; + private System.Windows.Forms.TabPage YndNodeTabPage; + private System.Windows.Forms.Label label33; + private System.Windows.Forms.Label YndAreaIDInfoLabel; + private System.Windows.Forms.Label YndTotalNodesLabel; + private System.Windows.Forms.NumericUpDown YndPedNodesUpDown; + private System.Windows.Forms.Label label45; + private System.Windows.Forms.NumericUpDown YndVehicleNodesUpDown; + private System.Windows.Forms.Label label40; + private System.Windows.Forms.Label label47; + private System.Windows.Forms.ToolStripMenuItem FileNewYndMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenYndMenu; + private System.Windows.Forms.ToolStripMenuItem YndMenu; + private System.Windows.Forms.ToolStripMenuItem YndNameMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripMenuItem YndNewNodeMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; + private System.Windows.Forms.ToolStripMenuItem YndAddToProjectMenu; + private System.Windows.Forms.ToolStripMenuItem YndRemoveFromProjectMenu; + private System.Windows.Forms.Label label46; + private System.Windows.Forms.TextBox YndFilePathTextBox; + private System.Windows.Forms.Panel YndNodePanel; + private System.Windows.Forms.Label label48; + private System.Windows.Forms.TextBox YndProjectPathTextBox; + private System.Windows.Forms.Label PathNodeStreetNameLabel; + private System.Windows.Forms.TextBox PathNodeStreetHashTextBox; + private System.Windows.Forms.Label label52; + private System.Windows.Forms.NumericUpDown PathNodeNodeIDUpDown; + private System.Windows.Forms.Label label50; + private System.Windows.Forms.NumericUpDown PathNodeAreaIDUpDown; + private System.Windows.Forms.Label label49; + private System.Windows.Forms.Label PathNodeFlags4Label; + private System.Windows.Forms.NumericUpDown PathNodeFlags4UpDown; + private System.Windows.Forms.Label PathNodeFlags3Label; + private System.Windows.Forms.NumericUpDown PathNodeFlags3UpDown; + private System.Windows.Forms.Label PathNodeFlags2Label; + private System.Windows.Forms.NumericUpDown PathNodeFlags2UpDown; + private System.Windows.Forms.Label PathNodeFlags1Label; + private System.Windows.Forms.NumericUpDown PathNodeFlags1UpDown; + private System.Windows.Forms.Label PathNodeFlags0Label; + private System.Windows.Forms.NumericUpDown PathNodeFlags0UpDown; + private System.Windows.Forms.TabControl PathNodeTabControl; + private System.Windows.Forms.TabPage PathNodeLinksTabPage; + private System.Windows.Forms.TabPage PathNodeJunctionTabPage; + private System.Windows.Forms.SplitContainer splitContainer2; + private System.Windows.Forms.ListBox PathNodeLinksListBox; + private System.Windows.Forms.Panel PathNodeLinkPanel; + private System.Windows.Forms.NumericUpDown PathNodeLinkNodeIDUpDown; + private System.Windows.Forms.Label label51; + private System.Windows.Forms.NumericUpDown PathNodeLinkAreaIDUpDown; + private System.Windows.Forms.Label label54; + private System.Windows.Forms.NumericUpDown PathNodeLinkLengthUpDown; + private System.Windows.Forms.Label label57; + private System.Windows.Forms.Label PathNodeLinkFlags2Label; + private System.Windows.Forms.NumericUpDown PathNodeLinkFlags2UpDown; + private System.Windows.Forms.Label PathNodeLinkFlags1Label; + private System.Windows.Forms.NumericUpDown PathNodeLinkFlags1UpDown; + private System.Windows.Forms.Label PathNodeLinkFlags0Label; + private System.Windows.Forms.NumericUpDown PathNodeLinkFlags0UpDown; + private System.Windows.Forms.Button PathNodeGoToButton; + private System.Windows.Forms.TextBox PathNodePositionTextBox; + private System.Windows.Forms.Label label55; + private System.Windows.Forms.NumericUpDown PathNodeFlags5UpDown; + private System.Windows.Forms.Button PathNodeRemoveLinkButton; + private System.Windows.Forms.Button PathNodeAddLinkButton; + private System.Windows.Forms.Panel PathNodeJunctionPanel; + private System.Windows.Forms.NumericUpDown PathNodeJunctionMaxZUpDown; + private System.Windows.Forms.Label label65; + private System.Windows.Forms.CheckBox PathNodeJunctionEnableCheckBox; + private System.Windows.Forms.NumericUpDown PathNodeJunctionMinZUpDown; + private System.Windows.Forms.Label label67; + private System.Windows.Forms.NumericUpDown PathNodeJunctionHeightmapDimYUpDown; + private System.Windows.Forms.Label label77; + private System.Windows.Forms.NumericUpDown PathNodeJunctionHeightmapDimXUpDown; + private System.Windows.Forms.Label label76; + private System.Windows.Forms.Label label78; + private WinForms.TextBoxFix PathNodeJunctionHeightmapBytesTextBox; + private System.Windows.Forms.Label PathNodeLinkCountLabel; + private System.Windows.Forms.Label label68; + private System.Windows.Forms.Label PathNodeLinkageStatusLabel; + private System.Windows.Forms.Button PathNodeDeleteButton; + private System.Windows.Forms.Button PathNodeAddToProjectButton; + private System.Windows.Forms.TabPage TrainsTabPage; + private System.Windows.Forms.TabControl TrainsTabControl; + private System.Windows.Forms.TabPage TrainTrackTabPage; + private System.Windows.Forms.TabPage TrainNodeTabPage; + private System.Windows.Forms.Panel TrainNodePanel; + private System.Windows.Forms.Panel TrainTrackFilePanel; + private System.Windows.Forms.Label label74; + private System.Windows.Forms.TextBox TrainTrackProjectPathTextBox; + private System.Windows.Forms.Label label79; + private System.Windows.Forms.TextBox TrainTrackFilePathTextBox; + private System.Windows.Forms.Label label80; + private System.Windows.Forms.TextBox TrainTrackRpfPathTextBox; + private System.Windows.Forms.Button TrainNodeDeleteButton; + private System.Windows.Forms.Button TrainNodeAddToProjectButton; + private System.Windows.Forms.Button TrainNodeGoToButton; + private System.Windows.Forms.TextBox TrainNodePositionTextBox; + private System.Windows.Forms.Label label81; + private System.Windows.Forms.ComboBox TrainNodeTypeComboBox; + private System.Windows.Forms.Label label82; + private System.Windows.Forms.Label label83; + private System.Windows.Forms.TextBox TrainTrackFilenameTextBox; + private System.Windows.Forms.Label label84; + private System.Windows.Forms.TextBox TrainTrackConfigNameTextBox; + private System.Windows.Forms.CheckBox TrainTrackMPStopsAtStationsCheckBox; + private System.Windows.Forms.CheckBox TrainTrackStopsAtStationsCheckBox; + private System.Windows.Forms.CheckBox TrainTrackIsPingPongCheckBox; + private System.Windows.Forms.Label label86; + private System.Windows.Forms.TextBox TrainTrackBrakingDistTextBox; + private System.Windows.Forms.Label label85; + private System.Windows.Forms.TextBox TrainTrackSpeedTextBox; + private System.Windows.Forms.ToolStripMenuItem TrainsMenu; + private System.Windows.Forms.ToolStripMenuItem TrainsNameMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; + private System.Windows.Forms.ToolStripMenuItem TrainsNewNodeMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator8; + private System.Windows.Forms.ToolStripMenuItem TrainsAddToProjectMenu; + private System.Windows.Forms.ToolStripMenuItem TrainsRemoveFromProjectMenu; + private System.Windows.Forms.ToolStripMenuItem FileNewTrainsMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenTrainsMenu; + private System.Windows.Forms.TabPage YnvTabPage; + private System.Windows.Forms.TabControl YnvTabControl; + private System.Windows.Forms.TabPage YnvYnvTabPage; + private System.Windows.Forms.TabPage YnvPolyTabPage; + private System.Windows.Forms.TabPage YnvPortalTabPage; + private System.Windows.Forms.Panel YnvPanel; + private System.Windows.Forms.Panel YnvPolygonPanel; + private System.Windows.Forms.Panel YnvPortalPanel; + private System.Windows.Forms.ToolStripMenuItem FileNewYnvMenu; + private System.Windows.Forms.ToolStripMenuItem FileOpenYnvMenu; + private System.Windows.Forms.ToolStripMenuItem YnvMenu; + private System.Windows.Forms.ToolStripMenuItem YnvNameMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator9; + private System.Windows.Forms.ToolStripMenuItem YnvNewPolygonMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator10; + private System.Windows.Forms.ToolStripMenuItem YnvAddToProjectMenu; + private System.Windows.Forms.ToolStripMenuItem YnvRemoveFromProjectMenu; + private System.Windows.Forms.Label label88; + private System.Windows.Forms.NumericUpDown YndAreaIDYUpDown; + private System.Windows.Forms.Label label87; + private System.Windows.Forms.NumericUpDown YndAreaIDXUpDown; + private System.Windows.Forms.Label label89; + private System.Windows.Forms.NumericUpDown YnvAreaIDYUpDown; + private System.Windows.Forms.Label label90; + private System.Windows.Forms.NumericUpDown YnvAreaIDXUpDown; + private System.Windows.Forms.Label YnvAreaIDInfoLabel; + private System.Windows.Forms.Label label92; + private System.Windows.Forms.TextBox YnvAABBSizeTextBox; + private System.Windows.Forms.Label label91; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.CheckBox YmapCFlagsSLOD2CheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsLODCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsHDCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsOcclusionCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsInteriorCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsSLODCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsPhysicsCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsCriticalCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsDistLightsCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsLODLightsCheckBox; + private System.Windows.Forms.CheckBox YmapCFlagsGrassCheckBox; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.CheckBox YmapFlagsLODCheckBox; + private System.Windows.Forms.CheckBox YmapFlagsScriptedCheckBox; + private System.Windows.Forms.Button YmapCalculateFlagsButton; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.Label label12; + private WinForms.TextBoxFix YmapPhysicsDictionariesTextBox; + private System.Windows.Forms.TabControl EntityTabControl; + private System.Windows.Forms.TabPage EntityGeneralTabPage; + private System.Windows.Forms.TabPage EntityLodTabPage; + private System.Windows.Forms.TabPage EntityExtensionsTabPage; + private System.Windows.Forms.TabPage EntityPivotTabPage; + private System.Windows.Forms.Label label93; + private System.Windows.Forms.TextBox EntityPivotPositionTextBox; + private System.Windows.Forms.Button EntityPivotRotationNormalizeButton; + private System.Windows.Forms.Label label94; + private System.Windows.Forms.TextBox EntityPivotRotationTextBox; + private System.Windows.Forms.CheckBox EntityPivotEditCheckBox; + private System.Windows.Forms.Label label95; + private System.Windows.Forms.NumericUpDown PathNodeJunctionPosYUpDown; + private System.Windows.Forms.Label label59; + private System.Windows.Forms.NumericUpDown PathNodeJunctionPosXUpDown; + private System.Windows.Forms.Label label69; + private System.Windows.Forms.Label TrainTrackInfoLabel; + private System.Windows.Forms.TabPage PathNodePropertiesTabPage; + private System.Windows.Forms.CheckBox PathNodeFlags08CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags07CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags06CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags05CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags04CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags03CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags02CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags01CheckBox; + private System.Windows.Forms.GroupBox PathNodeFlags0GroupBox; + private System.Windows.Forms.GroupBox PathNodeFlags1GroupBox; + private System.Windows.Forms.CheckBox PathNodeFlags11CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags18CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags12CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags17CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags13CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags16CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags14CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags15CheckBox; + private System.Windows.Forms.GroupBox PathNodeFlags2GroupBox; + private System.Windows.Forms.CheckBox PathNodeFlags21CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags28CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags22CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags27CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags23CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags26CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags24CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags25CheckBox; + private System.Windows.Forms.GroupBox PathNodeFlags3GroupBox; + private System.Windows.Forms.CheckBox PathNodeFlags31CheckBox; + private System.Windows.Forms.Label label70; + private System.Windows.Forms.GroupBox PathNodeFlags4GroupBox; + private System.Windows.Forms.Label label71; + private System.Windows.Forms.CheckBox PathNodeFlags41CheckBox; + private System.Windows.Forms.NumericUpDown PathNodeFlags42UpDown; + private System.Windows.Forms.GroupBox PathNodeFlags5GroupBox; + private System.Windows.Forms.CheckBox PathNodeFlags51CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags45CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags46CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags47CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags48CheckBox; + private System.Windows.Forms.NumericUpDown PathNodeFlags32UpDown; + private System.Windows.Forms.CheckBox PathNodeFlags52CheckBox; + private System.Windows.Forms.CheckBox PathNodeFlags53CheckBox; + private System.Windows.Forms.NumericUpDown PathNodeLinkBackLanesUpDown; + private System.Windows.Forms.Label label56; + private System.Windows.Forms.NumericUpDown PathNodeLinkFwdLanesUpDown; + private System.Windows.Forms.Label label53; + private System.Windows.Forms.GroupBox PathLinkFlags0GroupBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags01CheckBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags02CheckBox; + private System.Windows.Forms.GroupBox PathLinkFlags1GroupBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags11CheckBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags18CheckBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags12CheckBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags13CheckBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags14CheckBox; + private System.Windows.Forms.GroupBox PathLinkFlags2GroupBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags21CheckBox; + private System.Windows.Forms.CheckBox PathNodeLinkFlags22CheckBox; + private System.Windows.Forms.NumericUpDown PathNodeLinkFlags04UpDown; + private System.Windows.Forms.Label label60; + private System.Windows.Forms.NumericUpDown PathNodeLinkFlags03UpDown; + private System.Windows.Forms.Label label58; + private System.Windows.Forms.NumericUpDown PathNodeLinkOffsetSizeUpDown; + private System.Windows.Forms.Label label61; + private System.Windows.Forms.TabPage ScenarioTabPage; + private System.Windows.Forms.TabControl ScenarioTabControl; + private System.Windows.Forms.TabPage ScenarioYmtTabPage; + private System.Windows.Forms.TabPage ScenarioPointTabPage; + private System.Windows.Forms.Panel ScenarioYmtPanel; + private System.Windows.Forms.Panel ScenarioPointOuterPanel; + private System.Windows.Forms.TextBox ScenarioYmtNameTextBox; + private System.Windows.Forms.Label label63; + private System.Windows.Forms.TextBox ScenarioYmtVersionTextBox; + private System.Windows.Forms.Label label64; + private System.Windows.Forms.TextBox ScenarioYmtProjectPathTextBox; + private System.Windows.Forms.Label label66; + private System.Windows.Forms.TextBox ScenarioYmtFileLocationTextBox; + private System.Windows.Forms.Label label72; + private System.Windows.Forms.TextBox ScenarioYmtGridMaxTextBox; + private System.Windows.Forms.Label label73; + private System.Windows.Forms.TextBox ScenarioYmtGridMinTextBox; + private System.Windows.Forms.Label label75; + private System.Windows.Forms.Label ScenarioYmtGridInfoLabel; + private System.Windows.Forms.TextBox ScenarioYmtGridScaleTextBox; + private System.Windows.Forms.Label label96; + private System.Windows.Forms.ToolStripMenuItem FileOpenScenarioMenu; + private System.Windows.Forms.ToolStripMenuItem ScenarioMenu; + private System.Windows.Forms.ToolStripMenuItem ScenarioNameMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator11; + private System.Windows.Forms.ToolStripMenuItem ScenarioNewPointMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator12; + private System.Windows.Forms.ToolStripMenuItem ScenarioAddToProjectMenu; + private System.Windows.Forms.ToolStripMenuItem ScenarioRemoveFromProjectMenu; + private System.Windows.Forms.ToolStripMenuItem FileNewScenarioMenu; + private System.Windows.Forms.TextBox ScenarioPointDirectionTextBox; + private System.Windows.Forms.Label label97; + private System.Windows.Forms.Button ScenarioPointDeleteButton; + private System.Windows.Forms.Button ScenarioPointAddToProjectButton; + private System.Windows.Forms.Button ScenarioPointGoToButton; + private System.Windows.Forms.TextBox ScenarioPointPositionTextBox; + private System.Windows.Forms.Label label62; + private System.Windows.Forms.Panel ScenarioPointPanel; + private System.Windows.Forms.ComboBox ScenarioPointTypeComboBox; + private System.Windows.Forms.Label label98; + private System.Windows.Forms.NumericUpDown ScenarioPointTimeEndUpDown; + private System.Windows.Forms.NumericUpDown ScenarioPointTimeStartUpDown; + private System.Windows.Forms.Label label100; + private System.Windows.Forms.ComboBox ScenarioPointModelSetComboBox; + private System.Windows.Forms.Label label99; + private System.Windows.Forms.Label label101; + private System.Windows.Forms.TextBox ScenarioPointInteriorTextBox; + private System.Windows.Forms.Label label102; + private System.Windows.Forms.Label label106; + private System.Windows.Forms.NumericUpDown ScenarioPointProbabilityUpDown; + private System.Windows.Forms.Label label107; + private System.Windows.Forms.NumericUpDown ScenarioPointSpOnlyFlagUpDown; + private System.Windows.Forms.Label label108; + private System.Windows.Forms.NumericUpDown ScenarioPointRadiusUpDown; + private System.Windows.Forms.Label label109; + private System.Windows.Forms.NumericUpDown ScenarioPointWaitTimeUpDown; + private System.Windows.Forms.Label label111; + private System.Windows.Forms.NumericUpDown ScenarioPointFlagsValueUpDown; + private System.Windows.Forms.CheckedListBox ScenarioPointFlagsCheckedListBox; + private System.Windows.Forms.CheckBox ScenarioPointCheckBox; + private System.Windows.Forms.TabPage ScenarioEntityPointTabPage; + private System.Windows.Forms.Panel ScenarioEntityPointPanel; + private System.Windows.Forms.CheckBox ScenarioEntityPointCheckBox; + private System.Windows.Forms.TabPage ScenarioChainTabPage; + private System.Windows.Forms.TabPage ScenarioClusterTabPage; + private System.Windows.Forms.Panel ScenarioClusterPanel; + private System.Windows.Forms.CheckBox ScenarioClusterCheckBox; + private System.Windows.Forms.Label ScenarioPointInteriorHashLabel; + private System.Windows.Forms.Label label116; + private System.Windows.Forms.Button ScenarioEntityPointGoToButton; + private System.Windows.Forms.TextBox ScenarioEntityPointPositionTextBox; + private System.Windows.Forms.Label label117; + private System.Windows.Forms.TextBox ScenarioEntityPointRotationTextBox; + private System.Windows.Forms.Label label118; + private System.Windows.Forms.Label ScenarioEntityPointPedTypeHashLabel; + private System.Windows.Forms.TextBox ScenarioEntityPointPedTypeTextBox; + private System.Windows.Forms.Label label122; + private System.Windows.Forms.Label ScenarioEntityPointSpawnTypeHashLabel; + private System.Windows.Forms.TextBox ScenarioEntityPointSpawnTypeTextBox; + private System.Windows.Forms.Label label120; + private System.Windows.Forms.Label ScenarioEntityPointRequiredImapHashLabel; + private System.Windows.Forms.TextBox ScenarioEntityPointRequiredImapTextBox; + private System.Windows.Forms.Label label128; + private System.Windows.Forms.Label ScenarioEntityPointInteriorHashLabel; + private System.Windows.Forms.TextBox ScenarioEntityPointInteriorTextBox; + private System.Windows.Forms.Label label126; + private System.Windows.Forms.Label ScenarioEntityPointGroupHashLabel; + private System.Windows.Forms.TextBox ScenarioEntityPointGroupTextBox; + private System.Windows.Forms.Label label124; + private System.Windows.Forms.ComboBox ScenarioEntityPointAvailableInMpSpComboBox; + private System.Windows.Forms.Label label129; + private System.Windows.Forms.TextBox ScenarioEntityPointProbabilityTextBox; + private System.Windows.Forms.Label label130; + private System.Windows.Forms.TextBox ScenarioEntityPointTimeTillPedLeavesTextBox; + private System.Windows.Forms.Label label131; + private System.Windows.Forms.TextBox ScenarioEntityPointRadiusTextBox; + private System.Windows.Forms.Label label132; + private System.Windows.Forms.Label label133; + private System.Windows.Forms.NumericUpDown ScenarioEntityPointEndUpDown; + private System.Windows.Forms.NumericUpDown ScenarioEntityPointStartUpDown; + private System.Windows.Forms.Label label134; + private System.Windows.Forms.CheckBox ScenarioEntityPointHighPriCheckBox; + private System.Windows.Forms.CheckBox ScenarioEntityPointExtendedRangeCheckBox; + private System.Windows.Forms.CheckedListBox ScenarioEntityPointFlagsCheckedListBox; + private System.Windows.Forms.Label label135; + private System.Windows.Forms.NumericUpDown ScenarioEntityPointFlagsUpDown; + private System.Windows.Forms.CheckBox ScenarioEntityPointShortRangeCheckBox; + private System.Windows.Forms.Button ScenarioEntityPointDeleteButton; + private System.Windows.Forms.Button ScenarioEntityPointAddToProjectButton; + private System.Windows.Forms.Button ScenarioClusterDeleteButton; + private System.Windows.Forms.Button ScenarioClusterAddToProjectButton; + private System.Windows.Forms.Label ScenarioEntityPointNameHashLabel; + private System.Windows.Forms.TextBox ScenarioEntityPointNameTextBox; + private System.Windows.Forms.SplitContainer splitContainer3; + private System.Windows.Forms.Button ScenarioChainRemoveEdgeButton; + private System.Windows.Forms.Button ScenarioChainAddEdgeButton; + private System.Windows.Forms.ListBox ScenarioChainEdgesListBox; + private System.Windows.Forms.Label ScenarioChainEdgeCountLabel; + private System.Windows.Forms.Panel ScenarioChainEdgePanel; + private System.Windows.Forms.Label label121; + private System.Windows.Forms.Label label125; + private System.Windows.Forms.NumericUpDown ScenarioChainEdgeNodeIndexToUpDown; + private System.Windows.Forms.NumericUpDown ScenarioChainEdgeNodeIndexFromUpDown; + private System.Windows.Forms.ComboBox ScenarioChainEdgeActionComboBox; + private System.Windows.Forms.Label label127; + private System.Windows.Forms.ComboBox ScenarioChainEdgeNavSpeedComboBox; + private System.Windows.Forms.Label label137; + private System.Windows.Forms.ComboBox ScenarioChainEdgeNavModeComboBox; + private System.Windows.Forms.Label label136; + private System.Windows.Forms.Label label138; + private System.Windows.Forms.NumericUpDown ScenarioChainUnk1UpDown; + private System.Windows.Forms.Button ScenarioClusterGoToButton; + private System.Windows.Forms.TextBox ScenarioClusterCenterTextBox; + private System.Windows.Forms.Label label139; + private System.Windows.Forms.TextBox ScenarioClusterUnk1TextBox; + private System.Windows.Forms.Label label140; + private System.Windows.Forms.CheckBox ScenarioClusterUnk2CheckBox; + private System.Windows.Forms.Label ScenarioPointGroupHashLabel; + private System.Windows.Forms.TextBox ScenarioPointGroupTextBox; + private System.Windows.Forms.Label label156; + private System.Windows.Forms.Label ScenarioPointImapHashLabel; + private System.Windows.Forms.TextBox ScenarioPointImapTextBox; + private System.Windows.Forms.Label label110; + private System.Windows.Forms.TabPage ScenarioClusterPointTabPage; + private System.Windows.Forms.Button ScenarioClusterPointDeleteButton; + private System.Windows.Forms.Button ScenarioClusterPointAddToProjectButton; + private System.Windows.Forms.Panel ScenarioClusterPointPanel; + private System.Windows.Forms.Label ScenarioClusterPointImapHashLabel; + private System.Windows.Forms.TextBox ScenarioClusterPointImapTextBox; + private System.Windows.Forms.Label label143; + private System.Windows.Forms.Label ScenarioClusterPointGroupHashLabel; + private System.Windows.Forms.TextBox ScenarioClusterPointGroupTextBox; + private System.Windows.Forms.Label label141; + private System.Windows.Forms.Label ScenarioClusterPointInteriorHashLabel; + private System.Windows.Forms.CheckedListBox ScenarioClusterPointFlagsCheckedListBox; + private System.Windows.Forms.Label label142; + private System.Windows.Forms.TextBox ScenarioClusterPointDirectionTextBox; + private System.Windows.Forms.Label label144; + private System.Windows.Forms.NumericUpDown ScenarioClusterPointFlagsUpDown; + private System.Windows.Forms.Label label145; + private System.Windows.Forms.Button ScenarioClusterPointGoToButton; + private System.Windows.Forms.NumericUpDown ScenarioClusterPointWaitTimeUpDown; + private System.Windows.Forms.TextBox ScenarioClusterPointPositionTextBox; + private System.Windows.Forms.Label label146; + private System.Windows.Forms.Label label147; + private System.Windows.Forms.NumericUpDown ScenarioClusterPointRadiusUpDown; + private System.Windows.Forms.Label label148; + private System.Windows.Forms.NumericUpDown ScenarioClusterPointAnimalFlagUpDown; + private System.Windows.Forms.Label label149; + private System.Windows.Forms.NumericUpDown ScenarioClusterPointProbabilityUpDown; + private System.Windows.Forms.TextBox ScenarioClusterPointInteriorTextBox; + private System.Windows.Forms.Label label151; + private System.Windows.Forms.Label label152; + private System.Windows.Forms.NumericUpDown ScenarioClusterPointTimeEndUpDown; + private System.Windows.Forms.NumericUpDown ScenarioClusterPointTimeStartUpDown; + private System.Windows.Forms.Label label153; + private System.Windows.Forms.ComboBox ScenarioClusterPointModelSetComboBox; + private System.Windows.Forms.Label label154; + private System.Windows.Forms.ComboBox ScenarioClusterPointTypeComboBox; + private System.Windows.Forms.Label label155; + private System.Windows.Forms.CheckBox ScenarioClusterPointCheckBox; + private System.Windows.Forms.TabPage ScenarioChainNodeTabPage; + private System.Windows.Forms.Panel ScenarioChainNodePanel; + private System.Windows.Forms.ComboBox ScenarioChainNodeTypeComboBox; + private System.Windows.Forms.TextBox ScenarioChainNodeIndexTextBox; + private System.Windows.Forms.Label label115; + private System.Windows.Forms.CheckBox ScenarioChainNodeLastCheckBox; + private System.Windows.Forms.CheckBox ScenarioChainNodeFirstCheckBox; + private System.Windows.Forms.Label label123; + private System.Windows.Forms.Label ScenarioChainNodeUnk1HashLabel; + private System.Windows.Forms.TextBox ScenarioChainNodeUnk1TextBox; + private System.Windows.Forms.Label label119; + private System.Windows.Forms.Button ScenarioChainNodeGoToButton; + private System.Windows.Forms.TextBox ScenarioChainNodePositionTextBox; + private System.Windows.Forms.Label label105; + private System.Windows.Forms.Button ScenarioChainNodeDeleteButton; + private System.Windows.Forms.CheckBox ScenarioChainNodeCheckBox; + private System.Windows.Forms.Button ScenarioChainNodeAddToProjectButton; + private System.Windows.Forms.TabPage ScenarioEntityTabPage; + private System.Windows.Forms.Button ScenarioEntityDeleteButton; + private System.Windows.Forms.Panel ScenarioEntityPanel; + private System.Windows.Forms.Label ScenarioEntityInfoLabel; + private System.Windows.Forms.Label label114; + private System.Windows.Forms.NumericUpDown ScenarioEntityUnk2UpDown; + private System.Windows.Forms.Label label113; + private System.Windows.Forms.NumericUpDown ScenarioEntityUnk1UpDown; + private System.Windows.Forms.Label ScenarioEntityTypeHashLabel; + private System.Windows.Forms.TextBox ScenarioEntityTypeTextBox; + private System.Windows.Forms.Label label112; + private System.Windows.Forms.Button ScenarioEntityGoToButton; + private System.Windows.Forms.TextBox ScenarioEntityPositionTextBox; + private System.Windows.Forms.Label label104; + private System.Windows.Forms.Button ScenarioEntityAddToProjectButton; + private System.Windows.Forms.CheckBox ScenarioEntityCheckBox; + private System.Windows.Forms.Button ScenarioChainDeleteButton; + private System.Windows.Forms.Button ScenarioChainAddToProjectButton; + private System.Windows.Forms.TextBox ScenarioYmtExtentsMaxTextBox; + private System.Windows.Forms.Label label103; + private System.Windows.Forms.TextBox ScenarioYmtExtentsMinTextBox; + private System.Windows.Forms.Label label150; + private System.Windows.Forms.ToolStripMenuItem ScenarioNewPointFromSelectedMenu; + private System.Windows.Forms.ToolStripMenuItem ScenarioNewEntityOverrideMenu; + private System.Windows.Forms.ToolStripMenuItem ScenarioNewChainMenu; + private System.Windows.Forms.ToolStripMenuItem ScenarioNewClusterMenu; + private System.Windows.Forms.TextBox ScenarioClusterRadiusTextBox; + private System.Windows.Forms.Label label157; + private System.Windows.Forms.Button ScenarioChainMoveEdgeDownButton; + private System.Windows.Forms.Button ScenarioChainMoveEdgeUpButton; + private System.Windows.Forms.Button ScenarioClusterAddPointButton; + private System.Windows.Forms.Label label158; + private System.Windows.Forms.ListBox ScenarioClusterPointsListBox; + private System.Windows.Forms.Label label159; + private System.Windows.Forms.Label label160; + private System.Windows.Forms.Button ScenarioEntityAddPointButton; + private System.Windows.Forms.Label label161; + private System.Windows.Forms.ListBox ScenarioEntityPointsListBox; + } +} \ No newline at end of file diff --git a/ProjectForm.cs b/ProjectForm.cs new file mode 100644 index 0000000..c185624 --- /dev/null +++ b/ProjectForm.cs @@ -0,0 +1,10069 @@ +using CodeWalker.GameFiles; +using CodeWalker.Project; +using CodeWalker.Properties; +using CodeWalker.World; +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class ProjectForm : Form + { + WorldForm WorldForm; + GameFileCache GameFileCache; + RpfManager RpfMan; + + ProjectFile CurrentProjectFile; + YmapFile CurrentYmapFile; + YmapEntityDef CurrentEntity; + YmapCarGen CurrentCarGen; + + YndFile CurrentYndFile; + YndNode CurrentPathNode; + YndLink CurrentPathLink; + + YnvFile CurrentYnvFile; + YnvPoly CurrentNavPoly; + + TrainTrack CurrentTrainTrack; + TrainTrackNode CurrentTrainNode; + + YmtFile CurrentScenario; + ScenarioNode CurrentScenarioNode; + MCScenarioChainingEdge CurrentScenarioChainEdge; + + + bool renderentities = true; + bool hidegtavmap = false; + + object ymapsyncroot = new object(); + object yndsyncroot = new object(); + object ynvsyncroot = new object(); + object trainsyncroot = new object(); + object scenariosyncroot = new object(); + + Dictionary visibleynds = new Dictionary(); + Dictionary visibleynvs = new Dictionary(); + Dictionary visibletrains = new Dictionary(); + Dictionary visiblescenarios = new Dictionary(); + + + bool populatingui = false; + + + + public bool IsProjectLoaded + { + get { return CurrentProjectFile != null; } + } + + + public ProjectForm(WorldForm worldForm) + { + InitializeComponent(); + + MainTabControl.TabPages.Remove(YnvTabPage);//TODO + EntityTabControl.TabPages.Remove(EntityExtensionsTabPage);//TODO + + LoadDropDowns(); + + WorldForm = worldForm; + if ((WorldForm != null) && (WorldForm.GameFileCache != null)) + { + GameFileCache = WorldForm.GameFileCache; + RpfMan = GameFileCache.RpfMan; + } + else + { + GameFileCache = new GameFileCache(); + new Thread(new ThreadStart(() => { + GameFileCache.Init(UpdateStatus, UpdateStatus); + RpfMan = GameFileCache.RpfMan; + })).Start(); + } + + } + + + private void LoadDropDowns() + { + EntityLodLevelComboBox.Items.Clear(); + EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_ORPHANHD); + EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_HD); + EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_LOD); + EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_SLOD1); + EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_SLOD2); + EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_SLOD3); + EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_SLOD4); + + EntityPriorityLevelComboBox.Items.Clear(); + EntityPriorityLevelComboBox.Items.Add(Unk_648413703.PRI_REQUIRED); + EntityPriorityLevelComboBox.Items.Add(Unk_648413703.PRI_OPTIONAL_HIGH); + EntityPriorityLevelComboBox.Items.Add(Unk_648413703.PRI_OPTIONAL_MEDIUM); + EntityPriorityLevelComboBox.Items.Add(Unk_648413703.PRI_OPTIONAL_LOW); + } + + + private void UpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateStatus(text); })); + } + else + { + //TODO: status text + //StatusLabel.Text = text; + } + } + catch { } + } + + + + + private void UpdateFormTitleText() + { + if (CurrentProjectFile == null) + { + Text = "Project - CodeWalker by dexyfex"; + } + else + { + Text = CurrentProjectFile.Name + " - CodeWalker by dexyfex"; + } + } + + private void RefreshProjectUI() + { + bool enable = (CurrentProjectFile != null); + FileCloseProjectMenu.Enabled = enable; + FileSaveProjectMenu.Enabled = enable; + FileSaveProjectAsMenu.Enabled = enable; + } + + private void RefreshYmapUI() + { + bool enable = (CurrentYmapFile != null); + bool inproj = YmapExistsInProject(CurrentYmapFile); + + YmapNewEntityMenu.Enabled = enable && inproj; + YmapNewCarGenMenu.Enabled = enable && inproj; + + if (CurrentYmapFile != null) + { + YmapNameMenu.Text = "(" + CurrentYmapFile.Name + ")"; + } + else + { + YmapNameMenu.Text = "(No .ymap file selected)"; + } + + YmapAddToProjectMenu.Enabled = enable && !inproj; + YmapRemoveFromProjectMenu.Enabled = inproj; + + if (WorldForm != null) + { + WorldForm.EnableYmapUI(enable, CurrentYmapFile?.Name ?? ""); + } + } + + private void RefreshEntityUI() + { + bool enable = (CurrentEntity != null); + bool isinproj = false; + + if (CurrentEntity != null) + { + isinproj = YmapExistsInProject(CurrentEntity.Ymap); + } + + EntityAddToProjectButton.Enabled = !isinproj; + EntityDeleteButton.Enabled = isinproj; + } + + private void RefreshCarGenUI() + { + bool enable = (CurrentCarGen != null); + bool isinproj = false; + + if (CurrentCarGen != null) + { + isinproj = YmapExistsInProject(CurrentCarGen.Ymap); + } + + CarAddToProjectButton.Enabled = !isinproj; + CarDeleteButton.Enabled = isinproj; + } + + private void RefreshYndUI() + { + bool enable = (CurrentYndFile != null); + bool inproj = YndExistsInProject(CurrentYndFile); + + YndNewNodeMenu.Enabled = enable && inproj; + + if (CurrentYndFile != null) + { + YndNameMenu.Text = "(" + CurrentYndFile.Name + ")"; + } + else + { + YndNameMenu.Text = "(No .ynd file selected)"; + } + + YndAddToProjectMenu.Enabled = enable && !inproj; + YndRemoveFromProjectMenu.Enabled = inproj; + + + if (WorldForm != null) + { + WorldForm.EnableYndUI(enable, CurrentYndFile?.Name ?? ""); + } + } + + private void RefreshYnvUI() + { + bool enable = (CurrentYnvFile != null); + bool inproj = YnvExistsInProject(CurrentYnvFile); + + YnvNewPolygonMenu.Enabled = enable && inproj; + + if (CurrentYnvFile != null) + { + YnvNameMenu.Text = "(" + CurrentYnvFile.Name + ")"; + } + else + { + YnvNameMenu.Text = "(No .ynv file selected)"; + } + + YnvAddToProjectMenu.Enabled = enable && !inproj; + YnvRemoveFromProjectMenu.Enabled = inproj; + + + if (WorldForm != null) + { + WorldForm.EnableYnvUI(enable, CurrentYnvFile?.Name ?? ""); + } + } + + private void RefreshTrainTrackUI() + { + bool enable = (CurrentTrainTrack != null); + bool inproj = TrainTrackExistsInProject(CurrentTrainTrack); + + TrainsNewNodeMenu.Enabled = enable && inproj; + + if (CurrentTrainTrack != null) + { + TrainsNameMenu.Text = "(" + CurrentTrainTrack.Name + ")"; + } + else + { + TrainsNameMenu.Text = "(No train track selected)"; + } + + TrainsAddToProjectMenu.Enabled = enable && !inproj; + TrainsRemoveFromProjectMenu.Enabled = inproj; + + + if (WorldForm != null) + { + WorldForm.EnableTrainsUI(enable, CurrentTrainTrack?.Name ?? ""); + } + } + + private void RefreshScenarioUI() + { + bool enable = (CurrentScenario != null); + bool inproj = ScenarioExistsInProject(CurrentScenario); + + ScenarioNewPointMenu.Enabled = enable && inproj; + ScenarioNewPointFromSelectedMenu.Enabled = enable && inproj && (CurrentScenarioNode != null); + ScenarioNewEntityOverrideMenu.Enabled = enable && inproj; + ScenarioNewChainMenu.Enabled = enable && inproj; + ScenarioNewClusterMenu.Enabled = enable && inproj; + + if (CurrentScenario != null) + { + ScenarioNameMenu.Text = "(" + CurrentScenario.Name + ")"; + } + else + { + ScenarioNameMenu.Text = "(No scenario region selected)"; + } + + ScenarioAddToProjectMenu.Enabled = enable && !inproj; + ScenarioRemoveFromProjectMenu.Enabled = inproj; + + + if (WorldForm != null) + { + WorldForm.EnableScenarioUI(enable, CurrentScenario?.Name ?? ""); + } + } + + private void RefreshUI() + { + RefreshYmapUI(); + RefreshEntityUI(); + RefreshCarGenUI(); + RefreshYndUI(); + RefreshYnvUI(); + RefreshTrainTrackUI(); + RefreshScenarioUI(); + SetCurrentSaveItem(); + LoadYmapTabPage(); + LoadEntityTabPage(); + LoadCarGenTabPage(); + LoadYndTabPage(); + LoadYnvTabPage(); + LoadPathNodeTabPage(); + LoadTrainTrackTabPage(); + LoadTrainNodeTabPage(); + LoadScenarioTabPage(); + LoadScenarioNodeTabPages(); + } + + + private void SetCurrentSaveItem() + { + string filename = null; + if (CurrentYmapFile != null) + { + filename = CurrentYmapFile.RpfFileEntry?.Name; + } + else if (CurrentYndFile != null) + { + filename = CurrentYndFile.RpfFileEntry?.Name; + } + else if (CurrentYnvFile != null) + { + filename = CurrentYnvFile.RpfFileEntry?.Name; + } + else if (CurrentTrainTrack != null) + { + filename = CurrentTrainTrack.RpfFileEntry?.Name; + } + else if (CurrentScenario != null) + { + filename = CurrentScenario.RpfFileEntry?.Name; + } + + bool enable = !string.IsNullOrEmpty(filename); + + if (enable) + { + FileSaveItemMenu.Text = "Save " + filename; + FileSaveItemAsMenu.Text = "Save " + filename + " As..."; + } + else + { + FileSaveItemMenu.Text = "Save"; + FileSaveItemAsMenu.Text = "Save As..."; + } + + FileSaveItemMenu.Tag = filename; + FileSaveItemAsMenu.Tag = filename; + + FileSaveItemMenu.Enabled = enable; + FileSaveItemMenu.Visible = enable; + FileSaveItemAsMenu.Enabled = enable; + FileSaveItemAsMenu.Visible = enable; + + if (WorldForm != null) + { + WorldForm.SetCurrentSaveItem(filename); + } + } + + + + public void Save() + { + if (CurrentYmapFile != null) + { + SaveYmap(); + } + else if (CurrentYndFile != null) + { + SaveYnd(); + } + else if (CurrentYnvFile != null) + { + SaveYnv(); + } + else if (CurrentTrainTrack != null) + { + SaveTrainTrack(); + } + else if (CurrentScenario != null) + { + SaveScenario(); + } + else if (CurrentProjectFile != null) + { + SaveProject(); + } + } + + public void SaveAll() + { + if (CurrentProjectFile != null) + { + if (CurrentProjectFile.YmapFiles != null) + { + var cymap = CurrentYmapFile; + foreach (var ymap in CurrentProjectFile.YmapFiles) + { + CurrentYmapFile = ymap; + SaveYmap(); + } + CurrentYmapFile = cymap; + LoadYmapTabPage(); + } + + if (CurrentProjectFile.YndFiles != null) + { + var cynd = CurrentYndFile; + foreach (var ynd in CurrentProjectFile.YndFiles) + { + CurrentYndFile = ynd; + SaveYnd(); + } + CurrentYndFile = cynd; + LoadYndTabPage(); + } + + if (CurrentProjectFile.YnvFiles != null) + { + var cynv = CurrentYnvFile; + foreach (var ynv in CurrentProjectFile.YnvFiles) + { + CurrentYnvFile = ynv; + SaveYnv(); + } + CurrentYnvFile = cynv; + LoadYnvTabPage(); + } + + if (CurrentProjectFile.TrainsFiles != null) + { + var ctrack = CurrentTrainTrack; + foreach (var track in CurrentProjectFile.TrainsFiles) + { + CurrentTrainTrack = track; + SaveYnd(); + } + CurrentTrainTrack = ctrack; + LoadTrainTrackTabPage(); + } + + if (CurrentProjectFile.ScenarioFiles != null) + { + var cscen = CurrentScenario; + foreach (var scen in CurrentProjectFile.ScenarioFiles) + { + CurrentScenario = scen; + SaveScenario(); + } + CurrentScenario = cscen; + LoadScenarioTabPage(); + } + + + SaveProject(); + } + } + + + private void SaveCurrentItem(bool saveas = false) + { + if (CurrentYmapFile != null) + { + SaveYmap(saveas); + } + else if (CurrentYndFile != null) + { + SaveYnd(saveas); + } + else if (CurrentYnvFile != null) + { + SaveYnv(saveas); + } + else if (CurrentTrainTrack != null) + { + SaveTrainTrack(saveas); + } + else if (CurrentScenario != null) + { + SaveScenario(saveas); + } + } + + + + public void NewProject() + { + if (CurrentProjectFile != null) + { + ////unload current project first + CloseProject(); + } + + CurrentProjectFile = new ProjectFile(); + CurrentProjectFile.Name = "New CodeWalker Project"; + CurrentProjectFile.Version = 1; + CurrentProjectFile.HasChanged = true; + LoadProjectUI(); + } + + public void OpenProject() + { + string file = ShowOpenDialog("CodeWalker Projects|*.cwproj", string.Empty); + if (string.IsNullOrEmpty(file)) + { + return; + } + + CloseProject(); + + CurrentProjectFile = new ProjectFile(); + CurrentProjectFile.Load(file); + + string cpath = new FileInfo(CurrentProjectFile.Filepath).Directory.FullName; + + foreach (var ymap in CurrentProjectFile.YmapFiles) + { + string filename = ymap.FilePath; + if (!File.Exists(filename)) + { + filename = cpath + "\\" + filename; + } + if (File.Exists(filename)) + { + LoadYmapFromFile(ymap, filename); + } + else + { + MessageBox.Show("Couldn't find file: " + filename); + } + } + + foreach (var ynd in CurrentProjectFile.YndFiles) + { + string filename = ynd.FilePath; + if (!File.Exists(filename)) + { + filename = cpath + "\\" + filename; + } + if (File.Exists(filename)) + { + LoadYndFromFile(ynd, filename); + } + else + { + MessageBox.Show("Couldn't find file: " + filename); + } + } + + foreach (var ynv in CurrentProjectFile.YnvFiles) + { + string filename = ynv.FilePath; + if (!File.Exists(filename)) + { + filename = cpath + "\\" + filename; + } + if (File.Exists(filename)) + { + LoadYnvFromFile(ynv, filename); + } + else + { + MessageBox.Show("Couldn't find file: " + filename); + } + } + + foreach (var track in CurrentProjectFile.TrainsFiles) + { + string filename = track.FilePath; + if (!File.Exists(filename)) + { + filename = cpath + "\\" + filename; + } + if (File.Exists(filename)) + { + LoadTrainTrackFromFile(track, filename); + } + else + { + MessageBox.Show("Couldn't find file: " + filename); + } + } + + foreach (var scenario in CurrentProjectFile.ScenarioFiles) + { + string filename = scenario.FilePath; + if (!File.Exists(filename)) + { + filename = cpath + "\\" + filename; + } + if (File.Exists(filename)) + { + LoadScenarioFromFile(scenario, filename); + } + else + { + MessageBox.Show("Couldn't find file: " + filename); + } + } + + + LoadProjectUI(); + } + + public void SaveProject(bool saveas = false) + { + if (CurrentProjectFile == null) return; + if (string.IsNullOrEmpty(CurrentProjectFile.Filepath) || saveas) + { + string fileName = ShowSaveDialog("CodeWalker Projects|*.cwproj", CurrentProjectFile.Filepath); + if (string.IsNullOrEmpty(fileName)) + { return; } //user cancelled + + string oldpath = CurrentProjectFile.Filepath; + CurrentProjectFile.Filepath = fileName; + CurrentProjectFile.Filename = new FileInfo(fileName).Name; + CurrentProjectFile.UpdateFilenames(oldpath); + } + + CurrentProjectFile.Save(); + + SetProjectHasChanged(false); + } + + private void CloseProject() + { + if (CurrentProjectFile == null) return; + + foreach (var ymap in CurrentProjectFile.YmapFiles) + { + if ((ymap != null) && (ymap.HasChanged)) + { + //save the current ymap first? + if (MessageBox.Show("Would you like to save "+ymap.Name+" before closing?", "Save .ymap before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + CurrentYmapFile = ymap; + SaveYmap(); + } + } + } + + foreach (var ynd in CurrentProjectFile.YndFiles) + { + if ((ynd != null) && (ynd.HasChanged)) + { + //save the current ynd first? + if (MessageBox.Show("Would you like to save " + ynd.Name + " before closing?", "Save .ynd before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + CurrentYndFile = ynd; + SaveYnd(); + } + } + } + + foreach (var ynv in CurrentProjectFile.YnvFiles) + { + if ((ynv != null) && (ynv.HasChanged)) + { + //save the current ynv first? + if (MessageBox.Show("Would you like to save " + ynv.Name + " before closing?", "Save .ynv before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + CurrentYnvFile = ynv; + SaveYnv(); + } + } + } + + foreach (var trains in CurrentProjectFile.TrainsFiles) + { + if ((trains != null) && (trains.HasChanged)) + { + //save the current trains file first? + if (MessageBox.Show("Would you like to save " + trains.Name + " before closing?", "Save trains file before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + CurrentTrainTrack = trains; + SaveTrainTrack(); + } + } + } + + foreach (var scenario in CurrentProjectFile.ScenarioFiles) + { + if ((scenario != null) && (scenario.HasChanged)) + { + //save the current scenario file first? + if (MessageBox.Show("Would you like to save " + scenario.Name + " before closing?", "Save scenario file before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + CurrentScenario = scenario; + SaveScenario(); + } + } + } + + + if (CurrentProjectFile.HasChanged) + { + //save the current project first? + if (MessageBox.Show("Would you like to save the current project before closing?", "Save project before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + SaveProject(); + } + } + + CurrentProjectFile = null; + CurrentYmapFile = null; + CurrentYndFile = null; + + LoadProjectUI(); + + + if (WorldForm != null) + { + WorldForm.SelectItem(null, null, null);//make sure current selected item isn't still selected... + } + } + + private void LoadProjectUI() + { + RefreshProjectUI(); + UpdateFormTitleText(); + LoadProjectTree(); + LoadProjectTabPage(); + RefreshUI(); + } + + + private void LoadProjectTree() + { + ProjectTreeView.Nodes.Clear(); + + if (CurrentProjectFile == null) return; + + var pcstr = CurrentProjectFile.HasChanged ? "*" : ""; + + var projnode = ProjectTreeView.Nodes.Add(pcstr + CurrentProjectFile.Name); + projnode.Tag = CurrentProjectFile; + + + if (CurrentProjectFile.YmapFiles.Count > 0) + { + var ymapsnode = projnode.Nodes.Add("Ymap Files"); + ymapsnode.Name = "Ymap"; + + foreach (var ymapfile in CurrentProjectFile.YmapFiles) + { + var ycstr = ymapfile.HasChanged ? "*" : ""; + string name = ymapfile.Name; + if (ymapfile.RpfFileEntry != null) + { + name = ymapfile.RpfFileEntry.Name; + } + var ymapnode = ymapsnode.Nodes.Add(ycstr + name); + ymapnode.Tag = ymapfile; + + LoadYmapTreeNodes(ymapfile, ymapnode); + + JenkIndex.Ensure(name); + JenkIndex.Ensure(Path.GetFileNameWithoutExtension(name)); + } + ymapsnode.Expand(); + } + + if (CurrentProjectFile.YndFiles.Count > 0) + { + var yndsnode = projnode.Nodes.Add("Ynd Files"); + yndsnode.Name = "Ynd"; + + foreach (var yndfile in CurrentProjectFile.YndFiles) + { + var ycstr = yndfile.HasChanged ? "*" : ""; + string name = yndfile.Name; + if (yndfile.RpfFileEntry != null) + { + name = yndfile.RpfFileEntry.Name; + } + var yndnode = yndsnode.Nodes.Add(ycstr + name); + yndnode.Tag = yndfile; + + LoadYndTreeNodes(yndfile, yndnode); + } + yndsnode.Expand(); + } + + if (CurrentProjectFile.YnvFiles.Count > 0) + { + var ynvsnode = projnode.Nodes.Add("Ynv Files"); + ynvsnode.Name = "Ynv"; + + foreach (var ynvfile in CurrentProjectFile.YnvFiles) + { + var ycstr = ynvfile.HasChanged ? "*" : ""; + string name = ynvfile.Name; + if (ynvfile.RpfFileEntry != null) + { + name = ynvfile.RpfFileEntry.Name; + } + var ynvnode = ynvsnode.Nodes.Add(ycstr + name); + ynvnode.Tag = ynvfile; + + LoadYnvTreeNodes(ynvfile, ynvnode); + } + ynvsnode.Expand(); + } + + if (CurrentProjectFile.TrainsFiles.Count > 0) + { + var trainsnode = projnode.Nodes.Add("Trains Files"); + trainsnode.Name = "Trains"; + + foreach (var trainfile in CurrentProjectFile.TrainsFiles) + { + var tcstr = trainfile.HasChanged ? "*" : ""; + string name = trainfile.Name; + if (trainfile.RpfFileEntry != null) + { + name = trainfile.RpfFileEntry.Name; + } + var trainnode = trainsnode.Nodes.Add(tcstr + name); + trainnode.Tag = trainfile; + + LoadTrainTrackTreeNodes(trainfile, trainnode); + } + trainsnode.Expand(); + } + + if (CurrentProjectFile.ScenarioFiles.Count > 0) + { + var scenariosnode = projnode.Nodes.Add("Scenario Files"); + scenariosnode.Name = "Scenarios"; + + foreach (var scenariofile in CurrentProjectFile.ScenarioFiles) + { + var scstr = scenariofile.HasChanged ? "*" : ""; + string name = scenariofile.Name; + if (scenariofile.RpfFileEntry != null) + { + name = scenariofile.RpfFileEntry.Name; + } + var scenarionode = scenariosnode.Nodes.Add(scstr + name); + scenarionode.Tag = scenariofile; + + LoadScenarioTreeNodes(scenariofile, scenarionode); + } + scenariosnode.Expand(); + } + + projnode.Expand(); + + } + + private void LoadProjectTabPage() + { + if (CurrentProjectFile == null) + { + ProjectPanel.Enabled = false; + ProjectNameTextBox.Text = ""; + ProjectVersionLabel.Text = "Version: -"; + } + else + { + ProjectPanel.Enabled = true; + ProjectNameTextBox.Text = CurrentProjectFile.Name; + ProjectVersionLabel.Text = "Version: " + CurrentProjectFile.Version.ToString(); + } + } + + private void SetProjectHasChanged(bool changed) + { + if (CurrentProjectFile == null) return; + + CurrentProjectFile.HasChanged = changed; + + if (ProjectTreeView.Nodes.Count > 0) + { + //first node is the project... + string changestr = changed ? "*" : ""; + ProjectTreeView.Nodes[0].Text = changestr + CurrentProjectFile.Name; + } + + UpdateFormTitleText(); + } + + + + public void NewYmap() + { + if (CurrentProjectFile == null) + { + NewProject(); + } + if (CurrentProjectFile == null) return; + + int testi = 1; + string fname = string.Empty; + bool filenameok = false; + while (!filenameok) + { + fname = "map" + testi.ToString() + ".ymap"; + filenameok = !CurrentProjectFile.ContainsYmap(fname); + testi++; + } + + lock (ymapsyncroot) + { + YmapFile ymap = CurrentProjectFile.AddYmapFile(fname); + if (ymap != null) + { + ymap.Loaded = true; + ymap.HasChanged = true; //new ymap, flag as not saved + ymap._CMapData.contentFlags = 65; //stream flags value + } + } + + CurrentProjectFile.HasChanged = true; + + LoadProjectTree(); + } + + public void OpenYmap() + { + string[] files = ShowOpenDialogMulti("Ymap files|*.ymap", string.Empty); + if (files == null) + { + return; + } + + if (CurrentProjectFile == null) + { + NewProject(); + } + + foreach (string file in files) + { + if (!File.Exists(file)) continue; + + var ymap = CurrentProjectFile.AddYmapFile(file); + + if (ymap != null) + { + SetProjectHasChanged(true); + + LoadYmapFromFile(ymap, file); + + LoadProjectTree(); + } + else + { + MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); + } + + } + } + + public void SaveYmap(bool saveas = false) + { + + if (CurrentYmapFile == null) return; + string ymapname = CurrentYmapFile.Name; + string filepath = CurrentYmapFile.FilePath; + if (string.IsNullOrEmpty(filepath)) + { + filepath = ymapname; + } + string origfile = filepath; + if (!File.Exists(filepath)) + { + saveas = true; + } + + + byte[] data; + lock (ymapsyncroot) //need to sync writes to ymap objects... + { + saveas = saveas || string.IsNullOrEmpty(filepath); + if (saveas) + { + filepath = ShowSaveDialog("Ymap files|*.ymap", filepath); + if (string.IsNullOrEmpty(filepath)) + { return; } + + string newname = Path.GetFileNameWithoutExtension(filepath); + JenkIndex.Ensure(newname); + CurrentYmapFile.FilePath = filepath; + CurrentYmapFile.RpfFileEntry.Name = new FileInfo(filepath).Name; + CurrentYmapFile.Name = CurrentYmapFile.RpfFileEntry.Name; + CurrentYmapFile._CMapData.name = new MetaHash(JenkHash.GenHash(newname)); + } + + data = CurrentYmapFile.Save(); + } + + + if (data != null) + { + File.WriteAllBytes(filepath, data); + } + + SetYmapHasChanged(false); + + if (saveas) + { + LoadYmapTabPage(); + if (CurrentProjectFile != null) + { + //string newname = CurrentYmapFile.Name; + string origpath = CurrentProjectFile.GetRelativePath(origfile); + string newpath = CurrentProjectFile.GetRelativePath(CurrentYmapFile.FilePath); + + if (!CurrentProjectFile.RenameYmap(origpath, newpath)) + { //couldn't rename it in the project? + MessageBox.Show("Couldn't rename ymap in project! This shouldn't happen - check the project file XML."); + } + } + SetProjectHasChanged(true); + SetCurrentSaveItem(); + } + + if (CurrentYmapFile.SaveWarnings != null) + { + string w = string.Join("\n", CurrentYmapFile.SaveWarnings); + MessageBox.Show(CurrentYmapFile.SaveWarnings.Count.ToString() + " warnings were generated while saving the ymap:\n" + w); + CurrentYmapFile.SaveWarnings = null;//clear it out for next time.. + } + } + + private void AddYmapToProject(YmapFile ymap) + { + if (ymap == null) return; + if (CurrentProjectFile == null) + { + NewProject(); + } + if (YmapExistsInProject(ymap)) return; + if (CurrentProjectFile.AddYmapFile(ymap)) + { + ymap.HasChanged = true; + CurrentProjectFile.HasChanged = true; + LoadProjectTree(); + } + CurrentYmapFile = ymap; + RefreshUI(); + if (CurrentEntity != null) + { + TrySelectEntityTreeNode(CurrentEntity); + } + else if (CurrentCarGen != null) + { + TrySelectCarGenTreeNode(CurrentCarGen); + } + } + + private void RemoveYmapFromProject() + { + if (CurrentYmapFile == null) return; + if (CurrentProjectFile == null) return; + CurrentProjectFile.RemoveYmapFile(CurrentYmapFile); + CurrentYmapFile = null; + LoadProjectTree(); + RefreshUI(); + } + + private void LoadYmapTabPage() + { + if (CurrentYmapFile == null) + { + YmapPanel.Enabled = false; + YmapNameTextBox.Text = ""; + YmapNameHashLabel.Text = "Hash: 0"; + YmapParentTextBox.Text = string.Empty; + YmapParentHashLabel.Text = "Hash: 0"; + YmapFlagsTextBox.Text = string.Empty; + YmapContentFlagsTextBox.Text = string.Empty; + YmapCFlagsHDCheckBox.Checked = false; + YmapCFlagsLODCheckBox.Checked = false; + YmapCFlagsSLOD2CheckBox.Checked = false; + YmapCFlagsInteriorCheckBox.Checked = false; + YmapCFlagsSLODCheckBox.Checked = false; + YmapCFlagsOcclusionCheckBox.Checked = false; + YmapCFlagsPhysicsCheckBox.Checked = false; + YmapCFlagsLODLightsCheckBox.Checked = false; + YmapCFlagsDistLightsCheckBox.Checked = false; + YmapCFlagsCriticalCheckBox.Checked = false; + YmapCFlagsGrassCheckBox.Checked = false; + YmapFlagsScriptedCheckBox.Checked = false; + YmapFlagsLODCheckBox.Checked = false; + YmapPhysicsDictionariesTextBox.Text = string.Empty; + YmapEntitiesExtentsMinTextBox.Text = string.Empty; + YmapEntitiesExtentsMaxTextBox.Text = string.Empty; + YmapStreamingExtentsMinTextBox.Text = string.Empty; + YmapStreamingExtentsMaxTextBox.Text = string.Empty; + YmapFileLocationTextBox.Text = string.Empty; + YmapProjectPathTextBox.Text = string.Empty; + } + else + { + populatingui = true; + var md = CurrentYmapFile.CMapData; + if (md.name.Hash == 0) + { + string name = Path.GetFileNameWithoutExtension(CurrentYmapFile.Name); + JenkIndex.Ensure(name); + md.name = new MetaHash(JenkHash.GenHash(name)); + } + + YmapPanel.Enabled = true; + YmapNameTextBox.Text = md.name.ToString(); + YmapNameHashLabel.Text = "Hash: " + md.name.Hash.ToString(); + YmapParentTextBox.Text = md.parent.ToString(); + YmapParentHashLabel.Text = "Hash: " + md.parent.Hash.ToString(); + YmapEntitiesExtentsMinTextBox.Text = FloatUtil.GetVector3String(md.entitiesExtentsMin); + YmapEntitiesExtentsMaxTextBox.Text = FloatUtil.GetVector3String(md.entitiesExtentsMax); + YmapStreamingExtentsMinTextBox.Text = FloatUtil.GetVector3String(md.streamingExtentsMin); + YmapStreamingExtentsMaxTextBox.Text = FloatUtil.GetVector3String(md.streamingExtentsMax); + YmapFileLocationTextBox.Text = CurrentYmapFile.FilePath; + YmapProjectPathTextBox.Text = (CurrentProjectFile != null) ? CurrentProjectFile.GetRelativePath(CurrentYmapFile.FilePath) : CurrentYmapFile.FilePath; + + UpdateYmapFlagsUI(true, true); + + UpdateYmapPhysicsDictionariesUI(); + + populatingui = false; + + ////struct CMapData: + //MetaHash name { get; set; } //8 8: Hash: 0: name + //MetaHash parent { get; set; } //12 12: Hash: 0: parent + //uint flags { get; set; } //16 16: UnsignedInt: 0: flags + //uint contentFlags { get; set; } //20 20: UnsignedInt: 0: contentFlags//1785155637 + //Vector3 streamingExtentsMin { get; set; } //32 32: Float_XYZ: 0: streamingExtentsMin//3710026271 + //Vector3 streamingExtentsMax { get; set; } //48 48: Float_XYZ: 0: streamingExtentsMax//2720965429 + //Vector3 entitiesExtentsMin { get; set; } //64 64: Float_XYZ: 0: entitiesExtentsMin//477478129 + //Vector3 entitiesExtentsMax { get; set; } //80 80: Float_XYZ: 0: entitiesExtentsMax//1829192759 + //Array_StructurePointer entities { get; set; } //96 96: Array: 0: entities {0: StructurePointer: 0: 256} + //Array_Structure containerLods { get; set; } //112 112: Array: 0: containerLods//2935983381 {0: Structure: 372253349: 256} + //Array_Structure boxOccluders { get; set; } //128 128: Array: 0: boxOccluders//3983590932 {0: Structure: SectionUNKNOWN7: 256} + //Array_Structure occludeModels { get; set; } //144 144: Array: 0: occludeModels//2132383965 {0: Structure: SectionUNKNOWN5: 256} + //Array_uint physicsDictionaries { get; set; } //160 160: Array: 0: physicsDictionaries//949589348 {0: Hash: 0: 256} + //rage__fwInstancedMapData instancedData { get; set; } //176 176: Structure: rage__fwInstancedMapData: instancedData//2569067561 + //Array_Structure timeCycleModifiers { get; set; } //224 224: Array: 0: timeCycleModifiers {0: Structure: CTimeCycleModifier: 256} + //Array_Structure carGenerators { get; set; } //240 240: Array: 0: carGenerators//3254823756 {0: Structure: CCarGen: 256} + //CLODLight LODLightsSOA { get; set; } //256 256: Structure: CLODLight: LODLightsSOA//1774371066 + //CDistantLODLight DistantLODLightsSOA { get; set; } //392 392: Structure: CDistantLODLight: DistantLODLightsSOA//2954466641 + //CBlockDesc block { get; set; } //440 440: Structure: CBlockDesc//3072355914: block + + } + } + + private void LoadYmapFromFile(YmapFile ymap, string filename) + { + byte[] data = File.ReadAllBytes(filename); + + ymap.Load(data); + + GameFileCache.InitYmapEntityArchetypes(ymap); //this needs to be done after calling YmapFile.Load() + } + + private void LoadYmapTreeNodes(YmapFile ymap, TreeNode node) + { + if (ymap == null) return; + + if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Entities and CarGens + + node.Nodes.Clear(); + + if ((ymap.AllEntities != null)&& (ymap.AllEntities.Length > 0)) + { + var entsnode = node.Nodes.Add("Entities (" + ymap.AllEntities.Length.ToString() + ")"); + entsnode.Name = "Entities"; + entsnode.Tag = ymap; + var ents = ymap.AllEntities; + for (int i = 0; i < ents.Length; i++) + { + var ent = ents[i]; + var edef = ent.CEntityDef; + var enode = entsnode.Nodes.Add(edef.archetypeName.ToString()); + enode.Tag = ent; + } + } + if ((ymap.CarGenerators != null) && (ymap.CarGenerators.Length > 0)) + { + var cargensnode = node.Nodes.Add("Car Generators (" + ymap.CarGenerators.Length.ToString() + ")"); + cargensnode.Name = "CarGens"; + cargensnode.Tag = ymap; + var cargens = ymap.CarGenerators; + for (int i = 0; i < cargens.Length; i++) + { + var cargen = cargens[i]; + var ccgnode = cargensnode.Nodes.Add(cargen.ToString()); + ccgnode.Tag = cargen; + } + } + + } + + private void SetYmapHasChanged(bool changed) + { + if (CurrentYmapFile == null) return; + + bool changechange = changed != CurrentYmapFile.HasChanged; + if (!changechange) return; + + CurrentYmapFile.HasChanged = changed; + + SetYmapHasChangedUI(changed); + } + + private void SetYmapHasChangedUI(bool changed) + { + if (ProjectTreeView.Nodes.Count > 0) + { + var pnode = ProjectTreeView.Nodes[0]; + var ymnode = GetChildTreeNode(pnode, "Ymap"); + if (ymnode == null) return; + string changestr = changed ? "*" : ""; + for (int i = 0; i < ymnode.Nodes.Count; i++) + { + var ynode = ymnode.Nodes[i]; + if (ynode.Tag == CurrentYmapFile) + { + string name = CurrentYmapFile.Name; + if (CurrentYmapFile.RpfFileEntry != null) + { + name = CurrentYmapFile.RpfFileEntry.Name; + } + ynode.Text = changestr + name; + break; + } + } + } + } + + private void UpdateYmapFlagsUI(bool updateCheckboxes, bool updateTextboxes) + { + if (CurrentYmapFile == null) return; + + var md = CurrentYmapFile.CMapData; + var flags = md.flags; + var contentFlags = md.contentFlags; + + if (updateCheckboxes) + { + YmapCFlagsHDCheckBox.Checked = IsBitSet(contentFlags, 0); //1 + YmapCFlagsLODCheckBox.Checked = IsBitSet(contentFlags, 1); //2 + YmapCFlagsSLOD2CheckBox.Checked = IsBitSet(contentFlags, 2); //4 + YmapCFlagsInteriorCheckBox.Checked = IsBitSet(contentFlags, 3); //8 + YmapCFlagsSLODCheckBox.Checked = IsBitSet(contentFlags, 4); //16 + YmapCFlagsOcclusionCheckBox.Checked = IsBitSet(contentFlags, 5); //32 + YmapCFlagsPhysicsCheckBox.Checked = IsBitSet(contentFlags, 6); //64 + YmapCFlagsLODLightsCheckBox.Checked = IsBitSet(contentFlags, 7); //128 + YmapCFlagsDistLightsCheckBox.Checked = IsBitSet(contentFlags, 8); //256 + YmapCFlagsCriticalCheckBox.Checked = IsBitSet(contentFlags, 9); //512 + YmapCFlagsGrassCheckBox.Checked = IsBitSet(contentFlags, 10); //1024 + + YmapFlagsScriptedCheckBox.Checked = IsBitSet(flags, 0); //1 + YmapFlagsLODCheckBox.Checked = IsBitSet(flags, 1); //2 + } + if (updateTextboxes) + { + YmapFlagsTextBox.Text = flags.ToString(); + YmapContentFlagsTextBox.Text = contentFlags.ToString(); + } + } + + private void SetYmapFlagsFromCheckBoxes() + { + if (populatingui) return; + if (CurrentYmapFile == null) return; + + uint flags = 0; + uint contentFlags = 0; + + contentFlags = UpdateBit(contentFlags, 0, YmapCFlagsHDCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 1, YmapCFlagsLODCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 2, YmapCFlagsSLOD2CheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 3, YmapCFlagsInteriorCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 4, YmapCFlagsSLODCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 5, YmapCFlagsOcclusionCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 6, YmapCFlagsPhysicsCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 7, YmapCFlagsLODLightsCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 8, YmapCFlagsDistLightsCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 9, YmapCFlagsCriticalCheckBox.Checked); + contentFlags = UpdateBit(contentFlags, 10, YmapCFlagsGrassCheckBox.Checked); + + flags = UpdateBit(flags, 0, YmapFlagsScriptedCheckBox.Checked); + flags = UpdateBit(flags, 1, YmapFlagsLODCheckBox.Checked); + + + lock (ymapsyncroot) + { + if (CurrentYmapFile._CMapData.flags != flags) + { + CurrentYmapFile._CMapData.flags = flags; + SetYmapHasChanged(true); + } + if (CurrentYmapFile._CMapData.contentFlags != contentFlags) + { + CurrentYmapFile._CMapData.contentFlags = contentFlags; + SetYmapHasChanged(true); + } + } + + populatingui = true; + UpdateYmapFlagsUI(false, true); //update textbox + populatingui = false; + } + + private void SetYmapFlagsFromTextBoxes() + { + if (populatingui) return; + if (CurrentYmapFile == null) return; + + uint flags = 0; + uint contentFlags = 0; + uint.TryParse(YmapFlagsTextBox.Text, out flags); + uint.TryParse(YmapContentFlagsTextBox.Text, out contentFlags); + lock (ymapsyncroot) + { + if (CurrentYmapFile._CMapData.flags != flags) + { + CurrentYmapFile._CMapData.flags = flags; + SetYmapHasChanged(true); + } + if (CurrentYmapFile._CMapData.contentFlags != contentFlags) + { + CurrentYmapFile._CMapData.contentFlags = contentFlags; + SetYmapHasChanged(true); + } + } + + populatingui = true; + UpdateYmapFlagsUI(true, false); //update checkboxes + populatingui = false; + } + + private void CalcYmapFlags() + { + if (populatingui) return; + if (CurrentYmapFile == null) return; + + uint flags = 0; + uint contentFlags = 0; + + if (CurrentYmapFile.AllEntities != null) + { + foreach (var yent in CurrentYmapFile.AllEntities) + { + var cent = yent.CEntityDef; + switch (cent.lodLevel) + { + case Unk_1264241711.LODTYPES_DEPTH_ORPHANHD: + case Unk_1264241711.LODTYPES_DEPTH_HD: + contentFlags = SetBit(contentFlags, 0); //1 + break; + case Unk_1264241711.LODTYPES_DEPTH_LOD: + contentFlags = SetBit(contentFlags, 1); //2 + flags = SetBit(flags, 1); //2 + break; + case Unk_1264241711.LODTYPES_DEPTH_SLOD1: + contentFlags = SetBit(contentFlags, 4); //16 + flags = SetBit(flags, 1); //2 + break; + case Unk_1264241711.LODTYPES_DEPTH_SLOD2: + case Unk_1264241711.LODTYPES_DEPTH_SLOD3: + case Unk_1264241711.LODTYPES_DEPTH_SLOD4: + contentFlags = SetBit(contentFlags, 2); //4 + contentFlags = SetBit(contentFlags, 4); //16 + flags = SetBit(flags, 1); //2 + break; + } + } + } + + if (CurrentYmapFile.CMloInstanceDefs != null) + { + if (CurrentYmapFile.CMloInstanceDefs.Length > 0) + { + contentFlags = SetBit(contentFlags, 3); //8 + } + } + if (CurrentYmapFile.physicsDictionaries != null) + { + if (CurrentYmapFile.physicsDictionaries.Length > 0) + { + contentFlags = SetBit(contentFlags, 6); //64 + } + } + + lock (ymapsyncroot) + { + if (CurrentYmapFile._CMapData.flags != flags) + { + CurrentYmapFile._CMapData.flags = flags; + SetYmapHasChanged(true); + } + if (CurrentYmapFile._CMapData.contentFlags != contentFlags) + { + CurrentYmapFile._CMapData.contentFlags = contentFlags; + SetYmapHasChanged(true); + } + } + + populatingui = true; + UpdateYmapFlagsUI(true, true); //update checkboxes and textboxes + populatingui = false; + } + + private void CalcYmapExtents() + { + if (CurrentYmapFile == null) return; + + var allents = CurrentYmapFile.AllEntities; + var allbatches = CurrentYmapFile.GrassInstanceBatches; + + if ((allents == null) && (allbatches == null)) + { + MessageBox.Show("No items to calculate extents from."); + return; + } + + Vector3 emin = new Vector3(float.MaxValue); + Vector3 emax = new Vector3(float.MinValue); + Vector3 smin = new Vector3(float.MaxValue); + Vector3 smax = new Vector3(float.MinValue); + Vector3[] c = new Vector3[8]; + Vector3[] s = new Vector3[8]; + + if (allents != null) + { + for (int i = 0; i < allents.Length; i++) + { + var ent = allents[i]; + var arch = ent.Archetype; + var ori = ent.Orientation; + float loddist = ent._CEntityDef.lodDist; + + Vector3 bbmin = ent.Position - ent.BSRadius; //sphere + Vector3 bbmax = ent.Position + ent.BSRadius; + Vector3 sbmin = bbmin - loddist; + Vector3 sbmax = bbmax + loddist; + if (arch != null) + { + if (loddist <= 0.0f) + { + loddist = arch.LodDist; + } + + Vector3 abmin = arch.BBMin * ent.Scale; //entity box + Vector3 abmax = arch.BBMax * ent.Scale; + c[0] = abmin; + c[1] = new Vector3(abmin.X, abmin.Y, abmax.Z); + c[2] = new Vector3(abmin.X, abmax.Y, abmin.Z); + c[3] = new Vector3(abmin.X, abmax.Y, abmax.Z); + c[4] = new Vector3(abmax.X, abmin.Y, abmin.Z); + c[5] = new Vector3(abmax.X, abmin.Y, abmax.Z); + c[6] = new Vector3(abmax.X, abmax.Y, abmin.Z); + c[7] = abmax; + + abmin = arch.BBMin * ent.Scale - loddist; //streaming box + abmax = arch.BBMax * ent.Scale + loddist; + s[0] = abmin; + s[1] = new Vector3(abmin.X, abmin.Y, abmax.Z); + s[2] = new Vector3(abmin.X, abmax.Y, abmin.Z); + s[3] = new Vector3(abmin.X, abmax.Y, abmax.Z); + s[4] = new Vector3(abmax.X, abmin.Y, abmin.Z); + s[5] = new Vector3(abmax.X, abmin.Y, abmax.Z); + s[6] = new Vector3(abmax.X, abmax.Y, abmin.Z); + s[7] = abmax; + + bbmin = new Vector3(float.MaxValue); + bbmax = new Vector3(float.MinValue); + sbmin = new Vector3(float.MaxValue); + sbmax = new Vector3(float.MinValue); + for (int j = 0; j < 8; j++) + { + Vector3 corn = ori.Multiply(c[j]) + ent.Position; + bbmin = Vector3.Min(bbmin, corn); + bbmax = Vector3.Max(bbmax, corn); + + corn = ori.Multiply(s[j]) + ent.Position; + sbmin = Vector3.Min(sbmin, corn); + sbmax = Vector3.Max(sbmax, corn); + } + } + + emin = Vector3.Min(emin, bbmin); + emax = Vector3.Max(emax, bbmax); + + smin = Vector3.Min(smin, sbmin); + smax = Vector3.Max(smax, sbmax); + } + } + + if (allbatches != null) + { + var lodoffset = Vector3.Zero;// new Vector3(0, 0, 100); //IDK WHY -neos7 + foreach (var batch in allbatches) //thanks to Neos7 + { + emin = Vector3.Min(emin, batch.AABBMin); + emax = Vector3.Max(emax, batch.AABBMax); + + smin = Vector3.Min(smin, (batch.AABBMin - batch.Batch.lodDist) + lodoffset); + smax = Vector3.Min(smax, (batch.AABBMax + batch.Batch.lodDist) - lodoffset); + } + } + + + + + YmapEntitiesExtentsMinTextBox.Text = FloatUtil.GetVector3String(emin); + YmapEntitiesExtentsMaxTextBox.Text = FloatUtil.GetVector3String(emax); + YmapStreamingExtentsMinTextBox.Text = FloatUtil.GetVector3String(smin); + YmapStreamingExtentsMaxTextBox.Text = FloatUtil.GetVector3String(smax); + + } + + private void UpdateYmapPhysicsDictionariesUI() + { + if ((CurrentYmapFile == null) || (CurrentYmapFile.physicsDictionaries == null)) + { + YmapPhysicsDictionariesTextBox.Text = string.Empty; + } + else + { + StringBuilder sb = new StringBuilder(); + foreach (var hash in CurrentYmapFile.physicsDictionaries) + { + sb.AppendLine(hash.ToString()); + } + YmapPhysicsDictionariesTextBox.Text = sb.ToString(); + } + } + + private void SetYmapPhysicsDictionariesFromTextbox() + { + if (populatingui) return; + if (CurrentYmapFile == null) return; + + List hashes = new List(); + + var strs = YmapPhysicsDictionariesTextBox.Text.Split('\n'); + foreach (var str in strs) + { + var tstr = str.Trim(); + if (!string.IsNullOrEmpty(tstr)) + { + uint h = 0; + if (uint.TryParse(tstr, out h)) + { + hashes.Add(h); + } + else + { + h = JenkHash.GenHash(tstr.ToLower()); + hashes.Add(h); + } + } + } + + lock (ymapsyncroot) + { + CurrentYmapFile.physicsDictionaries = (hashes.Count > 0) ? hashes.ToArray() : null; + SetYmapHasChanged(true); + } + } + + + private Vector3 GetSpawnPos(float dist) + { + Vector3 pos = Vector3.Zero; + if (WorldForm != null) + { + Vector3 campos = WorldForm.GetCameraPosition(); + Vector3 camdir = WorldForm.GetCameraViewDir(); + pos = campos + camdir * dist; + } + return pos; + } + + + public void NewEntity(YmapEntityDef copy = null, bool copyPosition = false) + { + if (CurrentYmapFile == null) return; + + + + float spawndist = 5.0f; //use archetype BSradius if starting with a copy... + if (copy != null) + { + spawndist = copy.BSRadius * 2.5f; + } + bool cp = copyPosition && (copy != null); + Vector3 pos = cp ? copy.Position : GetSpawnPos(spawndist); + + + CEntityDef cent = new CEntityDef(); + cent.archetypeName = new MetaHash(JenkHash.GenHash("prop_alien_egg_01")); + cent.rotation = new Vector4(0, 0, 0, 1); + cent.scaleXY = 1.0f; + cent.scaleZ = 1.0f; + cent.flags = 1572872; + cent.parentIndex = -1; + cent.lodDist = 200.0f; + cent.lodLevel = Unk_1264241711.LODTYPES_DEPTH_ORPHANHD; + cent.priorityLevel = Unk_648413703.PRI_REQUIRED; + cent.ambientOcclusionMultiplier = 255; + cent.artificialAmbientOcclusion = 255; + + if (copy != null) + { + cent = copy.CEntityDef; + //TODO: copy entity extensions! + } + + cent.position = pos; + + + YmapEntityDef ent = new YmapEntityDef(CurrentYmapFile, 0, ref cent); + + ent.SetArchetype(GameFileCache.GetArchetype(cent.archetypeName)); + + if (WorldForm != null) + { + lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... + { + CurrentYmapFile.AddEntity(ent); + } + } + else + { + CurrentYmapFile.AddEntity(ent); + } + + + LoadProjectTree(); + + TrySelectEntityTreeNode(ent); + CurrentEntity = ent; + LoadEntityTabPage(); + } + + public bool DeleteEntity() + { + if (CurrentYmapFile == null) return false; + if (CurrentEntity == null) return false; + if (CurrentEntity.Ymap != CurrentYmapFile) return false; + if (CurrentYmapFile.AllEntities == null) return false; //nothing to delete.. + if (CurrentYmapFile.RootEntities == null) return false; //nothing to delete.. + + if (CurrentEntity._CEntityDef.numChildren != 0) + { + MessageBox.Show("This entity's numChildren is not 0 - deleting entities with children is not currently supported by CodeWalker."); + return true; + } + + int idx = CurrentEntity.Index; + for (int i = idx + 1; i < CurrentYmapFile.AllEntities.Length; i++) + { + var ent = CurrentYmapFile.AllEntities[i]; + if (ent._CEntityDef.numChildren != 0) + { + MessageBox.Show("There are other entities present in this .ymap that have children. Deleting this entity is not currently supported by CodeWalker."); + return true; + } + } + + if (MessageBox.Show("Are you sure you want to delete this entity?\n" + CurrentEntity._CEntityDef.archetypeName.ToString() + "\n" + CurrentEntity.Position.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return true; + } + + //find this now to remove it later. + var tn = FindEntityTreeNode(CurrentEntity); + + bool res = false; + if (WorldForm != null) + { + lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... + { + res = CurrentYmapFile.RemoveEntity(CurrentEntity); + + //WorldForm.SelectItem(null, null, null); + } + } + else + { + res = CurrentYmapFile.RemoveEntity(CurrentEntity); + } + if (!res) + { + MessageBox.Show("Entity.Index didn't match the index of the entity in the ymap. This shouldn't happen, check LOD linkages!"); + } + + SetYmapHasChangedUI(true); + + CurrentEntity = null; + if ((tn != null) && (tn.Parent != null)) + { + tn.Parent.Text = "Entities (" + CurrentYmapFile.AllEntities.Length.ToString() + ")"; + tn.Parent.Nodes.Remove(tn); + } + else + { + //no need for this when removing the node above will select something else. + LoadEntityTabPage(); //this case really shouldn't happen... + } + + return true; + } + + private void AddEntityToProject() + { + if (CurrentEntity == null) return; + + if (CurrentEntity.Ymap == null) + { + MessageBox.Show("Sorry, interior entities cannot currently be added to the project."); + return; + } + + CurrentYmapFile = CurrentEntity.Ymap; + if (!YmapExistsInProject(CurrentYmapFile)) + { + var ent = CurrentEntity; + CurrentYmapFile.HasChanged = true; + AddYmapToProject(CurrentYmapFile); + + CurrentEntity = ent; //bug fix for some reason the treeview selects the project node here. + CurrentYmapFile = ent.Ymap; + TrySelectEntityTreeNode(ent); + } + } + + private void LoadEntityTabPage() + { + if (CurrentEntity == null) + { + EntityPanel.Enabled = false; + EntityArchetypeTextBox.Text = string.Empty; + EntityArchetypeHashLabel.Text = "Hash: 0"; + EntityFlagsTextBox.Text = string.Empty; + EntityGuidTextBox.Text = string.Empty; + EntityPositionTextBox.Text = string.Empty; + EntityRotationTextBox.Text = string.Empty; + EntityScaleXYTextBox.Text = string.Empty; + EntityScaleZTextBox.Text = string.Empty; + EntityParentIndexTextBox.Text = string.Empty; + EntityLodDistTextBox.Text = string.Empty; + EntityChildLodDistTextBox.Text = string.Empty; + EntityLodLevelComboBox.SelectedIndex = 0;// Math.Max(EntityLodLevelComboBox.FindString(), 0); + EntityNumChildrenTextBox.Text = string.Empty; + EntityPriorityLevelComboBox.SelectedIndex = 0; //Math.Max(.. + EntityAOMultiplierTextBox.Text = string.Empty; + EntityArtificialAOTextBox.Text = string.Empty; + EntityTintValueTextBox.Text = string.Empty; + EntityPivotEditCheckBox.Checked = false; + EntityPivotPositionTextBox.Text = string.Empty; + EntityPivotRotationTextBox.Text = string.Empty; + } + else + { + populatingui = true; + var e = CurrentEntity.CEntityDef; + var po = CurrentEntity.PivotOrientation; + EntityPanel.Enabled = true; + EntityArchetypeTextBox.Text = e.archetypeName.ToString(); + EntityArchetypeHashLabel.Text = "Hash: " + e.archetypeName.Hash.ToString(); + EntityFlagsTextBox.Text = e.flags.ToString(); + EntityGuidTextBox.Text = e.guid.ToString(); + EntityPositionTextBox.Text = FloatUtil.GetVector3String(e.position); + EntityRotationTextBox.Text = FloatUtil.GetVector4String(e.rotation); + EntityScaleXYTextBox.Text = FloatUtil.ToString(e.scaleXY); + EntityScaleZTextBox.Text = FloatUtil.ToString(e.scaleZ); + EntityParentIndexTextBox.Text = e.parentIndex.ToString(); + EntityLodDistTextBox.Text = FloatUtil.ToString(e.lodDist); + EntityChildLodDistTextBox.Text = FloatUtil.ToString(e.childLodDist); + EntityLodLevelComboBox.SelectedIndex = Math.Max(EntityLodLevelComboBox.FindString(e.lodLevel.ToString()), 0); + EntityNumChildrenTextBox.Text = e.numChildren.ToString(); + EntityPriorityLevelComboBox.SelectedIndex = Math.Max(EntityPriorityLevelComboBox.FindString(e.priorityLevel.ToString()), 0); + EntityAOMultiplierTextBox.Text = e.ambientOcclusionMultiplier.ToString(); + EntityArtificialAOTextBox.Text = e.artificialAmbientOcclusion.ToString(); + EntityTintValueTextBox.Text = e.tintValue.ToString(); + EntityPivotPositionTextBox.Text = FloatUtil.GetVector3String(CurrentEntity.PivotPosition); + EntityPivotRotationTextBox.Text = FloatUtil.GetVector4String(new Vector4(po.X, po.Y, po.Z, po.W)); + populatingui = false; + + + + if (WorldForm != null) + { + WorldForm.SelectItem(CurrentEntity, CurrentEntity.Archetype, null); //hopefully the drawable is already loaded - this will try get from cache + } + + ////struct CEntityDef: + //MetaHash archetypeName { get; set; } //8 8: Hash: 0: archetypeName + //uint flags { get; set; } //12 12: UnsignedInt: 0: flags + //uint guid { get; set; } //16 16: UnsignedInt: 0: guid + //Vector3 position { get; set; } //32 32: Float_XYZ: 0: position + //Vector4 rotation { get; set; } //48 48: Float_XYZW: 0: rotation + //float scaleXY { get; set; } //64 64: Float: 0: 2627937847 + //float scaleZ { get; set; } //68 68: Float: 0: 284916802 + //int parentIndex { get; set; } //72 72: SignedInt: 0: parentIndex + //float lodDist { get; set; } //76 76: Float: 0: lodDist + //float childLodDist { get; set; } //80 80: Float: 0: childLodDist//3398912973 + //Unk_1264241711 lodLevel { get; set; } //84 84: IntEnum: 1264241711: lodLevel //LODTYPES_DEPTH_ + //uint numChildren { get; set; } //88 88: UnsignedInt: 0: numChildren//2793909385 + //Unk_648413703 priorityLevel { get; set; } //92 92: IntEnum: 648413703: priorityLevel//647098393 + //Array_StructurePointer extensions { get; set; } //96 96: Array: 0: extensions {0: StructurePointer: 0: 256} + //int ambientOcclusionMultiplier { get; set; } //112 112: SignedInt: 0: ambientOcclusionMultiplier//415356295 + //int artificialAmbientOcclusion { get; set; } //116 116: SignedInt: 0: artificialAmbientOcclusion//599844163 + //uint tintValue { get; set; } //120 120: UnsignedInt: 0: tintValue//1015358759 + } + } + + public bool IsCurrentEntity(YmapEntityDef ent) + { + return CurrentEntity == ent; + } + + + + public void NewCarGen(YmapCarGen copy = null, bool copyPosition = false) + { + if (CurrentYmapFile == null) return; + + + Vector3 pos = GetSpawnPos(10.0f); + + + CCarGen ccg = new CCarGen(); + ccg.flags = 3680; + ccg.orientX = 5.0f; + ccg.perpendicularLength = 2.6f; + //TODO: set default values for cargen + + if (copy != null) + { + ccg = copy.CCarGen; + } + + if (!copyPosition || (copy == null)) + { + ccg.position = pos; + } + + + YmapCarGen cg = new YmapCarGen(CurrentYmapFile, ccg); + + if (WorldForm != null) + { + lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... + { + CurrentYmapFile.AddCarGen(cg); + } + } + else + { + CurrentYmapFile.AddCarGen(cg); + } + + + LoadProjectTree(); + + TrySelectCarGenTreeNode(cg); + CurrentCarGen = cg; + LoadCarGenTabPage(); + } + + public bool DeleteCarGen() + { + if (CurrentYmapFile == null) return false; + if (CurrentCarGen == null) return false; + if (CurrentCarGen.Ymap != CurrentYmapFile) return false; + if (CurrentYmapFile.CarGenerators == null) return false; //nothing to delete.. + + if (MessageBox.Show("Are you sure you want to delete this car generator?\n" + CurrentCarGen.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return true; + } + + //find this now to remove it later. + var tn = FindCarGenTreeNode(CurrentCarGen); + + bool res = false; + if (WorldForm != null) + { + lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... + { + res = CurrentYmapFile.RemoveCarGen(CurrentCarGen); + + //WorldForm.SelectItem(null, null, null); + } + } + else + { + res = CurrentYmapFile.RemoveCarGen(CurrentCarGen); + } + if (!res) + { + MessageBox.Show("Unable to delete the car generator. This shouldn't happen!"); + } + + SetYmapHasChangedUI(true); + + CurrentCarGen = null; + if ((tn != null) && (tn.Parent != null)) + { + tn.Parent.Text = "Car Generators (" + CurrentYmapFile.CarGenerators.Length.ToString() + ")"; + tn.Parent.Nodes.Remove(tn); + } + else + { + //no need for this when removing the node above will select something else. + LoadCarGenTabPage(); //this case really shouldn't happen... + } + + return true; + } + + private void AddCarGenToProject() + { + if (CurrentCarGen == null) return; + + CurrentYmapFile = CurrentCarGen.Ymap; + if (!YmapExistsInProject(CurrentYmapFile)) + { + var cargen = CurrentCarGen; + CurrentYmapFile.HasChanged = true; + AddYmapToProject(CurrentYmapFile); + + CurrentCarGen = cargen; //bug fix for some reason the treeview selects the project node here. + CurrentYmapFile = cargen.Ymap; + TrySelectCarGenTreeNode(cargen); + } + } + + private void LoadCarGenTabPage() + { + + if (CurrentCarGen == null) + { + CarGenPanel.Enabled = false; + CarModelTextBox.Text = string.Empty; + CarModelHashLabel.Text = "Hash: 0"; + CarPopGroupTextBox.Text = string.Empty; + CarPopGroupHashLabel.Text = "Hash: 0"; + CarFlagsTextBox.Text = string.Empty; + CarPositionTextBox.Text = string.Empty; + CarOrientXTextBox.Text = string.Empty; + CarOrientYTextBox.Text = string.Empty; + CarPerpendicularLengthTextBox.Text = string.Empty; + CarBodyColorRemap1TextBox.Text = string.Empty; + CarBodyColorRemap2TextBox.Text = string.Empty; + CarBodyColorRemap3TextBox.Text = string.Empty; + CarBodyColorRemap4TextBox.Text = string.Empty; + CarLiveryTextBox.Text = string.Empty; + } + else + { + populatingui = true; + var c = CurrentCarGen.CCarGen; + CarGenPanel.Enabled = true; + CarModelTextBox.Text = c.carModel.ToString(); + CarModelHashLabel.Text = "Hash: " + c.carModel.Hash.ToString(); + CarPopGroupTextBox.Text = c.popGroup.ToString(); + CarPopGroupHashLabel.Text = "Hash: " + c.popGroup.Hash.ToString(); + CarFlagsTextBox.Text = c.flags.ToString(); + CarPositionTextBox.Text = FloatUtil.GetVector3String(c.position); + CarOrientXTextBox.Text = FloatUtil.ToString(c.orientX); + CarOrientYTextBox.Text = FloatUtil.ToString(c.orientY); + CarPerpendicularLengthTextBox.Text = FloatUtil.ToString(c.perpendicularLength); + CarBodyColorRemap1TextBox.Text = c.bodyColorRemap1.ToString(); + CarBodyColorRemap2TextBox.Text = c.bodyColorRemap2.ToString(); + CarBodyColorRemap3TextBox.Text = c.bodyColorRemap3.ToString(); + CarBodyColorRemap4TextBox.Text = c.bodyColorRemap4.ToString(); + CarLiveryTextBox.Text = c.livery.ToString(); + populatingui = false; + + if (WorldForm != null) + { + WorldForm.SelectCarGen(CurrentCarGen); + } + + ////struct CCarGen: + //Vector3 position { get; set; } //16 16: Float_XYZ: 0: position + //float orientX { get; set; } //32 32: Float: 0: orientX=735213009 + //float orientY { get; set; } //36 36: Float: 0: orientY=979440342 + //float perpendicularLength { get; set; } //40 40: Float: 0: perpendicularLength=124715667 + //MetaHash carModel { get; set; } //44 44: Hash: 0: carModel + //uint flags { get; set; } //48 48: UnsignedInt: 0: flags + //int bodyColorRemap1 { get; set; } //52 52: SignedInt: 0: bodyColorRemap1=1429703670 + //int bodyColorRemap2 { get; set; } //56 56: SignedInt: 0: bodyColorRemap2=1254848286 + //int bodyColorRemap3 { get; set; } //60 60: SignedInt: 0: bodyColorRemap3=1880965569 + //int bodyColorRemap4 { get; set; } //64 64: SignedInt: 0: bodyColorRemap4=1719152247 + //MetaHash popGroup { get; set; } //68 68: Hash: 0: popGroup=911358791 + //sbyte livery { get; set; } //72 72: SignedByte: 0: livery + } + } + + public bool IsCurrentCarGen(YmapCarGen cargen) + { + return CurrentCarGen == cargen; + } + + + + + public void NewYnd() + { + if (CurrentProjectFile == null) + { + NewProject(); + } + if (CurrentProjectFile == null) return; + + int testi = 1; + string fname = string.Empty; + bool filenameok = false; + while (!filenameok) + { + fname = "nodes" + testi.ToString() + ".ynd"; + filenameok = !CurrentProjectFile.ContainsYnd(fname); + testi++; + } + + lock (yndsyncroot) + { + YndFile ynd = CurrentProjectFile.AddYndFile(fname); + if (ynd != null) + { + ynd.Loaded = true; + ynd.HasChanged = true; //new ynd, flag as not saved + + //TODO: set new ynd default values... + ynd.NodeDictionary = new NodeDictionary(); + + + } + } + + CurrentProjectFile.HasChanged = true; + + LoadProjectTree(); + } + + public void OpenYnd() + { + string[] files = ShowOpenDialogMulti("Ynd files|*.ynd", string.Empty); + if (files == null) + { + return; + } + + if (CurrentProjectFile == null) + { + NewProject(); + } + + foreach (string file in files) + { + if (!File.Exists(file)) continue; + + var ynd = CurrentProjectFile.AddYndFile(file); + + if (ynd != null) + { + SetProjectHasChanged(true); + + LoadYndFromFile(ynd, file); + + LoadProjectTree(); + } + else + { + MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); + } + + } + } + + public void SaveYnd(bool saveas = false) + { + if ((CurrentYndFile == null) && (CurrentPathNode != null)) CurrentYndFile = CurrentPathNode.Ynd; + if (CurrentYndFile == null) return; + string yndname = CurrentYndFile.Name; + string filepath = CurrentYndFile.FilePath; + if (string.IsNullOrEmpty(filepath)) + { + filepath = yndname; + } + string origfile = filepath; + if (!File.Exists(filepath)) + { + saveas = true; + } + + + byte[] data; + lock (yndsyncroot) //need to sync writes to ynd objects... + { + saveas = saveas || string.IsNullOrEmpty(filepath); + if (saveas) + { + filepath = ShowSaveDialog("Ynd files|*.ynd", filepath); + if (string.IsNullOrEmpty(filepath)) + { return; } + + string newname = Path.GetFileNameWithoutExtension(filepath); + JenkIndex.Ensure(newname); + CurrentYndFile.FilePath = filepath; + CurrentYndFile.RpfFileEntry.Name = new FileInfo(filepath).Name; + CurrentYndFile.Name = CurrentYndFile.RpfFileEntry.Name; + } + + + data = CurrentYndFile.Save(); + } + + + if (data != null) + { + File.WriteAllBytes(filepath, data); + } + + SetYndHasChanged(false); + + if (saveas) + { + LoadYndTabPage(); + if (CurrentProjectFile != null) + { + string origpath = CurrentProjectFile.GetRelativePath(origfile); + string newpath = CurrentProjectFile.GetRelativePath(CurrentYndFile.FilePath); + if (!CurrentProjectFile.RenameYnd(origpath, newpath)) + { //couldn't rename it in the project? happens when project not saved yet... + //MessageBox.Show("Couldn't rename ynd in project! This shouldn't happen - check the project file XML."); + } + } + SetProjectHasChanged(true); + SetCurrentSaveItem(); + } + + } + + private void AddYndToProject(YndFile ynd) + { + if (ynd == null) return; + if (CurrentProjectFile == null) + { + NewProject(); + } + if (YndExistsInProject(ynd)) return; + if (CurrentProjectFile.AddYndFile(ynd)) + { + ynd.HasChanged = true; + CurrentProjectFile.HasChanged = true; + LoadProjectTree(); + } + CurrentYndFile = ynd; + RefreshUI(); + if (CurrentPathNode != null) + { + TrySelectPathNodeTreeNode(CurrentPathNode); + } + } + + private void RemoveYndFromProject() + { + if (CurrentYndFile == null) return; + if (CurrentProjectFile == null) return; + CurrentProjectFile.RemoveYndFile(CurrentYndFile); + CurrentYndFile = null; + LoadProjectTree(); + RefreshUI(); + } + + private void LoadYndTabPage() + { + if (CurrentYndFile == null) + { + YndPanel.Enabled = false; + YndRpfPathTextBox.Text = string.Empty; + YndFilePathTextBox.Text = string.Empty; + YndProjectPathTextBox.Text = string.Empty; + YndAreaIDXUpDown.Value = 0; + YndAreaIDYUpDown.Value = 0; + YndAreaIDInfoLabel.Text = "ID: 0"; + YndTotalNodesLabel.Text = "Total Nodes: 0"; + YndVehicleNodesUpDown.Value = 0; + YndVehicleNodesUpDown.Maximum = 0; + YndPedNodesUpDown.Value = 0; + YndPedNodesUpDown.Maximum = 0; + } + else + { + populatingui = true; + var nd = CurrentYndFile.NodeDictionary; + YndPanel.Enabled = true; + YndRpfPathTextBox.Text = CurrentYndFile.RpfFileEntry.Path; + YndFilePathTextBox.Text = CurrentYndFile.FilePath; + YndProjectPathTextBox.Text = (CurrentProjectFile != null) ? CurrentProjectFile.GetRelativePath(CurrentYndFile.FilePath) : CurrentYndFile.FilePath; + YndAreaIDXUpDown.Value = CurrentYndFile.CellX; + YndAreaIDYUpDown.Value = CurrentYndFile.CellY; + YndAreaIDInfoLabel.Text = "ID: " + CurrentYndFile.AreaID.ToString(); + YndTotalNodesLabel.Text = "Total Nodes: " + (nd?.NodesCount.ToString()??"0"); + YndVehicleNodesUpDown.Maximum = nd?.NodesCount??0; + YndVehicleNodesUpDown.Value = Math.Min(nd?.NodesCountVehicle??0, YndVehicleNodesUpDown.Maximum); + YndPedNodesUpDown.Maximum = nd?.NodesCount??0; + YndPedNodesUpDown.Value = Math.Min(nd?.NodesCountPed??0, YndPedNodesUpDown.Maximum); + populatingui = false; + } + } + + private void LoadYndFromFile(YndFile ynd, string filename) + { + byte[] data = File.ReadAllBytes(filename); + + ynd.Load(data); + + + + if (WorldForm != null) + { + WorldForm.UpdatePathYndGraphics(ynd, true); //links don't get drawn until something changes otherwise + //note: this is actually necessary to properly populate junctions data........ + } + } + + private void LoadYndTreeNodes(YndFile ynd, TreeNode node) + { + if (ynd == null) return; + + if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Nodes + + node.Nodes.Clear(); + + + + if ((ynd.Nodes != null) && (ynd.Nodes.Length > 0)) + { + var nodesnode = node.Nodes.Add("Nodes (" + ynd.Nodes.Length.ToString() + ")"); + nodesnode.Name = "Nodes"; + nodesnode.Tag = ynd; + var nodes = ynd.Nodes; + for (int i = 0; i < nodes.Length; i++) + { + var ynode = nodes[i]; + var nnode = ynode.RawData; + var tnode = nodesnode.Nodes.Add(nnode.ToString()); + tnode.Tag = ynode; + } + } + + } + + private void SetYndHasChanged(bool changed) + { + if (CurrentYndFile == null) return; + + bool changechange = changed != CurrentYndFile.HasChanged; + if (!changechange) return; + + CurrentYndFile.HasChanged = changed; + + SetYndHasChangedUI(changed); + } + + private void SetYndHasChangedUI(bool changed) + { + if (ProjectTreeView.Nodes.Count > 0) + { + var pnode = ProjectTreeView.Nodes[0]; + var ynnode = GetChildTreeNode(pnode, "Ynd"); + if (ynnode == null) return; + string changestr = changed ? "*" : ""; + for (int i = 0; i < ynnode.Nodes.Count; i++) + { + var ynode = ynnode.Nodes[i]; + if (ynode.Tag == CurrentYndFile) + { + string name = CurrentYndFile.Name; + if (CurrentYndFile.RpfFileEntry != null) + { + name = CurrentYndFile.RpfFileEntry.Name; + } + ynode.Text = changestr + name; + break; + } + } + } + } + + + + public void NewPathNode(YndNode copy = null, bool copyPosition = false) + { + if (CurrentYndFile == null) return; + + var n = CurrentYndFile.AddNode(); + var areaid = n.AreaID; + var nodeid = n.NodeID; + if (copy == null) + { + copy = CurrentPathNode; + } + if (copy != null) + { + n.Init(CurrentYndFile, copy.RawData); + n.LinkCountUnk = copy.LinkCountUnk; + } + n.AreaID = areaid; + n.NodeID = nodeid; + + bool cp = copyPosition && (copy != null); + Vector3 pos = cp ? copy.Position : GetSpawnPos(10.0f); + n.SetPosition(pos); + + + if (copy != null) + { + var link1 = n.AddLink(copy); + var link2 = copy.AddLink(n); + if ((copy.Links != null) && (copy.Links.Length > 0)) + { + var clink = copy.Links[0]; + link1.CopyFlags(clink); + var clnode = clink.Node2; + if (clnode.Links != null) + { + for (int i = 0; i < clnode.Links.Length; i++) + { + var clnlink = clnode.Links[i]; + if (clnlink.Node2 == copy) + { + link2.CopyFlags(clnlink); + break; + } + } + } + } + } + + CurrentYndFile.UpdateAllNodePositions(); //for the graphics... + CurrentYndFile.BuildBVH(); + + + LoadProjectTree(); + + TrySelectPathNodeTreeNode(n); + CurrentPathNode = n; + LoadYndTabPage(); + LoadPathNodeTabPage(); + + + if (WorldForm != null) + { + WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); + } + } + + public bool DeletePathNode() + { + if (CurrentYndFile == null) return false; + if (CurrentPathNode == null) return false; + if (CurrentPathNode.Ynd != CurrentYndFile) return false; + if (CurrentYndFile.Nodes == null) return false; //nothing to delete.. + + if (MessageBox.Show("Are you sure you want to delete this path node?\n" + CurrentPathNode.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return true; + } + + //find this now to remove it later. + var tn = FindPathNodeTreeNode(CurrentPathNode); + + bool res = false; + if (WorldForm != null) + { + lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... + { + res = CurrentYndFile.RemoveNode(CurrentPathNode); + + //WorldForm.SelectItem(null, null, null); + } + } + else + { + res = CurrentYndFile.RemoveNode(CurrentPathNode); + } + if (!res) + { + MessageBox.Show("Unable to delete the path node. This shouldn't happen!"); + } + + SetYndHasChangedUI(true); + + CurrentPathNode = null; + if ((tn != null) && (tn.Parent != null)) + { + tn.Parent.Text = "Nodes (" + CurrentYndFile.Nodes.Length.ToString() + ")"; + tn.Parent.Nodes.Remove(tn); + } + else + { + //no need for this when removing the node above will select something else. + LoadPathNodeTabPage(); //this case really shouldn't happen... + } + + if (WorldForm != null) + { + WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); + } + + + return true; + } + + private void AddPathNodeToProject() + { + if (CurrentPathNode == null) return; + if (CurrentYndFile != null) + { + AddYndToProject(CurrentYndFile); + } + } + + private void LoadPathNodeTabPage() + { + + CurrentPathLink = null; + + if (CurrentPathNode == null) + { + YndNodePanel.Enabled = false; + PathNodeDeleteButton.Enabled = false; + PathNodeAddToProjectButton.Enabled = false; + PathNodeAreaIDUpDown.Value = 0; + PathNodeNodeIDUpDown.Value = 0; + PathNodePositionTextBox.Text = string.Empty; + PathNodeStreetHashTextBox.Text = string.Empty; + PathNodeStreetNameLabel.Text = "Name: [None]"; + + UpdatePathNodeFlagsUI(true, true); + + PathNodeLinkCountLabel.Text = "Link Count: 0"; + PathNodeLinksListBox.Items.Clear(); + + } + else + { + populatingui = true; + var n = CurrentPathNode.RawData; + YndNodePanel.Enabled = true; + PathNodeDeleteButton.Enabled = YndExistsInProject(CurrentYndFile); + PathNodeAddToProjectButton.Enabled = !PathNodeDeleteButton.Enabled; + var streetname = GlobalText.TryGetString(n.StreetName.Hash); + PathNodeAreaIDUpDown.Value = n.AreaID; + PathNodeNodeIDUpDown.Value = n.NodeID; + PathNodePositionTextBox.Text = FloatUtil.GetVector3String(CurrentPathNode.Position); + PathNodeStreetHashTextBox.Text = n.StreetName.Hash.ToString(); + PathNodeStreetNameLabel.Text = "Name: " + ((n.StreetName.Hash == 0) ? "[None]" : (string.IsNullOrEmpty(streetname) ? "[Not found]" : streetname)); + + UpdatePathNodeFlagsUI(true, true); + + PathNodeLinkCountLabel.Text = "Link Count: " + CurrentPathNode.LinkCount.ToString(); + PathNodeLinksListBox.Items.Clear(); + if (CurrentPathNode.Links != null) + { + foreach (var link in CurrentPathNode.Links) + { + PathNodeLinksListBox.Items.Add(link); + } + } + populatingui = false; + + + if (WorldForm != null) + { + WorldForm.SelectPathNode(CurrentPathNode); + } + + } + + + LoadPathNodeJunctionPage(); + + LoadPathNodeLinkPage(); + } + + private void LoadPathNodeLinkPage() + { + if (CurrentPathLink == null) + { + PathNodeLinkPanel.Enabled = false; + PathNodeLinkAreaIDUpDown.Value = 0; + PathNodeLinkNodeIDUpDown.Value = 0; + + UpdatePathNodeLinkFlagsUI(true, true); + + PathNodeLinkLengthUpDown.Value = 0; + PathNodeLinkageStatusLabel.Text = ""; + } + else + { + populatingui = true; + PathNodeLinkPanel.Enabled = true; + PathNodeLinkAreaIDUpDown.Value = CurrentPathLink._RawData.AreaID; + PathNodeLinkNodeIDUpDown.Value = CurrentPathLink._RawData.NodeID; + + UpdatePathNodeLinkFlagsUI(true, true); + + PathNodeLinkLengthUpDown.Value = CurrentPathLink.LinkLength.Value; + PathNodeLinkageStatusLabel.Text = ""; + populatingui = false; + + if (WorldForm != null) + { + WorldForm.SelectPathLink(CurrentPathLink); + } + } + + } + + private void LoadPathNodeJunctionPage() + { + + var junc = CurrentPathNode?.Junction; + if (junc == null) + { + PathNodeJunctionEnableCheckBox.Checked = false; + PathNodeJunctionPanel.Enabled = false; + PathNodeJunctionMaxZUpDown.Value = 0; + PathNodeJunctionMinZUpDown.Value = 0; + PathNodeJunctionPosXUpDown.Value = 0; + PathNodeJunctionPosYUpDown.Value = 0; + PathNodeJunctionHeightmapDimXUpDown.Value = 1; + PathNodeJunctionHeightmapDimYUpDown.Value = 1; + PathNodeJunctionHeightmapBytesTextBox.Text = string.Empty; + } + else + { + populatingui = true; + PathNodeJunctionEnableCheckBox.Checked = CurrentPathNode.HasJunction; + PathNodeJunctionPanel.Enabled = PathNodeJunctionEnableCheckBox.Checked; + PathNodeJunctionMaxZUpDown.Value = junc.MaxZ; + PathNodeJunctionMinZUpDown.Value = junc.MinZ; + PathNodeJunctionPosXUpDown.Value = junc.PositionX; + PathNodeJunctionPosYUpDown.Value = junc.PositionY; + PathNodeJunctionHeightmapDimXUpDown.Value = junc.Heightmap.CountX; + PathNodeJunctionHeightmapDimYUpDown.Value = junc.Heightmap.CountY; + PathNodeJunctionHeightmapBytesTextBox.Text = junc.Heightmap?.GetDataString() ?? ""; + populatingui = false; + } + + + } + + public bool IsCurrentPathNode(YndNode pathnode) + { + return CurrentPathNode == pathnode; + } + + + private void UpdatePathNodeFlagsUI(bool updateCheckboxes, bool updateUpDowns) + { + + var flags0 = CurrentPathNode?.Flags0.Value ?? 0; + var flags1 = CurrentPathNode?.Flags1.Value ?? 0; + var flags2 = CurrentPathNode?.Flags2.Value ?? 0; + var flags3 = CurrentPathNode?.Flags3.Value ?? 0; + var flags4 = CurrentPathNode?.Flags4.Value ?? 0; + var flags5 = (uint)(CurrentPathNode?.LinkCountUnk ?? 0); + + + if (updateCheckboxes) + { + PathNodeFlags01CheckBox.Checked = IsBitSet(flags0, 0); + PathNodeFlags02CheckBox.Checked = IsBitSet(flags0, 1); + PathNodeFlags03CheckBox.Checked = IsBitSet(flags0, 2); + PathNodeFlags04CheckBox.Checked = IsBitSet(flags0, 3); + PathNodeFlags05CheckBox.Checked = IsBitSet(flags0, 4); + PathNodeFlags06CheckBox.Checked = IsBitSet(flags0, 5); + PathNodeFlags07CheckBox.Checked = IsBitSet(flags0, 6); + PathNodeFlags08CheckBox.Checked = IsBitSet(flags0, 7); + + PathNodeFlags11CheckBox.Checked = IsBitSet(flags1, 0); + PathNodeFlags12CheckBox.Checked = IsBitSet(flags1, 1); + PathNodeFlags13CheckBox.Checked = IsBitSet(flags1, 2); + PathNodeFlags14CheckBox.Checked = IsBitSet(flags1, 3); + PathNodeFlags15CheckBox.Checked = IsBitSet(flags1, 4); + PathNodeFlags16CheckBox.Checked = IsBitSet(flags1, 5); + PathNodeFlags17CheckBox.Checked = IsBitSet(flags1, 6); + PathNodeFlags18CheckBox.Checked = IsBitSet(flags1, 7); + + PathNodeFlags21CheckBox.Checked = IsBitSet(flags2, 0); + PathNodeFlags22CheckBox.Checked = IsBitSet(flags2, 1); + PathNodeFlags23CheckBox.Checked = IsBitSet(flags2, 2); + PathNodeFlags24CheckBox.Checked = IsBitSet(flags2, 3); + PathNodeFlags25CheckBox.Checked = IsBitSet(flags2, 4); + PathNodeFlags26CheckBox.Checked = IsBitSet(flags2, 5); + PathNodeFlags27CheckBox.Checked = IsBitSet(flags2, 6); + PathNodeFlags28CheckBox.Checked = IsBitSet(flags2, 7); + + PathNodeFlags31CheckBox.Checked = IsBitSet(flags3, 0); + PathNodeFlags32UpDown.Value = (flags3 >> 1) & 127; + + PathNodeFlags41CheckBox.Checked = IsBitSet(flags4, 0); + PathNodeFlags42UpDown.Value = (flags4 >> 1) & 7; + PathNodeFlags45CheckBox.Checked = IsBitSet(flags4, 4); + PathNodeFlags46CheckBox.Checked = IsBitSet(flags4, 5); + PathNodeFlags47CheckBox.Checked = IsBitSet(flags4, 6); + PathNodeFlags48CheckBox.Checked = IsBitSet(flags4, 7); + + PathNodeFlags51CheckBox.Checked = IsBitSet(flags5, 0); + PathNodeFlags52CheckBox.Checked = IsBitSet(flags5, 1); + PathNodeFlags53CheckBox.Checked = IsBitSet(flags5, 2); + } + if (updateUpDowns) + { + PathNodeFlags0UpDown.Value = flags0; + PathNodeFlags1UpDown.Value = flags1; + PathNodeFlags2UpDown.Value = flags2; + PathNodeFlags3UpDown.Value = flags3; + PathNodeFlags4UpDown.Value = flags4; + PathNodeFlags5UpDown.Value = flags5; + } + + var n = CurrentPathNode; + if (n != null) + { + PathNodeFlags0Label.Text = n.Flags0.ToHexString(); + PathNodeFlags1Label.Text = n.Flags1.ToHexString(); + PathNodeFlags2Label.Text = n.Flags2.ToHexString(); + PathNodeFlags3Label.Text = n.Flags3.ToHexString(); + PathNodeFlags4Label.Text = n.Flags4.ToHexString(); + } + else + { + PathNodeFlags0Label.Text = "0x00"; + PathNodeFlags1Label.Text = "0x00"; + PathNodeFlags2Label.Text = "0x00"; + PathNodeFlags3Label.Text = "0x00"; + PathNodeFlags4Label.Text = "0x00"; + } + } + + private void SetPathNodeFlagsFromCheckBoxes() + { + if (populatingui) return; + if (CurrentPathNode == null) return; + + uint flags0 = 0; + uint flags1 = 0; + uint flags2 = 0; + uint flags3 = 0; + uint flags4 = 0; + uint flags5 = 0; + flags0 = UpdateBit(flags0, 0, PathNodeFlags01CheckBox.Checked); + flags0 = UpdateBit(flags0, 1, PathNodeFlags02CheckBox.Checked); + flags0 = UpdateBit(flags0, 2, PathNodeFlags03CheckBox.Checked); + flags0 = UpdateBit(flags0, 3, PathNodeFlags04CheckBox.Checked); + flags0 = UpdateBit(flags0, 4, PathNodeFlags05CheckBox.Checked); + flags0 = UpdateBit(flags0, 5, PathNodeFlags06CheckBox.Checked); + flags0 = UpdateBit(flags0, 6, PathNodeFlags07CheckBox.Checked); + flags0 = UpdateBit(flags0, 7, PathNodeFlags08CheckBox.Checked); + + flags1 = UpdateBit(flags1, 0, PathNodeFlags11CheckBox.Checked); + flags1 = UpdateBit(flags1, 1, PathNodeFlags12CheckBox.Checked); + flags1 = UpdateBit(flags1, 2, PathNodeFlags13CheckBox.Checked); + flags1 = UpdateBit(flags1, 3, PathNodeFlags14CheckBox.Checked); + flags1 = UpdateBit(flags1, 4, PathNodeFlags15CheckBox.Checked); + flags1 = UpdateBit(flags1, 5, PathNodeFlags16CheckBox.Checked); + flags1 = UpdateBit(flags1, 6, PathNodeFlags17CheckBox.Checked); + flags1 = UpdateBit(flags1, 7, PathNodeFlags18CheckBox.Checked); + + flags2 = UpdateBit(flags2, 0, PathNodeFlags21CheckBox.Checked); + flags2 = UpdateBit(flags2, 1, PathNodeFlags22CheckBox.Checked); + flags2 = UpdateBit(flags2, 2, PathNodeFlags23CheckBox.Checked); + flags2 = UpdateBit(flags2, 3, PathNodeFlags24CheckBox.Checked); + flags2 = UpdateBit(flags2, 4, PathNodeFlags25CheckBox.Checked); + flags2 = UpdateBit(flags2, 5, PathNodeFlags26CheckBox.Checked); + flags2 = UpdateBit(flags2, 6, PathNodeFlags27CheckBox.Checked); + flags2 = UpdateBit(flags2, 7, PathNodeFlags28CheckBox.Checked); + + flags3 = UpdateBit(flags3, 0, PathNodeFlags31CheckBox.Checked); + flags3 += (((uint)PathNodeFlags32UpDown.Value & 127u) << 1); + + flags4 = UpdateBit(flags4, 0, PathNodeFlags41CheckBox.Checked); + flags4 += (((uint)PathNodeFlags42UpDown.Value & 7u) << 1); + flags4 = UpdateBit(flags4, 4, PathNodeFlags45CheckBox.Checked); + flags4 = UpdateBit(flags4, 5, PathNodeFlags46CheckBox.Checked); + flags4 = UpdateBit(flags4, 6, PathNodeFlags47CheckBox.Checked); + flags4 = UpdateBit(flags4, 7, PathNodeFlags48CheckBox.Checked); + + flags5 = UpdateBit(flags5, 0, PathNodeFlags51CheckBox.Checked); + flags5 = UpdateBit(flags5, 1, PathNodeFlags52CheckBox.Checked); + flags5 = UpdateBit(flags5, 2, PathNodeFlags53CheckBox.Checked); + + + lock (yndsyncroot) + { + if (CurrentPathNode.Flags0.Value != flags0) + { + CurrentPathNode.Flags0 = (byte)flags0; + SetYndHasChanged(true); + } + if (CurrentPathNode.Flags1.Value != flags1) + { + CurrentPathNode.Flags1 = (byte)flags1; + SetYndHasChanged(true); + } + if (CurrentPathNode.Flags2.Value != flags2) + { + CurrentPathNode.Flags2 = (byte)flags2; + SetYndHasChanged(true); + } + if (CurrentPathNode.Flags3.Value != flags3) + { + CurrentPathNode.Flags3 = (byte)flags3; + SetYndHasChanged(true); + } + if (CurrentPathNode.Flags4.Value != flags4) + { + CurrentPathNode.Flags4 = (byte)flags4; + SetYndHasChanged(true); + } + if (CurrentPathNode.LinkCountUnk != flags5) + { + CurrentPathNode.LinkCountUnk = (byte)flags5; + SetYndHasChanged(true); + } + } + + populatingui = true; + UpdatePathNodeFlagsUI(false, true); //update updowns + populatingui = false; + } + + private void SetPathNodeFlagsFromUpDowns() + { + if (populatingui) return; + if (CurrentPathNode == null) return; + + uint flags0 = (uint)PathNodeFlags0UpDown.Value; + uint flags1 = (uint)PathNodeFlags1UpDown.Value; + uint flags2 = (uint)PathNodeFlags2UpDown.Value; + uint flags3 = (uint)PathNodeFlags3UpDown.Value; + uint flags4 = (uint)PathNodeFlags4UpDown.Value; + uint flags5 = (uint)PathNodeFlags5UpDown.Value; + + lock (yndsyncroot) + { + if (CurrentPathNode.Flags0.Value != flags0) + { + CurrentPathNode.Flags0 = (byte)flags0; + SetYndHasChanged(true); + } + if (CurrentPathNode.Flags1.Value != flags1) + { + CurrentPathNode.Flags1 = (byte)flags1; + SetYndHasChanged(true); + } + if (CurrentPathNode.Flags2.Value != flags2) + { + CurrentPathNode.Flags2 = (byte)flags2; + SetYndHasChanged(true); + } + if (CurrentPathNode.Flags3.Value != flags3) + { + CurrentPathNode.Flags3 = (byte)flags3; + SetYndHasChanged(true); + } + if (CurrentPathNode.Flags4.Value != flags4) + { + CurrentPathNode.Flags4 = (byte)flags4; + SetYndHasChanged(true); + } + if (CurrentPathNode.LinkCountUnk != flags5) + { + CurrentPathNode.LinkCountUnk = (byte)flags5; + SetYndHasChanged(true); + } + } + + populatingui = true; + UpdatePathNodeFlagsUI(true, false); //update checkboxes + populatingui = false; + } + + + private void UpdatePathNodeLinkFlagsUI(bool updateCheckboxes, bool updateUpDowns) + { + var flags0 = CurrentPathLink?.Flags0.Value ?? 0; + var flags1 = CurrentPathLink?.Flags1.Value ?? 0; + var flags2 = CurrentPathLink?.Flags2.Value ?? 0; + + + if (updateCheckboxes) + { + PathNodeLinkFlags01CheckBox.Checked = IsBitSet(flags0, 0); + PathNodeLinkFlags02CheckBox.Checked = IsBitSet(flags0, 1); + PathNodeLinkFlags03UpDown.Value = (flags0 >> 2) & 7; + PathNodeLinkFlags04UpDown.Value = (flags0 >> 5) & 7; + + PathNodeLinkFlags11CheckBox.Checked = IsBitSet(flags1, 0); + PathNodeLinkFlags12CheckBox.Checked = IsBitSet(flags1, 1); + PathNodeLinkFlags13CheckBox.Checked = IsBitSet(flags1, 2); + PathNodeLinkFlags14CheckBox.Checked = IsBitSet(flags1, 3); + PathNodeLinkOffsetSizeUpDown.Value = (flags1 >> 4) & 7; + PathNodeLinkFlags18CheckBox.Checked = IsBitSet(flags1, 7); + + PathNodeLinkFlags21CheckBox.Checked = IsBitSet(flags2, 0); + PathNodeLinkFlags22CheckBox.Checked = IsBitSet(flags2, 1); + PathNodeLinkBackLanesUpDown.Value = (flags2 >> 2) & 7; + PathNodeLinkFwdLanesUpDown.Value = (flags2 >> 5) & 7; + } + if (updateUpDowns) + { + PathNodeLinkFlags0UpDown.Value = flags0; + PathNodeLinkFlags1UpDown.Value = flags1; + PathNodeLinkFlags2UpDown.Value = flags2; + } + + var l = CurrentPathLink; + if (l != null) + { + PathNodeLinkFlags0Label.Text = l.Flags0.ToHexString(); + PathNodeLinkFlags1Label.Text = l.Flags1.ToHexString(); + PathNodeLinkFlags2Label.Text = l.Flags2.ToHexString(); + } + else + { + PathNodeLinkFlags0Label.Text = "0x00"; + PathNodeLinkFlags1Label.Text = "0x00"; + PathNodeLinkFlags2Label.Text = "0x00"; + } + } + + private void SetPathNodeLinkFlagsFromCheckBoxes() + { + if (populatingui) return; + if (CurrentPathLink == null) return; + + uint flags0 = 0; + uint flags1 = 0; + uint flags2 = 0; + flags0 = UpdateBit(flags0, 0, PathNodeLinkFlags01CheckBox.Checked); + flags0 = UpdateBit(flags0, 1, PathNodeLinkFlags02CheckBox.Checked); + flags0 += (((uint)PathNodeLinkFlags03UpDown.Value & 7u) << 2); + flags0 += (((uint)PathNodeLinkFlags04UpDown.Value & 7u) << 5); + + flags1 = UpdateBit(flags1, 0, PathNodeLinkFlags11CheckBox.Checked); + flags1 = UpdateBit(flags1, 1, PathNodeLinkFlags12CheckBox.Checked); + flags1 = UpdateBit(flags1, 2, PathNodeLinkFlags13CheckBox.Checked); + flags1 = UpdateBit(flags1, 3, PathNodeLinkFlags14CheckBox.Checked); + flags1 += (((uint)PathNodeLinkOffsetSizeUpDown.Value & 7u) << 4); + flags1 = UpdateBit(flags1, 7, PathNodeLinkFlags18CheckBox.Checked); + + flags2 = UpdateBit(flags2, 0, PathNodeLinkFlags21CheckBox.Checked); + flags2 = UpdateBit(flags2, 1, PathNodeLinkFlags22CheckBox.Checked); + flags2 += (((uint)PathNodeLinkBackLanesUpDown.Value & 7u) << 2); + flags2 += (((uint)PathNodeLinkFwdLanesUpDown.Value & 7u) << 5); + + bool updgfx = false; + lock (yndsyncroot) + { + if (CurrentPathLink.Flags0.Value != flags0) + { + CurrentPathLink.Flags0 = (byte)flags0; + SetYndHasChanged(true); + } + if (CurrentPathLink.Flags1.Value != flags1) + { + CurrentPathLink.Flags1 = (byte)flags1; + SetYndHasChanged(true); + updgfx = true; + } + if (CurrentPathLink.Flags2.Value != flags2) + { + CurrentPathLink.Flags2 = (byte)flags2; + SetYndHasChanged(true); + updgfx = true; + } + } + + populatingui = true; + UpdatePathNodeLinkFlagsUI(false, true); //update updowns + populatingui = false; + + if (updgfx && (WorldForm != null) && (CurrentYndFile != null)) + { + WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); + } + } + + private void SetPathNodeLinkFlagsFromUpDowns() + { + if (populatingui) return; + if (CurrentPathLink == null) return; + + uint flags0 = (uint)PathNodeLinkFlags0UpDown.Value; + uint flags1 = (uint)PathNodeLinkFlags1UpDown.Value; + uint flags2 = (uint)PathNodeLinkFlags2UpDown.Value; + + bool updgfx = false; + lock (yndsyncroot) + { + if (CurrentPathLink.Flags0.Value != flags0) + { + CurrentPathLink.Flags0 = (byte)flags0; + SetYndHasChanged(true); + } + if (CurrentPathLink.Flags1.Value != flags1) + { + CurrentPathLink.Flags1 = (byte)flags1; + SetYndHasChanged(true); + } + if (CurrentPathLink.Flags2.Value != flags2) + { + CurrentPathLink.Flags2 = (byte)flags2; + SetYndHasChanged(true); + updgfx = true; + } + } + + populatingui = true; + UpdatePathNodeLinkFlagsUI(true, false); //update checkboxes + populatingui = false; + + if (updgfx && (WorldForm != null) && (CurrentYndFile != null)) + { + WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); + } + } + + + + private void AddPathLink() + { + if (CurrentPathNode == null) return; + + var l = CurrentPathNode.AddLink(); + + LoadPathNodeTabPage(); + + PathNodeLinksListBox.SelectedItem = l; + + if (WorldForm != null) + { + WorldForm.UpdatePathNodeGraphics(CurrentPathNode, false); + } + } + + private void RemovePathLink() + { + if (CurrentPathLink == null) return; + if (CurrentPathNode == null) return; + + var r = CurrentPathNode.RemoveLink(CurrentPathLink); + + if (!r) return; + + LoadPathNodeTabPage(); + + if (WorldForm != null) + { + WorldForm.UpdatePathNodeGraphics(CurrentPathNode, false); + } + } + + private void UpdatePathNodeLinkage() + { + if (CurrentPathLink == null) return; + if (CurrentYndFile == null) return; + + YndNode linknode = null; + ushort areaid = CurrentPathLink._RawData.AreaID; + ushort nodeid = CurrentPathLink._RawData.NodeID; + if (areaid == CurrentYndFile.AreaID) + { + //link to the same ynd. find the new node in the current ynd. + if ((CurrentYndFile.Nodes != null) && (nodeid < CurrentYndFile.Nodes.Length)) + { + linknode = CurrentYndFile.Nodes[nodeid]; + } + } + else + { + //try lookup the link node from the space. + if (WorldForm != null) + { + linknode = WorldForm.GetPathNodeFromSpace(areaid, nodeid); + } + } + + if (linknode == null) + { + PathNodeLinkageStatusLabel.Text = "Unable to find node " + areaid.ToString() + ":" + nodeid.ToString() + "."; + } + else + { + PathNodeLinkageStatusLabel.Text = ""; + } + + CurrentPathLink.Node2 = linknode; + CurrentPathLink.UpdateLength(); + + + ////need to rebuild the link verts.. updating the graphics should do it... + if (WorldForm != null) + { + WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); + } + } + + + + + + + + + + + + public void NewYnv()//TODO! + { + } + + public void OpenYnv()//TODO! + { + } + + public void SaveYnv(bool saveas = false)//TODO! + { + } + + private void AddYnvToProject(YnvFile ynv)//TODO! + { + } + + private void RemoveYnvFromProject()//TODO! + { + } + + private void LoadYnvTabPage()//TODO! + { + } + + private void LoadYnvFromFile(YnvFile ynv, string filename)//TODO! + { + } + + private void LoadYnvTreeNodes(YnvFile ynv, TreeNode node)//TODO! + { + } + + private void SetYnvHasChanged(bool changed)//TODO! + { + } + + private void SetYnvHasChangedUI(bool changed)//TODO! + { + } + + + public void NewNavPoly(YnvPoly copy = null, bool copyposition = false)//TODO! + { + } + + public bool DeleteNavPoly()//TODO! + { + return false; + } + + private void AddNavPolyToProject()//TODO! + { + } + + private void LoadNavPolyTabPage()//TODO! + { + } + + public bool IsCurrentNavPoly(YnvPoly poly) + { + return poly == CurrentNavPoly; + } + + + + + + + + + + + + public void NewTrainTrack() + { + if (CurrentProjectFile == null) + { + NewProject(); + } + if (CurrentProjectFile == null) return; + + int testi = 13; + string fname = string.Empty; + bool filenameok = false; + while (!filenameok) + { + fname = "trains" + testi.ToString() + ".dat"; + filenameok = !CurrentProjectFile.ContainsTrainTrack(fname); + testi++; + } + + lock (trainsyncroot) + { + TrainTrack track = CurrentProjectFile.AddTrainsFile(fname); + if (track != null) + { + track.Loaded = true; + track.HasChanged = true; //new track, flag as not saved + + //TODO: set new train track default values... + + } + } + + CurrentProjectFile.HasChanged = true; + + LoadProjectTree(); + } + + public void OpenTrainTrack() + { + string[] files = ShowOpenDialogMulti("Dat files|*.dat", string.Empty); + if (files == null) + { + return; + } + + if (CurrentProjectFile == null) + { + NewProject(); + } + + foreach (string file in files) + { + if (!File.Exists(file)) continue; + + var track = CurrentProjectFile.AddTrainsFile(file); + + if (track != null) + { + SetProjectHasChanged(true); + + LoadTrainTrackFromFile(track, file); + + LoadProjectTree(); + } + else + { + MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); + } + + } + } + + public void SaveTrainTrack(bool saveas = false) + { + if ((CurrentTrainTrack == null) && (CurrentTrainNode != null)) CurrentTrainTrack = CurrentTrainNode.Track; + if (CurrentTrainTrack == null) return; + string trackname = CurrentTrainTrack.Name; + string filepath = CurrentTrainTrack.FilePath; + if (string.IsNullOrEmpty(filepath)) + { + filepath = trackname; + } + string origfile = filepath; + if (!File.Exists(filepath)) + { + saveas = true; + } + + + byte[] data; + lock (trainsyncroot) //need to sync writes to ynd objects... + { + saveas = saveas || string.IsNullOrEmpty(filepath); + if (saveas) + { + filepath = ShowSaveDialog("Dat files|*.dat", filepath); + if (string.IsNullOrEmpty(filepath)) + { return; } + + string newname = Path.GetFileNameWithoutExtension(filepath); + //JenkIndex.Ensure(newname); + CurrentTrainTrack.FilePath = filepath; + CurrentTrainTrack.RpfFileEntry.Name = new FileInfo(filepath).Name; + CurrentTrainTrack.Name = CurrentTrainTrack.RpfFileEntry.Name; + } + + + data = CurrentTrainTrack.Save(); + } + + + if (data != null) + { + File.WriteAllBytes(filepath, data); + } + + SetTrainTrackHasChanged(false); + + if (saveas) + { + LoadTrainTrackTabPage(); + if (CurrentProjectFile != null) + { + string origpath = CurrentProjectFile.GetRelativePath(origfile); + string newpath = CurrentProjectFile.GetRelativePath(CurrentTrainTrack.FilePath); + if (!CurrentProjectFile.RenameTrainTrack(origpath, newpath)) + { //couldn't rename it in the project? happens when project not saved yet... + //MessageBox.Show("Couldn't rename train track in project! This shouldn't happen - check the project file XML."); + } + } + SetProjectHasChanged(true); + SetCurrentSaveItem(); + } + + } + + private void AddTrainTrackToProject(TrainTrack track) + { + if (track == null) return; + if (CurrentProjectFile == null) + { + NewProject(); + } + if (TrainTrackExistsInProject(track)) return; + if (CurrentProjectFile.AddTrainsFile(track)) + { + track.HasChanged = true; + CurrentProjectFile.HasChanged = true; + LoadProjectTree(); + } + CurrentTrainTrack = track; + RefreshUI(); + if (CurrentTrainNode != null) + { + TrySelectTrainNodeTreeNode(CurrentTrainNode); + } + } + + private void RemoveTrainTrackFromProject() + { + if (CurrentTrainTrack == null) return; + if (CurrentProjectFile == null) return; + CurrentProjectFile.RemoveTrainsFile(CurrentTrainTrack); + CurrentTrainTrack = null; + LoadProjectTree(); + RefreshUI(); + } + + private void LoadTrainTrackTabPage() + { + if (CurrentTrainTrack == null) + { + TrainTrackFilePanel.Enabled = false; + TrainTrackFilenameTextBox.Text = string.Empty; + TrainTrackConfigNameTextBox.Text = string.Empty; + TrainTrackIsPingPongCheckBox.Checked = false; + TrainTrackStopsAtStationsCheckBox.Checked = false; + TrainTrackMPStopsAtStationsCheckBox.Checked = false; + TrainTrackSpeedTextBox.Text = string.Empty; + TrainTrackBrakingDistTextBox.Text = string.Empty; + TrainTrackRpfPathTextBox.Text = string.Empty; + TrainTrackFilePathTextBox.Text = string.Empty; + TrainTrackProjectPathTextBox.Text = string.Empty; + TrainTrackInfoLabel.Text = string.Empty; + } + else + { + populatingui = true; + TrainTrackFilePanel.Enabled = true; + TrainTrackFilenameTextBox.Text = CurrentTrainTrack.filename; + TrainTrackConfigNameTextBox.Text = CurrentTrainTrack.trainConfigName; + TrainTrackIsPingPongCheckBox.Checked = CurrentTrainTrack.isPingPongTrack; + TrainTrackStopsAtStationsCheckBox.Checked = CurrentTrainTrack.stopsAtStations; + TrainTrackMPStopsAtStationsCheckBox.Checked = CurrentTrainTrack.MPstopsAtStations; + TrainTrackSpeedTextBox.Text = FloatUtil.ToString(CurrentTrainTrack.speed); + TrainTrackBrakingDistTextBox.Text = FloatUtil.ToString(CurrentTrainTrack.brakingDist); + TrainTrackRpfPathTextBox.Text = CurrentTrainTrack.RpfFileEntry?.Path ?? string.Empty; + TrainTrackFilePathTextBox.Text = string.Empty; //todo + TrainTrackProjectPathTextBox.Text = string.Empty; //todo + TrainTrackInfoLabel.Text = CurrentTrainTrack.StationCount.ToString() + " stations"; + populatingui = false; + } + } + + private void LoadTrainTrackFromFile(TrainTrack track, string filename) + { + byte[] data = File.ReadAllBytes(filename); + + string fname = new FileInfo(filename).Name; + + track.Load(data); + + track.Name = fname; + track.FilePath = filename; + track.RpfFileEntry.Name = fname; + track.RpfFileEntry.NameLower = fname.ToLower(); + + + if (WorldForm != null) + { + WorldForm.UpdateTrainTrackGraphics(track, true); //links don't get drawn until something changes otherwise + } + } + + private void LoadTrainTrackTreeNodes(TrainTrack track, TreeNode node) + { + if (track == null) return; + + if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Nodes + + node.Nodes.Clear(); + + + + if ((track.Nodes != null) && (track.Nodes.Count > 0)) + { + var nodesnode = node.Nodes.Add("Nodes (" + track.Nodes.Count.ToString() + ")"); + nodesnode.Name = "Nodes"; + nodesnode.Tag = track; + var nodes = track.Nodes; + for (int i = 0; i < nodes.Count; i++) + { + var ynode = nodes[i]; + var tnode = nodesnode.Nodes.Add(ynode.ToString()); + tnode.Tag = ynode; + } + } + + } + + private void SetTrainTrackHasChanged(bool changed) + { + if (CurrentTrainTrack == null) return; + + bool changechange = changed != CurrentTrainTrack.HasChanged; + if (!changechange) return; + + CurrentTrainTrack.HasChanged = changed; + + SetTrainTrackHasChangedUI(changed); + } + + private void SetTrainTrackHasChangedUI(bool changed) + { + if (ProjectTreeView.Nodes.Count > 0) + { + var pnode = ProjectTreeView.Nodes[0]; + var trnode = GetChildTreeNode(pnode, "Trains"); + if (trnode == null) return; + string changestr = changed ? "*" : ""; + for (int i = 0; i < trnode.Nodes.Count; i++) + { + var tnode = trnode.Nodes[i]; + if (tnode.Tag == CurrentTrainTrack) + { + string name = CurrentTrainTrack.Name; + if (CurrentTrainTrack.RpfFileEntry != null) + { + name = CurrentTrainTrack.RpfFileEntry.Name; + } + tnode.Text = changestr + name; + break; + } + } + } + } + + + + public void NewTrainNode(TrainTrackNode copy = null, bool copyPosition = false) + { + if (CurrentTrainTrack == null) return; + + var afternode = copyPosition ? copy : null; + + var n = CurrentTrainTrack.AddNode(afternode); + if (copy == null) + { + copy = CurrentTrainNode; + } + if (copy != null) + { + n.NodeType = copy.NodeType; + } + + bool cp = copyPosition && (copy != null); + Vector3 pos = cp ? copy.Position : GetSpawnPos(10.0f); + n.SetPosition(pos); + + + //CurrentTrainTrack.BuildVertices(); //for the graphics... + CurrentTrainTrack.BuildBVH(); + + + LoadProjectTree(); + + TrySelectTrainNodeTreeNode(n); + CurrentTrainNode = n; + LoadTrainNodeTabPage(); + + + if (WorldForm != null) + { + WorldForm.UpdateTrainTrackGraphics(CurrentTrainTrack, false); + } + } + + public bool DeleteTrainNode() + { + if (CurrentTrainTrack == null) return false; + if (CurrentTrainNode == null) return false; + if (CurrentTrainNode.Track != CurrentTrainTrack) return false; + if (CurrentTrainTrack.Nodes == null) return false; //nothing to delete.. + + if (MessageBox.Show("Are you sure you want to delete this train track node?\n" + CurrentTrainNode.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return true; + } + + //find this now to remove it later. + var tn = FindTrainNodeTreeNode(CurrentTrainNode); + + bool res = false; + if (WorldForm != null) + { + lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... + { + res = CurrentTrainTrack.RemoveNode(CurrentTrainNode); + + //WorldForm.SelectItem(null, null, null); + } + } + else + { + res = CurrentTrainTrack.RemoveNode(CurrentTrainNode); + } + if (!res) + { + MessageBox.Show("Unable to delete the train track node. This shouldn't happen!"); + } + + SetTrainTrackHasChangedUI(true); + + CurrentTrainNode = null; + if ((tn != null) && (tn.Parent != null)) + { + tn.Parent.Text = "Nodes (" + CurrentTrainTrack.Nodes.Count.ToString() + ")"; + tn.Parent.Nodes.Remove(tn); + } + else + { + //no need for this when removing the node above will select something else. + LoadTrainNodeTabPage(); //this case really shouldn't happen... + } + + if (WorldForm != null) + { + WorldForm.UpdateTrainTrackGraphics(CurrentTrainTrack, false); + } + + + return true; + } + + private void AddTrainNodeToProject() + { + if (CurrentTrainNode == null) return; + if (CurrentTrainTrack != null) + { + AddTrainTrackToProject(CurrentTrainTrack); + } + } + + private void LoadTrainNodeTabPage() + { + if (CurrentTrainNode == null) + { + TrainNodePanel.Enabled = false; + TrainNodeDeleteButton.Enabled = false; + TrainNodeAddToProjectButton.Enabled = false; + TrainNodePositionTextBox.Text = string.Empty; + TrainNodeTypeComboBox.SelectedIndex = -1; + } + else + { + populatingui = true; + TrainNodePanel.Enabled = true; + TrainNodeDeleteButton.Enabled = TrainTrackExistsInProject(CurrentTrainTrack); + TrainNodeAddToProjectButton.Enabled = !TrainNodeDeleteButton.Enabled; + TrainNodePositionTextBox.Text = FloatUtil.GetVector3String(CurrentTrainNode.Position); + TrainNodeTypeComboBox.SelectedIndex = CurrentTrainNode.NodeType; + populatingui = false; + + if (WorldForm != null) + { + WorldForm.SelectTrainTrackNode(CurrentTrainNode); + } + } + } + + public bool IsCurrentTrainNode(TrainTrackNode node) + { + return node == CurrentTrainNode; + } + + + + + + + + + + + + + + + + + + public void NewScenario() + { + if (CurrentProjectFile == null) + { + NewProject(); + } + if (CurrentProjectFile == null) return; + + int testi = 1; + string fname = string.Empty; + bool filenameok = false; + while (!filenameok) + { + fname = "scenario" + testi.ToString() + ".ymt"; + filenameok = !CurrentProjectFile.ContainsScenario(fname); + testi++; + } + + lock (scenariosyncroot) + { + YmtFile ymt = CurrentProjectFile.AddScenarioFile(fname); + if (ymt != null) + { + ymt.CScenarioPointRegion = new MCScenarioPointRegion(); + ymt.CScenarioPointRegion.Ymt = ymt; + ymt.CScenarioPointRegion.Points = new MCScenarioPointContainer(ymt.CScenarioPointRegion); + ymt.CScenarioPointRegion.Paths = new MUnk_4023740759(ymt.CScenarioPointRegion); + ymt.CScenarioPointRegion.LookUps = new MCScenarioPointLookUps(ymt.CScenarioPointRegion); + + ymt.ScenarioRegion = new ScenarioRegion(); + ymt.ScenarioRegion.Region = ymt.CScenarioPointRegion; + ymt.ScenarioRegion.Ymt = ymt; + + ymt.ScenarioRegion.BuildNodes(); //should be empty + ymt.ScenarioRegion.BuildBVH(); //should be empty + ymt.ScenarioRegion.BuildVertices(); //should be empty + + ymt.HasChanged = true; //new ymt, flag as not saved + ymt.Loaded = true; + } + } + + CurrentProjectFile.HasChanged = true; + + LoadProjectTree(); + } + + public void OpenScenario() + { + string[] files = ShowOpenDialogMulti("Ymt files|*.ymt", string.Empty); + if (files == null) + { + return; + } + + if (CurrentProjectFile == null) + { + NewProject(); + } + + foreach (string file in files) + { + if (!File.Exists(file)) continue; + + var ymt = CurrentProjectFile.AddScenarioFile(file); + + if (ymt != null) + { + SetProjectHasChanged(true); + + LoadScenarioFromFile(ymt, file); + + LoadProjectTree(); + } + else + { + MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); + } + + } + } + + public void SaveScenario(bool saveas = false) + { + if ((CurrentScenario == null) && (CurrentScenarioNode != null)) CurrentScenario = CurrentScenarioNode.Ymt; + if (CurrentScenario == null) return; + string ymtname = CurrentScenario.Name; + string filepath = CurrentScenario.FilePath; + if (string.IsNullOrEmpty(filepath)) + { + filepath = ymtname; + } + string origfile = filepath; + if (!File.Exists(filepath)) + { + saveas = true; + } + + + byte[] data; + lock (scenariosyncroot) //need to sync writes to scenario... + { + saveas = saveas || string.IsNullOrEmpty(filepath); + if (saveas) + { + filepath = ShowSaveDialog("Ymt files|*.ymt", filepath); + if (string.IsNullOrEmpty(filepath)) + { return; } + + string newname = Path.GetFileNameWithoutExtension(filepath); + JenkIndex.Ensure(newname); + CurrentScenario.FilePath = filepath; + CurrentScenario.RpfFileEntry.Name = new FileInfo(filepath).Name; + CurrentScenario.Name = CurrentScenario.RpfFileEntry.Name; + } + + + CurrentScenario.ContentType = YmtFileContentType.ScenarioPointRegion;//just to be sure.. + + data = CurrentScenario.Save(); + } + + + if (data != null) + { + File.WriteAllBytes(filepath, data); + } + + SetScenarioHasChanged(false); + + if (saveas) + { + LoadScenarioTabPage(); + if (CurrentProjectFile != null) + { + string origpath = CurrentProjectFile.GetRelativePath(origfile); + string newpath = CurrentProjectFile.GetRelativePath(CurrentScenario.FilePath); + if (!CurrentProjectFile.RenameScenario(origpath, newpath)) + { //couldn't rename it in the project? happens when project not saved yet... + //MessageBox.Show("Couldn't rename scenario in project! This shouldn't happen - check the project file XML."); + } + } + SetProjectHasChanged(true); + SetCurrentSaveItem(); + } + } + + private void AddScenarioToProject(YmtFile ymt) + { + if (ymt == null) return; + if (CurrentProjectFile == null) + { + NewProject(); + } + if (ScenarioExistsInProject(ymt)) return; + if (CurrentProjectFile.AddScenarioFile(ymt)) + { + ymt.HasChanged = true; + CurrentProjectFile.HasChanged = true; + LoadProjectTree(); + } + CurrentScenario = ymt; + RefreshUI(); + if (CurrentScenarioNode != null) + { + TrySelectScenarioNodeTreeNode(CurrentScenarioNode); + } + } + + private void RemoveScenarioFromProject() + { + if (CurrentScenario == null) return; + if (CurrentProjectFile == null) return; + CurrentProjectFile.RemoveScenarioFile(CurrentScenario); + CurrentScenario = null; + LoadProjectTree(); + RefreshUI(); + } + + private void LoadScenarioTabPage() + { + if (CurrentScenario == null) + { + populatingui = true; + ScenarioYmtPanel.Enabled = false; + ScenarioYmtNameTextBox.Text = string.Empty; + ScenarioYmtVersionTextBox.Text = string.Empty; + ScenarioYmtGridMinTextBox.Text = string.Empty; + ScenarioYmtGridMaxTextBox.Text = string.Empty; + ScenarioYmtGridScaleTextBox.Text = string.Empty; + ScenarioYmtGridInfoLabel.Text = "Total grid points: 0"; + ScenarioYmtExtentsMinTextBox.Text = string.Empty; + ScenarioYmtExtentsMaxTextBox.Text = string.Empty; + ScenarioYmtFileLocationTextBox.Text = string.Empty; + ScenarioYmtProjectPathTextBox.Text = string.Empty; + populatingui = false; + } + else + { + var rgn = CurrentScenario.CScenarioPointRegion; + var accg = rgn?._Data.AccelGrid ?? new rage__spdGrid2D(); + var bvh = CurrentScenario.ScenarioRegion?.BVH; + var emin = bvh?.Box.Minimum ?? Vector3.Zero; + var emax = bvh?.Box.Maximum ?? Vector3.Zero; + + populatingui = true; + ScenarioYmtPanel.Enabled = true; + ScenarioYmtNameTextBox.Text = CurrentScenario.Name; + ScenarioYmtVersionTextBox.Text = rgn?.VersionNumber.ToString() ?? ""; + ScenarioYmtGridMinTextBox.Text = FloatUtil.GetVector2String(accg.Min); + ScenarioYmtGridMaxTextBox.Text = FloatUtil.GetVector2String(accg.Max); + ScenarioYmtGridScaleTextBox.Text = FloatUtil.GetVector2String(accg.Scale); + ScenarioYmtGridInfoLabel.Text = "Total grid points: " + (rgn?.Unk_3844724227?.Length ?? 0).ToString(); + ScenarioYmtExtentsMinTextBox.Text = FloatUtil.GetVector3String(emin); + ScenarioYmtExtentsMaxTextBox.Text = FloatUtil.GetVector3String(emax); + ScenarioYmtFileLocationTextBox.Text = CurrentScenario.RpfFileEntry?.Path ?? ""; + ScenarioYmtProjectPathTextBox.Text = (CurrentProjectFile != null) ? CurrentProjectFile.GetRelativePath(CurrentScenario.FilePath) : CurrentScenario.FilePath; + populatingui = false; + } + } + + private void LoadScenarioFromFile(YmtFile ymt, string filename) + { + byte[] data = File.ReadAllBytes(filename); + + ymt.LoadRSC(data); + } + + private void LoadScenarioTreeNodes(YmtFile ymt, TreeNode node) + { + if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Points + + node.Nodes.Clear(); + + var region = ymt?.ScenarioRegion; + + if (region == null) return; + + var nodes = region.Nodes; + if ((nodes == null) || (nodes.Count == 0)) return; + + var pointsnode = node.Nodes.Add("Points (" + nodes.Count.ToString() + ")"); + pointsnode.Name = "Points"; + pointsnode.Tag = ymt; + for (int i = 0; i < nodes.Count; i++) + { + var snode = nodes[i]; + var tnode = pointsnode.Nodes.Add(snode.MedTypeName + ": " + snode.StringText); + tnode.Tag = snode; + } + + //var sr = region.Region; + //if (sr == null) return; + //int pointCount = (sr.Points?.LoadSavePoints?.Length ?? 0) + (sr.Points?.MyPoints?.Length ?? 0); + //int entityOverrideCount = (sr.EntityOverrides?.Length ?? 0); + //int chainCount = (sr.Paths?.Chains?.Length ?? 0); + //int clusterCount = (sr.Clusters?.Length ?? 0); + //TreeNode pointsNode = null; + //TreeNode entityOverridesNode = null; + //TreeNode chainsNode = null; + //TreeNode clustersNode = null; + //if (pointCount > 0) + //{ + // pointsNode = node.Nodes.Add("Points (" + pointCount.ToString() + ")"); + //} + //if (entityOverrideCount > 0) + //{ + // entityOverridesNode = node.Nodes.Add("Entity Overrides (" + entityOverrideCount.ToString() + ")"); + //} + //if (chainCount > 0) + //{ + // chainsNode = node.Nodes.Add("Chains (" + chainsNode.ToString() + ")"); + //} + //if (clusterCount > 0) + //{ + // clustersNode = node.Nodes.Add("Clusters (" + clusterCount.ToString() + ")"); + //} + //for (int i = 0; i < nodes.Count; i++) + //{ + // var snode = nodes[i]; + // if (snode == null) continue; + // if ((pointsNode != null) && ((snode.LoadSavePoint != null) || (snode.MyPoint != null))) + // { + // pointsNode.Nodes.Add(snode.ToString()).Tag = snode; + // } + // if ((entityOverridesNode != null) && ((snode.EntityOverride != null) || (snode.EntityPoint != null))) + // { + // entityOverridesNode.Nodes.Add(snode.ToString()).Tag = snode; + // } + // if ((chainsNode != null) && (snode.ChainingNode != null)) + // { + // chainsNode.Nodes.Add(snode.ToString()).Tag = snode; + // } + // if ((clustersNode != null) && ((snode.Cluster != null) || (snode.ClusterLoadSavePoint != null) || (snode.ClusterMyPoint != null))) + // { + // clustersNode.Nodes.Add(snode.ToString()).Tag = snode; + // } + //} + + } + + private void SetScenarioHasChanged(bool changed) + { + if (CurrentScenario == null) return; + + bool changechange = changed != CurrentScenario.HasChanged; + if (!changechange) return; + + CurrentScenario.HasChanged = changed; + + SetScenarioHasChangedUI(changed); + } + + private void SetScenarioHasChangedUI(bool changed) + { + if (ProjectTreeView.Nodes.Count > 0) + { + var pnode = ProjectTreeView.Nodes[0]; + var scnode = GetChildTreeNode(pnode, "Scenarios"); + if (scnode == null) return; + string changestr = changed ? "*" : ""; + for (int i = 0; i < scnode.Nodes.Count; i++) + { + var snode = scnode.Nodes[i]; + if (snode.Tag == CurrentScenario) + { + string name = CurrentScenario.Name; + if (CurrentScenario.RpfFileEntry != null) + { + name = CurrentScenario.RpfFileEntry.Name; + } + snode.Text = changestr + name; + break; + } + } + } + } + + + + public void NewScenarioNode(ScenarioNode copy = null, bool copyPosition = false) + { + if (CurrentScenario == null) return; + if (CurrentScenario.ScenarioRegion == null) return; + + if (copy == null) + { + copy = CurrentScenarioNode; + } + + var n = CurrentScenario.ScenarioRegion.AddNode(copy); + + bool cp = copyPosition && (copy != null); + Vector3 pos = cp ? copy.Position : GetSpawnPos(10.0f); + Quaternion ori = cp ? copy.Orientation : Quaternion.Identity; + n.SetPosition(pos); + n.SetOrientation(ori); + + + LoadProjectTree(); + + TrySelectScenarioNodeTreeNode(n); + CurrentScenarioNode = n; + LoadScenarioTabPage(); + LoadScenarioNodeTabPages(); + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + else + { + CurrentScenario.ScenarioRegion.BuildBVH(); + CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... + } + } + + public bool DeleteScenarioNode() + { + if (CurrentScenario == null) return false; + if (CurrentScenario.ScenarioRegion == null) return false; + if (CurrentScenarioNode == null) return false; + + + if (MessageBox.Show("Are you sure you want to delete this scenario node?\n" + CurrentScenarioNode.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return true; + } + + //find this now to remove it later. + var tn = FindScenarioNodeTreeNode(CurrentScenarioNode); + + bool res = false; + if (WorldForm != null) + { + lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... + { + res = CurrentScenario.ScenarioRegion.RemoveNode(CurrentScenarioNode); + } + } + else + { + res = CurrentScenario.ScenarioRegion.RemoveNode(CurrentScenarioNode); + } + if (!res) + { + MessageBox.Show("Unable to delete the scenario node. This shouldn't happen!"); + } + + SetScenarioHasChangedUI(true); + + CurrentScenarioNode = null; + if ((tn != null) && (tn.Parent != null)) + { + tn.Parent.Text = "Points (" + (CurrentScenario?.ScenarioRegion?.Nodes?.Count ?? 0).ToString() + ")"; + tn.Parent.Nodes.Remove(tn); + } + else + { + //no need for this when removing the node above will select something else. + LoadScenarioNodeTabPages(); //this case really shouldn't happen... + } + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + + + return true; + } + + private void AddScenarioNodeToProject() + { + if (CurrentScenarioNode == null) return; + if (CurrentScenario != null) + { + AddScenarioToProject(CurrentScenario); + } + } + + private void LoadScenarioNodeTabPages() + { + populatingui = true; + + LoadScenarioDropDowns(); + + LoadScenarioPointTabPage(); + LoadScenarioEntityTabPage(); + LoadScenarioEntityPointTabPage(); + LoadScenarioChainTabPage(); + LoadScenarioChainEdgeTabPage(); + LoadScenarioChainNodeTabPage(); + LoadScenarioClusterTabPage(); + LoadScenarioClusterPointTabPage(); + populatingui = false; + + if (CurrentScenarioNode != null) + { + if (WorldForm != null) + { + WorldForm.SelectScenarioNode(CurrentScenarioNode); + } + } + } + + private void LoadScenarioDropDowns() + { + if (ScenarioPointTypeComboBox.Items.Count > 0) return; + + var types = Scenarios.ScenarioTypes; //these are loaded by Scenarios.Init + if (types == null) + { return; } + + var stypes = types.GetScenarioTypes(); + if (stypes == null) return; + + var pmsets = types.GetPedModelSets(); + if (pmsets == null) return; + + var vmsets = types.GetVehicleModelSets(); + if (vmsets == null) return; + + ScenarioPointTypeComboBox.Items.Clear(); + ScenarioPointTypeComboBox.Items.Add(""); + ScenarioClusterPointTypeComboBox.Items.Clear(); + ScenarioClusterPointTypeComboBox.Items.Add(""); + ScenarioChainNodeTypeComboBox.Items.Clear(); + ScenarioChainNodeTypeComboBox.Items.Add(""); + foreach (var stype in stypes) + { + ScenarioPointTypeComboBox.Items.Add(stype); + ScenarioClusterPointTypeComboBox.Items.Add(stype); + ScenarioChainNodeTypeComboBox.Items.Add(stype); + } + + ScenarioPointModelSetComboBox.Items.Clear(); + ScenarioPointModelSetComboBox.Items.Add(""); + ScenarioClusterPointModelSetComboBox.Items.Clear(); + ScenarioClusterPointModelSetComboBox.Items.Add(""); + foreach (var pmset in pmsets) + { + ScenarioPointModelSetComboBox.Items.Add(pmset); + ScenarioClusterPointModelSetComboBox.Items.Add(pmset); + } + foreach (var vmset in vmsets) + { + ScenarioPointModelSetComboBox.Items.Add(vmset); + ScenarioClusterPointModelSetComboBox.Items.Add(vmset); + } + + + ScenarioEntityPointAvailableInMpSpComboBox.Items.Clear(); + ScenarioEntityPointAvailableInMpSpComboBox.Items.Add(Unk_3573596290.kBoth); + ScenarioEntityPointAvailableInMpSpComboBox.Items.Add(Unk_3573596290.kOnlySp); + ScenarioEntityPointAvailableInMpSpComboBox.Items.Add(Unk_3573596290.kOnlyMp); + + + ScenarioChainEdgeActionComboBox.Items.Clear(); + ScenarioChainEdgeActionComboBox.Items.Add(Unk_3609807418.Move); + ScenarioChainEdgeActionComboBox.Items.Add(Unk_3609807418.Unk_7865678); + ScenarioChainEdgeActionComboBox.Items.Add(Unk_3609807418.MoveFollowMaster); + + ScenarioChainEdgeNavModeComboBox.Items.Clear(); + ScenarioChainEdgeNavModeComboBox.Items.Add(Unk_3971773454.Direct); + ScenarioChainEdgeNavModeComboBox.Items.Add(Unk_3971773454.NavMesh); + ScenarioChainEdgeNavModeComboBox.Items.Add(Unk_3971773454.Roads); + + ScenarioChainEdgeNavSpeedComboBox.Items.Clear(); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_00_3279574318); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_01_2212923970); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_02_4022799658); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_03_1425672334); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_04_957720931); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_05_3795195414); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_06_2834622009); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_07_1876554076); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_08_698543797); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_09_1544199634); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_10_2725613303); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_11_4033265820); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_12_3054809929); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_13_3911005380); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_14_3717649022); + ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_15_3356026130); + + } + + private void LoadScenarioPointTabPage() + { + var p = CurrentScenarioNode?.MyPoint; + if (p == null) + { + ScenarioPointPanel.Enabled = false; + ScenarioPointCheckBox.Checked = false; + ScenarioPointAddToProjectButton.Enabled = false; + ScenarioPointDeleteButton.Enabled = false; + ScenarioPointPositionTextBox.Text = ""; + ScenarioPointDirectionTextBox.Text = ""; + ScenarioPointTypeComboBox.SelectedItem = null; + ScenarioPointModelSetComboBox.SelectedItem = null; + ScenarioPointInteriorTextBox.Text = ""; + ScenarioPointInteriorHashLabel.Text = "Hash: 0"; + ScenarioPointGroupTextBox.Text = ""; + ScenarioPointGroupHashLabel.Text = "Hash: 0"; + ScenarioPointImapTextBox.Text = ""; + ScenarioPointImapHashLabel.Text = "Hash: 0"; + ScenarioPointTimeStartUpDown.Value = 0; + ScenarioPointTimeEndUpDown.Value = 0; + ScenarioPointProbabilityUpDown.Value = 0; + ScenarioPointSpOnlyFlagUpDown.Value = 0; + ScenarioPointRadiusUpDown.Value = 0; + ScenarioPointWaitTimeUpDown.Value = 0; + ScenarioPointFlagsValueUpDown.Value = 0; + foreach (int i in ScenarioPointFlagsCheckedListBox.CheckedIndices) + { + ScenarioPointFlagsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked); + } + } + else + { + ScenarioPointPanel.Enabled = true; + ScenarioPointCheckBox.Checked = true; + ScenarioPointDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); + ScenarioPointAddToProjectButton.Enabled = !ScenarioPointDeleteButton.Enabled; + ScenarioPointPositionTextBox.Text = FloatUtil.GetVector3String(p.Position); + ScenarioPointDirectionTextBox.Text = FloatUtil.ToString(p.Direction); + ScenarioPointTypeComboBox.SelectedItem = ((object)p.Type) ?? ""; + ScenarioPointModelSetComboBox.SelectedItem = ((object)p.ModelSet) ?? ""; + ScenarioPointInteriorTextBox.Text = p.InteriorName.ToString(); + ScenarioPointInteriorHashLabel.Text = "Hash: " + p.InteriorName.Hash.ToString(); + ScenarioPointGroupTextBox.Text = p.GroupName.ToString(); + ScenarioPointGroupHashLabel.Text = "Hash: " + p.GroupName.Hash.ToString(); + ScenarioPointImapTextBox.Text = p.IMapName.ToString(); + ScenarioPointImapHashLabel.Text = "Hash: " + p.IMapName.Hash.ToString(); + ScenarioPointTimeStartUpDown.Value = p.TimeStart; + ScenarioPointTimeEndUpDown.Value = p.TimeEnd; + ScenarioPointProbabilityUpDown.Value = p.Probability; + ScenarioPointSpOnlyFlagUpDown.Value = p.SpOnlyFlag; + ScenarioPointRadiusUpDown.Value = p.Radius; + ScenarioPointWaitTimeUpDown.Value = p.WaitTime; + var iflags = (int)p.Flags; + ScenarioPointFlagsValueUpDown.Value = iflags; + for (int i = 0; i < ScenarioPointFlagsCheckedListBox.Items.Count; i++) + { + var c = ((iflags & (1 << i)) > 0); + ScenarioPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); + } + } + } + + private void LoadScenarioEntityTabPage() + { + var e = CurrentScenarioNode?.Entity; + if (e == null) + { + ScenarioEntityPanel.Enabled = false; + ScenarioEntityCheckBox.Checked = false; + ScenarioEntityAddToProjectButton.Enabled = false; + ScenarioEntityDeleteButton.Enabled = false; + ScenarioEntityPositionTextBox.Text = ""; + ScenarioEntityTypeTextBox.Text = ""; + ScenarioEntityTypeHashLabel.Text = "Hash: 0"; + ScenarioEntityUnk1UpDown.Value = 0; + ScenarioEntityUnk2UpDown.Value = 0; + ScenarioEntityInfoLabel.Text = "0 override points"; + ScenarioEntityPointsListBox.Items.Clear(); + ScenarioEntityAddPointButton.Enabled = false; + } + else + { + ScenarioEntityPanel.Enabled = true; + ScenarioEntityCheckBox.Checked = true; + ScenarioEntityDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); + ScenarioEntityAddToProjectButton.Enabled = !ScenarioEntityDeleteButton.Enabled; + ScenarioEntityPositionTextBox.Text = FloatUtil.GetVector3String(e.Position); + ScenarioEntityTypeTextBox.Text = e.TypeName.ToString(); + ScenarioEntityTypeHashLabel.Text = "Hash: " + e.TypeName.Hash.ToString(); + ScenarioEntityUnk1UpDown.Value = e.Unk1; + ScenarioEntityUnk2UpDown.Value = e.Unk2; + var pc = e.ScenarioPoints?.Length ?? 0; + ScenarioEntityInfoLabel.Text = pc.ToString() + " override point" + ((pc != 1) ? "s" : ""); + ScenarioEntityPointsListBox.Items.Clear(); + ScenarioEntityAddPointButton.Enabled = true; + + if (e.ScenarioPoints != null) + { + foreach (var point in e.ScenarioPoints) + { + ScenarioEntityPointsListBox.Items.Add(point); + } + if (CurrentScenarioNode.EntityPoint != null) + { + ScenarioEntityPointsListBox.SelectedItem = CurrentScenarioNode.EntityPoint; + } + } + } + } + + private void LoadScenarioEntityPointTabPage() + { + var p = CurrentScenarioNode?.EntityPoint; + if (p == null) + { + ScenarioEntityPointPanel.Enabled = false; + ScenarioEntityPointCheckBox.Checked = false; + ScenarioEntityPointAddToProjectButton.Enabled = false; + ScenarioEntityPointDeleteButton.Enabled = false; + ScenarioEntityPointNameTextBox.Text = ""; + ScenarioEntityPointNameHashLabel.Text = "Hash: 0"; + ScenarioEntityPointPositionTextBox.Text = ""; + ScenarioEntityPointRotationTextBox.Text = ""; + ScenarioEntityPointSpawnTypeTextBox.Text = ""; + ScenarioEntityPointSpawnTypeHashLabel.Text = "Hash: 0"; + ScenarioEntityPointPedTypeTextBox.Text = ""; + ScenarioEntityPointPedTypeHashLabel.Text = "Hash: 0"; + ScenarioEntityPointGroupTextBox.Text = ""; + ScenarioEntityPointGroupHashLabel.Text = "Hash: 0"; + ScenarioEntityPointInteriorTextBox.Text = ""; + ScenarioEntityPointInteriorHashLabel.Text = "Hash: 0"; + ScenarioEntityPointRequiredImapTextBox.Text = ""; + ScenarioEntityPointRequiredImapHashLabel.Text = "Hash: 0"; + ScenarioEntityPointAvailableInMpSpComboBox.SelectedItem = null; + ScenarioEntityPointProbabilityTextBox.Text = ""; + ScenarioEntityPointTimeTillPedLeavesTextBox.Text = ""; + ScenarioEntityPointRadiusTextBox.Text = ""; + ScenarioEntityPointStartUpDown.Value = 0; + ScenarioEntityPointEndUpDown.Value = 0; + ScenarioEntityPointExtendedRangeCheckBox.Checked = false; + ScenarioEntityPointShortRangeCheckBox.Checked = false; + ScenarioEntityPointHighPriCheckBox.Checked = false; + ScenarioEntityPointFlagsUpDown.Value = 0; + foreach (int i in ScenarioEntityPointFlagsCheckedListBox.CheckedIndices) + { + ScenarioEntityPointFlagsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked); + } + } + else + { + ScenarioEntityPointPanel.Enabled = true; + ScenarioEntityPointCheckBox.Checked = true; + ScenarioEntityPointDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); + ScenarioEntityPointAddToProjectButton.Enabled = !ScenarioEntityPointDeleteButton.Enabled; + ScenarioEntityPointNameTextBox.Text = p.NameHash.ToString(); + ScenarioEntityPointNameHashLabel.Text = "Hash: " + p.NameHash.Hash.ToString(); + ScenarioEntityPointPositionTextBox.Text = FloatUtil.GetVector3String(p.OffsetPosition); + ScenarioEntityPointRotationTextBox.Text = FloatUtil.GetVector4String(p.OffsetRotation); + ScenarioEntityPointSpawnTypeTextBox.Text = p.SpawnType.ToString(); + ScenarioEntityPointSpawnTypeHashLabel.Text = "Hash: " + p.SpawnType.Hash.ToString(); + ScenarioEntityPointPedTypeTextBox.Text = p.PedType.ToString(); + ScenarioEntityPointPedTypeHashLabel.Text = "Hash: " + p.PedType.Hash.ToString(); + ScenarioEntityPointGroupTextBox.Text = p.Group.ToString(); + ScenarioEntityPointGroupHashLabel.Text = "Hash: " + p.Group.Hash.ToString(); + ScenarioEntityPointInteriorTextBox.Text = p.Interior.ToString(); + ScenarioEntityPointInteriorHashLabel.Text = "Hash: " + p.Interior.Hash.ToString(); + ScenarioEntityPointRequiredImapTextBox.Text = p.RequiredImap.ToString(); + ScenarioEntityPointRequiredImapHashLabel.Text = "Hash: " + p.RequiredImap.Hash.ToString(); + ScenarioEntityPointAvailableInMpSpComboBox.SelectedItem = p.AvailableInMpSp; + ScenarioEntityPointProbabilityTextBox.Text = FloatUtil.ToString(p.Probability); + ScenarioEntityPointTimeTillPedLeavesTextBox.Text = FloatUtil.ToString(p.TimeTillPedLeaves); + ScenarioEntityPointRadiusTextBox.Text = FloatUtil.ToString(p.Radius); + ScenarioEntityPointStartUpDown.Value = p.StartTime; + ScenarioEntityPointEndUpDown.Value = p.EndTime; + ScenarioEntityPointExtendedRangeCheckBox.Checked = p.ExtendedRange; + ScenarioEntityPointShortRangeCheckBox.Checked = p.ShortRange; + ScenarioEntityPointHighPriCheckBox.Checked = p.HighPri; + var iflags = (int)p.Flags; + ScenarioEntityPointFlagsUpDown.Value = 0; + for (int i = 0; i < ScenarioEntityPointFlagsCheckedListBox.Items.Count; i++) + { + var c = ((iflags & (1 << i)) > 0); + ScenarioEntityPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); + } + + } + } + + private void LoadScenarioChainTabPage() + { + CurrentScenarioChainEdge = null; + + var n = CurrentScenarioNode?.ChainingNode; + if (n == null) + { + ScenarioChainAddToProjectButton.Enabled = false; + ScenarioChainDeleteButton.Enabled = false; + ScenarioChainEdgesListBox.Items.Clear(); + ScenarioChainEdgeCountLabel.Text = "Edge Count: 0"; + ScenarioChainUnk1UpDown.Value = 0; + } + else + { + ScenarioChainDeleteButton.Enabled = ScenarioChainNodeDeleteButton.Enabled;// ScenarioExistsInProject(CurrentScenario); + ScenarioChainAddToProjectButton.Enabled = !ScenarioChainDeleteButton.Enabled; + ScenarioChainEdgesListBox.Items.Clear(); + ScenarioChainEdgeCountLabel.Text = "Edge Count: " + (n.Chain?.EdgeIds?.Length ?? 0).ToString(); + ScenarioChainUnk1UpDown.Value = n.Chain?.Unk1 ?? 0; + + if ((n.Chain != null) && (n.Chain.Edges != null)) + { + foreach (var edge in n.Chain.Edges) + { + ScenarioChainEdgesListBox.Items.Add(edge); + } + } + else + { } + } + } + + private void LoadScenarioChainEdgeTabPage() + { + var e = CurrentScenarioChainEdge; + if (e == null) + { + ScenarioChainEdgePanel.Enabled = false; + ScenarioChainEdgeNodeIndexFromUpDown.Value = 0; + ScenarioChainEdgeNodeIndexToUpDown.Value = 0; + ScenarioChainEdgeActionComboBox.SelectedItem = null; + ScenarioChainEdgeNavModeComboBox.SelectedItem = null; + ScenarioChainEdgeNavSpeedComboBox.SelectedItem = null; + ScenarioChainMoveEdgeDownButton.Enabled = false; + ScenarioChainMoveEdgeUpButton.Enabled = false; + } + else + { + ScenarioChainEdgePanel.Enabled = true; + ScenarioChainEdgeNodeIndexFromUpDown.Value = e.NodeIndexFrom; + ScenarioChainEdgeNodeIndexToUpDown.Value = e.NodeIndexTo; + ScenarioChainEdgeActionComboBox.SelectedItem = e.Action; + ScenarioChainEdgeNavModeComboBox.SelectedItem = e.NavMode; + ScenarioChainEdgeNavSpeedComboBox.SelectedItem = e.NavSpeed; + ScenarioChainMoveEdgeDownButton.Enabled = true; + ScenarioChainMoveEdgeUpButton.Enabled = true; + + if (WorldForm != null) + { + WorldForm.SelectScenarioEdge(CurrentScenarioNode, e); + } + } + } + + private void LoadScenarioChainNodeTabPage() + { + var n = CurrentScenarioNode?.ChainingNode; + if (n == null) + { + ScenarioChainNodePanel.Enabled = false; + ScenarioChainNodeCheckBox.Checked = false; + ScenarioChainNodeAddToProjectButton.Enabled = false; + ScenarioChainNodeDeleteButton.Enabled = false; + ScenarioChainNodePositionTextBox.Text = ""; + ScenarioChainNodeUnk1TextBox.Text = ""; + ScenarioChainNodeUnk1HashLabel.Text = "Hash: 0"; + ScenarioChainNodeTypeComboBox.SelectedItem = null; + ScenarioChainNodeFirstCheckBox.Checked = false; + ScenarioChainNodeLastCheckBox.Checked = false; + ScenarioChainNodeIndexTextBox.Text = ""; + } + else + { + ScenarioChainNodePanel.Enabled = true; + ScenarioChainNodeCheckBox.Checked = true; + ScenarioChainNodeDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); + ScenarioChainNodeAddToProjectButton.Enabled = !ScenarioChainNodeDeleteButton.Enabled; + ScenarioChainNodePositionTextBox.Text = FloatUtil.GetVector3String(n.Position); + ScenarioChainNodeUnk1TextBox.Text = n.Unk1.ToString(); + ScenarioChainNodeUnk1HashLabel.Text = "Hash: " + n.Unk1.Hash.ToString(); + ScenarioChainNodeTypeComboBox.SelectedItem = ((object)n.Type) ?? ""; + ScenarioChainNodeFirstCheckBox.Checked = !n.NotFirst; + ScenarioChainNodeLastCheckBox.Checked = !n.NotLast; + ScenarioChainNodeIndexTextBox.Text = n.NodeIndex.ToString(); + } + } + + private void LoadScenarioClusterTabPage() + { + var c = CurrentScenarioNode?.Cluster; + if (c == null) + { + ScenarioClusterPanel.Enabled = false; + ScenarioClusterCheckBox.Checked = false; + ScenarioClusterAddToProjectButton.Enabled = false; + ScenarioClusterDeleteButton.Enabled = false; + ScenarioClusterCenterTextBox.Text = ""; + ScenarioClusterRadiusTextBox.Text = ""; + ScenarioClusterUnk1TextBox.Text = ""; + ScenarioClusterUnk2CheckBox.Checked = false; + ScenarioClusterPointsListBox.Items.Clear(); + ScenarioClusterAddPointButton.Enabled = false; + } + else + { + ScenarioClusterPanel.Enabled = true; + ScenarioClusterCheckBox.Checked = true; + ScenarioClusterDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); + ScenarioClusterAddToProjectButton.Enabled = !ScenarioClusterDeleteButton.Enabled; + ScenarioClusterCenterTextBox.Text = FloatUtil.GetVector3String(c.Position); + ScenarioClusterRadiusTextBox.Text = FloatUtil.ToString(c.Radius); + ScenarioClusterUnk1TextBox.Text = FloatUtil.ToString(c.Unk1); + ScenarioClusterUnk2CheckBox.Checked = c.Unk2; + ScenarioClusterPointsListBox.Items.Clear(); + ScenarioClusterAddPointButton.Enabled = true; + + if (c.Points != null) + { + if (c.Points.MyPoints != null) + { + foreach (var point in c.Points.MyPoints) + { + ScenarioClusterPointsListBox.Items.Add(point); + } + if (CurrentScenarioNode.ClusterMyPoint != null) + { + ScenarioClusterPointsListBox.SelectedItem = CurrentScenarioNode.ClusterMyPoint; + } + } + if (c.Points.LoadSavePoints != null) + { + foreach (var point in c.Points.LoadSavePoints) + { + ScenarioClusterPointsListBox.Items.Add(point); + } + if (CurrentScenarioNode.ClusterLoadSavePoint != null) + { + ScenarioClusterPointsListBox.SelectedItem = CurrentScenarioNode.ClusterLoadSavePoint; + } + } + } + + } + } + + private void LoadScenarioClusterPointTabPage() + { + var p = CurrentScenarioNode?.ClusterMyPoint; + if (p == null) + { + ScenarioClusterPointPanel.Enabled = false; + ScenarioClusterPointCheckBox.Checked = false; + ScenarioClusterPointAddToProjectButton.Enabled = false; + ScenarioClusterPointDeleteButton.Enabled = false; + ScenarioClusterPointPositionTextBox.Text = ""; + ScenarioClusterPointDirectionTextBox.Text = ""; + ScenarioClusterPointTypeComboBox.SelectedItem = null; + ScenarioClusterPointModelSetComboBox.SelectedItem = null; + ScenarioClusterPointInteriorTextBox.Text = ""; + ScenarioClusterPointInteriorHashLabel.Text = "Hash: 0"; + ScenarioClusterPointGroupTextBox.Text = ""; + ScenarioClusterPointGroupHashLabel.Text = "Hash: 0"; + ScenarioClusterPointImapTextBox.Text = ""; + ScenarioClusterPointImapHashLabel.Text = "Hash: 0"; + ScenarioClusterPointTimeStartUpDown.Value = 0; + ScenarioClusterPointTimeEndUpDown.Value = 0; + ScenarioClusterPointProbabilityUpDown.Value = 0; + ScenarioClusterPointAnimalFlagUpDown.Value = 0; + ScenarioClusterPointRadiusUpDown.Value = 0; + ScenarioClusterPointWaitTimeUpDown.Value = 0; + ScenarioClusterPointFlagsUpDown.Value = 0; + foreach (int i in ScenarioClusterPointFlagsCheckedListBox.CheckedIndices) + { + ScenarioClusterPointFlagsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked); + } + } + else + { + ScenarioClusterPointPanel.Enabled = true; + ScenarioClusterPointCheckBox.Checked = true; + ScenarioClusterPointDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); + ScenarioClusterPointAddToProjectButton.Enabled = !ScenarioClusterPointDeleteButton.Enabled; + ScenarioClusterPointPositionTextBox.Text = FloatUtil.GetVector3String(p.Position); + ScenarioClusterPointDirectionTextBox.Text = FloatUtil.ToString(p.Direction); + ScenarioClusterPointTypeComboBox.SelectedItem = ((object)p.Type) ?? ""; + ScenarioClusterPointModelSetComboBox.SelectedItem = ((object)p.ModelSet) ?? ""; + ScenarioClusterPointInteriorTextBox.Text = p.InteriorName.ToString(); + ScenarioClusterPointInteriorHashLabel.Text = "Hash: " + p.InteriorName.Hash.ToString(); + ScenarioClusterPointGroupTextBox.Text = p.GroupName.ToString(); + ScenarioClusterPointGroupHashLabel.Text = "Hash: " + p.GroupName.Hash.ToString(); + ScenarioClusterPointImapTextBox.Text = p.IMapName.ToString(); + ScenarioClusterPointImapHashLabel.Text = "Hash: " + p.IMapName.Hash.ToString(); + ScenarioClusterPointTimeStartUpDown.Value = p.TimeStart; + ScenarioClusterPointTimeEndUpDown.Value = p.TimeEnd; + ScenarioClusterPointProbabilityUpDown.Value = p.Probability; + ScenarioClusterPointAnimalFlagUpDown.Value = p.SpOnlyFlag; + ScenarioClusterPointRadiusUpDown.Value = p.Radius; + ScenarioClusterPointWaitTimeUpDown.Value = p.WaitTime; + var iflags = (int)p.Flags; + ScenarioClusterPointFlagsUpDown.Value = iflags; + for (int i = 0; i < ScenarioClusterPointFlagsCheckedListBox.Items.Count; i++) + { + var c = ((iflags & (1 << i)) > 0); + ScenarioClusterPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); + } + } + } + + private void SelectScenarioNodeTabPages(ScenarioNode node) + { + //select the appropriate tab page(s) for the given node. + + if (node == null) return; + + bool reseltree = ProjectTreeView.Focused; + bool change = false; + + if (node.MyPoint != null) + { + bool sw = true; + if ((node.Entity != null) && (ScenarioTabControl.SelectedTab == ScenarioEntityTabPage)) + { + sw = false; + } + if ((node.EntityPoint != null) && (ScenarioTabControl.SelectedTab == ScenarioEntityPointTabPage)) + { + sw = false; + } + if ((node.Cluster != null) && (ScenarioTabControl.SelectedTab == ScenarioClusterTabPage)) + { + sw = false; + } + if ((node.ClusterMyPoint != null) && (ScenarioTabControl.SelectedTab == ScenarioClusterPointTabPage)) + { + sw = false; + } + if ((node.ChainingNode != null) && (ScenarioTabControl.SelectedTab == ScenarioChainTabPage)) + { + sw = false; + } + if ((node.ChainingNode != null) && (ScenarioTabControl.SelectedTab == ScenarioChainNodeTabPage)) + { + sw = false; + } + + if (sw) + { + change = ScenarioTabControl.SelectedTab != ScenarioPointTabPage; + ScenarioTabControl.SelectedTab = ScenarioPointTabPage; + } + } + else if (node.EntityPoint != null) + { + if (ScenarioTabControl.SelectedTab != ScenarioEntityTabPage) + { + change = ScenarioTabControl.SelectedTab != ScenarioEntityPointTabPage; + ScenarioTabControl.SelectedTab = ScenarioEntityPointTabPage; + } + } + else if (node.Entity != null) + { + change = ScenarioTabControl.SelectedTab != ScenarioEntityTabPage; + ScenarioTabControl.SelectedTab = ScenarioEntityTabPage; + } + else if (node.ClusterMyPoint != null) + { + if (ScenarioTabControl.SelectedTab != ScenarioClusterTabPage) + { + change = ScenarioTabControl.SelectedTab != ScenarioClusterPointTabPage; + ScenarioTabControl.SelectedTab = ScenarioClusterPointTabPage; + } + } + else if (node.Cluster != null) + { + change = ScenarioTabControl.SelectedTab != ScenarioClusterTabPage; + ScenarioTabControl.SelectedTab = ScenarioClusterTabPage; + } + else if (node.ChainingNode != null) + { + if (ScenarioTabControl.SelectedTab != ScenarioChainTabPage) + { + change = ScenarioTabControl.SelectedTab != ScenarioChainNodeTabPage; + ScenarioTabControl.SelectedTab = ScenarioChainNodeTabPage; + } + } + else //if (node.MyPoint != null) + { + change = ScenarioTabControl.SelectedTab != ScenarioPointTabPage; + ScenarioTabControl.SelectedTab = ScenarioPointTabPage; + } + + if (reseltree && change) + { + ProjectTreeView.Focus(); + } + } + + public bool IsCurrentScenarioNode(ScenarioNode node) + { + return node == CurrentScenarioNode; + } + + + + + private void AddScenarioChain() + { + if (CurrentScenario.ScenarioRegion == null) return; + var paths = CurrentScenario?.CScenarioPointRegion?.Paths; + if (paths == null) return; + + var copy = CurrentScenarioNode?.ChainingNode?.Chain; + var copyn = CurrentScenarioNode?.ChainingNode; + var copyp = CurrentScenarioNode?.MyPoint; + var copye = CurrentScenarioChainEdge; + + MCScenarioChain chain = new MCScenarioChain(); + if (copy != null) + { + chain.Data = copy.Data; + chain._Data.EdgeIds = new Array_ushort(); //start empty.. not really necessary + } + + paths.AddChain(chain); + + + //add 2 new nodes to the new chain. + var pos1 = GetSpawnPos(10.0f); + var pos2 = pos1 + Vector3.UnitX; + + var n1 = CurrentScenario.ScenarioRegion.AddNode(); + var n2 = CurrentScenario.ScenarioRegion.AddNode(); + + if (copyp != null) + { + n1.MyPoint.CopyFrom(copyp); + n2.MyPoint.CopyFrom(copyp); + } + + n1.ChainingNode = new MCScenarioChainingNode(); + n2.ChainingNode = new MCScenarioChainingNode(); + + if (copyn != null) + { + n1.ChainingNode.CopyFrom(copyn); + n2.ChainingNode.CopyFrom(copyn); + } + + n1.ChainingNode.NotLast = true; + n2.ChainingNode.NotFirst = true; + + paths.AddNode(n1.ChainingNode); + paths.AddNode(n2.ChainingNode); + + n1.ChainingNode.Chain = chain; + n2.ChainingNode.Chain = chain; + + var ed = new MCScenarioChainingEdge(); + + if (copye != null) + { + ed.Data = copye.Data; + } + + ed.NodeFrom = n1.ChainingNode; + ed.NodeTo = n2.ChainingNode; + ed.NodeIndexFrom = (ushort)n1.ChainingNode.NodeIndex; + ed.NodeIndexTo = (ushort)n2.ChainingNode.NodeIndex; + + paths.AddEdge(ed); + chain.AddEdge(ed); + + + + n1.SetPosition(pos1); + n2.SetPosition(pos2); + + + + + + + LoadProjectTree(); + + TrySelectScenarioNodeTreeNode(n1); + CurrentScenarioNode = n1; + CurrentScenarioChainEdge = ed; + LoadScenarioChainTabPage(); + //LoadScenarioTabPage(); + //LoadScenarioNodeTabPages(); + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + else + { + CurrentScenario.ScenarioRegion.BuildBVH(); + CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... + } + } + + private void AddScenarioEdge() + { + var chain = CurrentScenarioNode?.ChainingNode?.Chain; + if (chain == null) return; + var paths = CurrentScenario?.CScenarioPointRegion?.Paths; + if (paths == null) return; + + MCScenarioChainingEdge edge = new MCScenarioChainingEdge(); + if (CurrentScenarioChainEdge != null) + { + edge.Data = CurrentScenarioChainEdge.Data; + } + + paths.AddEdge(edge); + chain.AddEdge(edge); + + CurrentScenarioChainEdge = edge; + + UpdateScenarioEdgeLinkage(); + + LoadScenarioChainTabPage(); + + ScenarioChainEdgesListBox.SelectedItem = edge; + } + + private void RemoveScenarioEdge() + { + if (CurrentScenarioChainEdge == null) return; + if (CurrentScenario == null) return; + + var chain = CurrentScenarioNode?.ChainingNode?.Chain; + if (chain == null) return; + var paths = CurrentScenario?.CScenarioPointRegion?.Paths; + if (paths == null) return; + + if (MessageBox.Show("Are you sure you want to delete this scenario chain edge?\n" + CurrentScenarioChainEdge.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return; + } + + chain.RemoveEdge(CurrentScenarioChainEdge); + paths.RemoveEdge(CurrentScenarioChainEdge); + + LoadScenarioChainTabPage(); + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + WorldForm.SelectScenarioEdge(CurrentScenarioNode, null); + } + } + + private void MoveScenarioEdge(bool moveDown) + { + + var chain = CurrentScenarioNode?.ChainingNode?.Chain; + if (chain == null) return; + if (chain.Edges == null) return; + if (chain.EdgeIds == null) return; + + if (CurrentScenarioChainEdge == null) return; + + var edges = CurrentScenario?.CScenarioPointRegion?.Paths?.Edges; + if (edges == null) return; + + + int lasti = (chain.Edges?.Length ?? 0) - 1; + + var edgeid = 0; + for (int i = 0; i < chain.Edges.Length; i++) + { + if (chain.Edges[i] == CurrentScenarioChainEdge) + { + edgeid = i; + break; + } + } + + if (!moveDown && (edgeid <= 0)) return; + if (moveDown && (edgeid >= lasti)) return; + + var swapid = edgeid + (moveDown ? 1 : -1); + var swaped = chain.Edges[swapid]; + + chain.Edges[swapid] = CurrentScenarioChainEdge; + chain.EdgeIds[swapid] = (ushort)CurrentScenarioChainEdge.EdgeIndex; + chain.Edges[edgeid] = swaped; + chain.EdgeIds[edgeid] = (ushort)swapid; + + var ce = CurrentScenarioChainEdge; + + LoadScenarioChainTabPage(); + + CurrentScenarioChainEdge = ce; + + ScenarioChainEdgesListBox.SelectedItem = ce; + + //LoadScenarioChainEdgeTabPage(); + + } + + private void UpdateScenarioEdgeLinkage() + { + if (CurrentScenarioChainEdge == null) return; + if (CurrentScenario == null) return; + + + var chains = CurrentScenario?.CScenarioPointRegion?.Paths; + if (chains == null) return; + + var nodes = chains.Nodes; + if (nodes == null) return; + + ushort nifrom = CurrentScenarioChainEdge.NodeIndexFrom; + ushort nito = CurrentScenarioChainEdge.NodeIndexTo; + + if (nifrom < nodes.Length) CurrentScenarioChainEdge.NodeFrom = nodes[nifrom]; + if (nito < nodes.Length) CurrentScenarioChainEdge.NodeTo = nodes[nito]; + + ////need to rebuild the link verts.. updating the graphics should do it... + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + + private void DeleteScenarioChain() + { + if (CurrentScenario == null) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ChainingNode == null) return; + if (CurrentScenarioNode.ChainingNode.Chain == null) return; + + var chain = CurrentScenarioNode.ChainingNode.Chain; + + var paths = CurrentScenario.CScenarioPointRegion?.Paths; + if (paths == null) return; + + var rgn = CurrentScenario.ScenarioRegion; + if (rgn == null) return; + + + if (MessageBox.Show("Are you sure you want to delete this scenario chain?\n" + chain.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return; + } + + bool delpoints = false; + if (MessageBox.Show("Delete all Scenario Points for this chain as well?", "Confirm delete points", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + delpoints = true; + } + + + + Dictionary ndict = new Dictionary(); + + var edges = chain.Edges; + foreach (var edge in edges) + { + //paths.RemoveEdge(edge); //removing nodes also removes edges! + paths.RemoveNode(edge.NodeFrom); + paths.RemoveNode(edge.NodeTo); + + ndict[edge.NodeFrom] = 1; + ndict[edge.NodeTo] = 1; + } + + paths.RemoveChain(chain); + + + + + List delnodes = new List(); + foreach (var node in rgn.Nodes) + { + if ((node.ChainingNode != null) && (ndict.ContainsKey(node.ChainingNode))) + { + delnodes.Add(node); + } + } + foreach (var delnode in delnodes) + { + delnode.ChainingNode = null;//this chaining node has been removed from the region. remove this association. + if (delpoints) + { + rgn.RemoveNode(delnode); + } + } + + + + var cn = CurrentScenarioNode; + var cs = CurrentScenario; + + LoadProjectTree(); + + if (!delpoints && (cn != null)) + { + TrySelectScenarioNodeTreeNode(cn); + } + else + { + TrySelectScenarioTreeNode(cs); + } + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(cs, false); + if (delpoints) + { + WorldForm.SelectItem(null, null, null); + } + } + else if (cs?.ScenarioRegion != null) + { + cs.ScenarioRegion.BuildBVH(); + cs.ScenarioRegion.BuildVertices(); //for the graphics... + } + } + + + + + private void AddScenarioCluster()//TODO: add defualt cluster points to new cluster + { + if (CurrentScenario == null) return; + + var sr = CurrentScenario.ScenarioRegion; + if (sr == null) return; + + var rgn = CurrentScenario.CScenarioPointRegion; + if (rgn == null) return; + + var copy = CurrentScenarioNode?.Cluster; + + + MCScenarioPointCluster cluster = new MCScenarioPointCluster(rgn, copy); + List clusterpoints = new List(); + + if (copy != null) + { + if (copy.Points?.MyPoints != null) + { + clusterpoints.AddRange(copy.Points.MyPoints); + } + } + + + + rgn.AddCluster(cluster); //add the base cluster to the region. + + + var pos1 = GetSpawnPos(10.0f); + + var ncopy = new ScenarioNode(CurrentScenario);//copy an empty node to start with, to avoid creating default MyPoint + var nc = sr.AddNode(ncopy); //add the base cluster's display node. + nc.Cluster = cluster; + + nc.SetPosition(pos1); + + if (cluster.Points != null) + { + foreach (var cpt in clusterpoints) + { + //TODO: copy cluster points.... + //or create some default points! + } + } + + + + + + + + + LoadProjectTree(); + + TrySelectScenarioNodeTreeNode(nc); + CurrentScenarioNode = nc; + LoadScenarioClusterTabPage(); + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + else + { + CurrentScenario.ScenarioRegion.BuildBVH(); + CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... + } + + } + + private void DeleteScenarioCluster() + { + if (CurrentScenario == null) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.Cluster == null) return; + + var cluster = CurrentScenarioNode.Cluster; + + var rgn = CurrentScenario.ScenarioRegion; + if (rgn == null) return; + + var crgn = CurrentScenario.CScenarioPointRegion; + if (crgn == null) return; + + + if (MessageBox.Show("Are you sure you want to delete this scenario cluster?\n" + cluster.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return; + } + + bool delpoints = false; + if (MessageBox.Show("Delete all Scenario Points for this cluster as well?", "Confirm delete points", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + delpoints = true; + } + + + crgn.RemoveCluster(cluster); + + + + + + Dictionary ndict = new Dictionary(); + if (cluster?.Points?.MyPoints != null) + { + foreach (var point in cluster.Points.MyPoints) + { + ndict[point] = 1; + } + } + List delnodes = new List(); + foreach (var node in rgn.Nodes) + { + if ((node.ClusterMyPoint != null) && (ndict.ContainsKey(node.ClusterMyPoint))) + { + delnodes.Add(node); + } + else if (node.Cluster == cluster) + { + delnodes.Add(node); + } + } + foreach (var delnode in delnodes) + { + if (!delpoints && (crgn.Points != null) && (delnode.ClusterMyPoint != null)) + { + var copypt = new MCScenarioPoint(crgn, delnode.ClusterMyPoint); + crgn.Points.AddMyPoint(copypt); + delnode.MyPoint = copypt; + } + bool iscl = false; + if ((delnode.Cluster != null) && (delnode.ClusterMyPoint == null) && (delnode.ClusterLoadSavePoint == null)) + { + iscl = true; + } + delnode.Cluster = null; + delnode.ClusterMyPoint = null;//this cluster point has been removed from the region. remove this association. + delnode.ClusterLoadSavePoint = null; + if (delpoints) + { + //if ((delnode.ChainingNode == null) && (delnode.EntityPoint == null)) + { + rgn.RemoveNode(delnode); + } + } + else if (iscl) + { + rgn.RemoveNode(delnode); //remove the cluster node itself. + } + } + + + + var cn = CurrentScenarioNode; + var cs = CurrentScenario; + + LoadProjectTree(); + + if (!delpoints && (cn != null)) + { + TrySelectScenarioNodeTreeNode(cn); + } + else + { + TrySelectScenarioTreeNode(cs); + } + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(cs, false); + if (delpoints || ((cn != null) && (cn.MyPoint == null))) + { + WorldForm.SelectItem(null, null, null); + } + } + else if (cs?.ScenarioRegion != null) + { + cs.ScenarioRegion.BuildBVH(); + cs.ScenarioRegion.BuildVertices(); //for the graphics... + } + + } + + private void AddScenarioClusterPoint() + { + if (CurrentScenario == null) return; + + var sr = CurrentScenario.ScenarioRegion; + if (sr == null) return; + + var rgn = CurrentScenario.CScenarioPointRegion; + if (rgn == null) return; + + var cluster = CurrentScenarioNode?.Cluster; + if (cluster == null) return; + + if (cluster.Points == null) + { + cluster.Points = new MCScenarioPointContainer(rgn); + cluster.Points.Parent = cluster; + } + + var copy = CurrentScenarioNode?.ClusterMyPoint; + + var pos1 = GetSpawnPos(10.0f); + var ori1 = copy?.Orientation ?? Quaternion.Identity; + + var cn = new ScenarioNode(CurrentScenario);//copy a blank node + var n = sr.AddNode(cn); + + var np = new MCScenarioPoint(rgn, copy); + cluster.Points.AddMyPoint(np); + + n.ClusterMyPoint = np; + n.Cluster = cluster; + + n.SetPosition(pos1); + n.SetOrientation(ori1); + + + LoadProjectTree(); + + TrySelectScenarioNodeTreeNode(n); + CurrentScenarioNode = n; + LoadScenarioClusterTabPage(); + LoadScenarioClusterPointTabPage(); + //LoadScenarioTabPage(); + //LoadScenarioNodeTabPages(); + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + else + { + CurrentScenario.ScenarioRegion.BuildBVH(); + CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... + } + } + + + private void AddScenarioEntity()//TODO: add default entity point(s) to entity + { + if (CurrentScenario == null) return; + + var sr = CurrentScenario.ScenarioRegion; + if (sr == null) return; + + var rgn = CurrentScenario.CScenarioPointRegion; + if (rgn == null) return; + + var copy = CurrentScenarioNode?.Entity; + + + MCScenarioEntityOverride entity = new MCScenarioEntityOverride(rgn, copy); + List entpoints = new List(); + + if (copy != null) + { + if (copy.ScenarioPoints != null) + { + entpoints.AddRange(copy.ScenarioPoints); + } + } + + + + + + + rgn.AddEntity(entity); //add the base entity to the region. + + + var pos1 = GetSpawnPos(10.0f); + + var ncopy = new ScenarioNode(CurrentScenario);//copy an empty node to start with, to avoid creating default MyPoint + var ne = sr.AddNode(ncopy); //add the base entity's display node. + ne.Entity = entity; + + ne.SetPosition(pos1); + + if (entity.ScenarioPoints != null) + { + foreach (var cpt in entpoints) + { + //TODO: copy entity points.... + //or create some default points! + } + } + + + + + + + + + LoadProjectTree(); + + TrySelectScenarioNodeTreeNode(ne); + CurrentScenarioNode = ne; + LoadScenarioEntityTabPage(); + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + else + { + CurrentScenario.ScenarioRegion.BuildBVH(); + CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... + } + + } + + private void DeleteScenarioEntity() + { + if (CurrentScenario == null) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.Entity == null) return; + + var entity = CurrentScenarioNode.Entity; + + var rgn = CurrentScenario.ScenarioRegion; + if (rgn == null) return; + + var crgn = CurrentScenario.CScenarioPointRegion; + if (crgn == null) return; + + + if (MessageBox.Show("Are you sure you want to delete this scenario entity override, and all its override points?\n" + entity.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return; + } + + //bool delpoints = false; + //if (MessageBox.Show("Delete all Scenario Points for this entity override as well?", "Confirm delete points", MessageBoxButtons.YesNo) == DialogResult.Yes) + //{ + // delpoints = true; + //} + + + crgn.RemoveEntity(entity); + + + + + + Dictionary ndict = new Dictionary(); + if (entity.ScenarioPoints != null) + { + foreach (var point in entity.ScenarioPoints) + { + ndict[point] = 1; + } + } + List delnodes = new List(); + foreach (var node in rgn.Nodes) + { + if ((node.EntityPoint != null) && (ndict.ContainsKey(node.EntityPoint))) + { + delnodes.Add(node); + } + else if (node.Entity == entity) + { + delnodes.Add(node); + } + } + foreach (var delnode in delnodes) + { + delnode.Entity = null; + delnode.EntityPoint = null;//this entity point has been removed from the region. remove this association. + rgn.RemoveNode(delnode); + } + + + + var cn = CurrentScenarioNode; + var cs = CurrentScenario; + + LoadProjectTree(); + + + TrySelectScenarioTreeNode(cs); + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(cs, false); + WorldForm.SelectItem(null, null, null); + } + else if (cs?.ScenarioRegion != null) + { + cs.ScenarioRegion.BuildBVH(); + cs.ScenarioRegion.BuildVertices(); //for the graphics... + } + } + + private void AddScenarioEntityPoint() + { + if (CurrentScenario == null) return; + + var sr = CurrentScenario.ScenarioRegion; + if (sr == null) return; + + var rgn = CurrentScenario.CScenarioPointRegion; + if (rgn == null) return; + + var entity = CurrentScenarioNode?.Entity; + if (entity == null) return; + + var copy = CurrentScenarioNode?.EntityPoint; + + var pos1 = GetSpawnPos(10.0f); + var ori1 = copy?.Orientation ?? Quaternion.Identity; + + var cn = new ScenarioNode(CurrentScenario);//copy a blank node + var n = sr.AddNode(cn); + + var np = new MCExtensionDefSpawnPoint(rgn, copy); + entity.AddScenarioPoint(np); + + n.EntityPoint = np; + n.Entity = entity; + + n.SetPosition(pos1); + n.SetOrientation(ori1); + + + LoadProjectTree(); + + TrySelectScenarioNodeTreeNode(n); + CurrentScenarioNode = n; + LoadScenarioEntityTabPage(); + LoadScenarioEntityPointTabPage(); + //LoadScenarioTabPage(); + //LoadScenarioNodeTabPages(); + + + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + else + { + CurrentScenario.ScenarioRegion.BuildBVH(); + CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... + } + } + + + + + + + public void GetVisibleYmaps(Camera camera, Dictionary ymaps) + { + if (hidegtavmap) + { + ymaps.Clear(); //remove all the gtav ymaps. + } + + if (renderentities && (CurrentProjectFile != null)) + { + lock (ymapsyncroot) + { + for (int i = 0; i < CurrentProjectFile.YmapFiles.Count; i++) + { + var ymap = CurrentProjectFile.YmapFiles[i]; + if (ymap.Loaded) + { + ymaps[ymap._CMapData.name] = ymap; + } + } + } + } + + } + + public void GetVisibleWaterQuads(Camera camera, List quads) + { + if (hidegtavmap) + { + quads.Clear(); + } + + } + + public void GetVisibleYnds(Camera camera, List ynds) + { + if (hidegtavmap) + { + ynds.Clear(); + } + + if (CurrentProjectFile == null) return; + + lock (yndsyncroot) + { + visibleynds.Clear(); + for (int i = 0; i < ynds.Count; i++) + { + var ynd = ynds[i]; + visibleynds[ynd.AreaID] = ynd; + } + + for (int i = 0; i < CurrentProjectFile.YndFiles.Count; i++) + { + var ynd = CurrentProjectFile.YndFiles[i]; + if (ynd.Loaded) + { + visibleynds[ynd.AreaID] = ynd; + } + } + + ynds.Clear(); + foreach (var ynd in visibleynds.Values) + { + ynds.Add(ynd); + } + } + + } + + public void GetVisibleYnvs(Camera camera, List ynvs) + { + if (hidegtavmap) + { + ynvs.Clear(); + } + + if (CurrentProjectFile == null) return; + + lock (ynvsyncroot) + { + visibleynvs.Clear(); + for (int i = 0; i < ynvs.Count; i++) + { + var ynv = ynvs[i]; + visibleynvs[ynv.AreaID] = ynv; + } + + for (int i = 0; i < CurrentProjectFile.YnvFiles.Count; i++) + { + var ynv = CurrentProjectFile.YnvFiles[i]; + if (ynv.Loaded) + { + visibleynvs[ynv.AreaID] = ynv; + } + } + + ynvs.Clear(); + foreach (var ynv in visibleynvs.Values) + { + ynvs.Add(ynv); + } + } + + } + + public void GetVisibleTrainTracks(Camera camera, List tracks) + { + if (hidegtavmap) + { + tracks.Clear(); + } + + + if (CurrentProjectFile == null) return; + + lock (trainsyncroot) + { + visibletrains.Clear(); + for (int i = 0; i < tracks.Count; i++) + { + var track = tracks[i]; + visibletrains[track.Name] = track; + } + + for (int i = 0; i < CurrentProjectFile.TrainsFiles.Count; i++) + { + var track = CurrentProjectFile.TrainsFiles[i]; + if (track.Loaded) + { + visibletrains[track.Name] = track; + } + } + + tracks.Clear(); + foreach (var track in visibletrains.Values) + { + tracks.Add(track); + } + } + + } + + public void GetVisibleScenarios(Camera camera, List ymts) + { + if (hidegtavmap) + { + ymts.Clear(); + } + + + if (CurrentProjectFile == null) return; + + lock (scenariosyncroot) + { + visiblescenarios.Clear(); + for (int i = 0; i < ymts.Count; i++) + { + var ymt = ymts[i]; + visiblescenarios[ymt.Name] = ymt; + } + + for (int i = 0; i < CurrentProjectFile.ScenarioFiles.Count; i++) + { + var scenario = CurrentProjectFile.ScenarioFiles[i]; + if (scenario.Loaded) + { + visiblescenarios[scenario.Name] = scenario; + } + } + + ymts.Clear(); + foreach (var ymt in visiblescenarios.Values) + { + ymts.Add(ymt); + } + } + + } + + + + public void OnWorldSelectionChanged(MapSelection sel) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { OnWorldSelectionChanged(sel); })); + } + else + { + var ent = sel.EntityDef; + var cargen = sel.CarGenerator; + var pathnode = sel.PathNode; + var pathlink = sel.PathLink; + var navpoly = sel.NavPoly; + var trainnode = sel.TrainTrackNode; + var scenariond = sel.ScenarioNode; + YmapFile ymap = ent?.Ymap; + YndFile ynd = pathnode?.Ynd; + YnvFile ynv = navpoly?.Ynv; + TrainTrack traintrack = trainnode?.Track; + YmtFile scenario = scenariond?.Ymt; + + if (cargen != null) + { + ymap = cargen.Ymap; + } + + if (YmapExistsInProject(ymap)) + { + if (ent != CurrentEntity) + { + TrySelectEntityTreeNode(ent); + } + if (cargen != CurrentCarGen) + { + TrySelectCarGenTreeNode(cargen); + } + } + else if (YndExistsInProject(ynd)) + { + if (pathnode != CurrentPathNode) + { + TrySelectPathNodeTreeNode(pathnode); + } + } + else if (YnvExistsInProject(ynv)) + { + if (navpoly != CurrentNavPoly) + { + TrySelectNavPolyTreeNode(navpoly); + } + } + else if (TrainTrackExistsInProject(traintrack)) + { + if (trainnode != CurrentTrainNode) + { + TrySelectTrainNodeTreeNode(trainnode); + } + } + else if (ScenarioExistsInProject(scenario)) + { + if ((scenariond != null) && (scenariond != CurrentScenarioNode)) + { + TrySelectScenarioNodeTreeNode(scenariond); + } + } + else + { + ProjectTreeView.SelectedNode = null; + if (ymap != null) + { + MainTabControl.SelectedTab = YmapTabPage; + } + else if (ynd != null) + { + MainTabControl.SelectedTab = YndTabPage; + } + else if (ynv != null) + { + MainTabControl.SelectedTab = YnvTabPage; + } + else if (traintrack != null) + { + MainTabControl.SelectedTab = TrainsTabPage; + } + else if (scenario != null) + { + MainTabControl.SelectedTab = ScenarioTabPage; + } + if (ent != null) + { + YmapTabControl.SelectedTab = YmapEntityTabPage; + } + else if (cargen != null) + { + YmapTabControl.SelectedTab = YmapCarGenTabPage; + } + if (pathnode != null) + { + YndTabControl.SelectedTab = YndNodeTabPage; + } + if (trainnode != null) + { + TrainsTabControl.SelectedTab = TrainNodeTabPage; + } + if (scenariond != null) + { + SelectScenarioNodeTabPages(scenariond); + } + } + + CurrentYmapFile = ymap; + CurrentEntity = ent; + CurrentCarGen = cargen; + CurrentYndFile = ynd; + CurrentPathNode = pathnode; + CurrentPathLink = pathlink; + CurrentYnvFile = ynv; + CurrentNavPoly = navpoly; + CurrentTrainTrack = traintrack; + CurrentTrainNode = trainnode; + CurrentScenario = scenario; + CurrentScenarioNode = scenariond; + RefreshUI(); + } + } + catch { } + } + + public void OnWorldEntityModified(YmapEntityDef ent) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { OnWorldEntityModified(ent); })); + } + else + { + if ((ent.Ymap == null) || (ent.MloParent != null)) + { + return;//TODO: properly handle interior entities! + } + + if (CurrentProjectFile == null) + { + NewProject(); + } + + if (!YmapExistsInProject(ent.Ymap)) + { + ent.Ymap.HasChanged = true; + AddYmapToProject(ent.Ymap); + TrySelectEntityTreeNode(ent); + } + + if (ent != CurrentEntity) + { + CurrentEntity = ent; + TrySelectEntityTreeNode(ent); + } + + if (ent == CurrentEntity) + { + LoadEntityTabPage(); + + if (ent.Ymap != null) + { + SetYmapHasChanged(true); + } + } + } + } + catch { } + } + + public void OnWorldCarGenModified(YmapCarGen cargen) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { OnWorldCarGenModified(cargen); })); + } + else + { + if (cargen?.Ymap == null) return; + + if (CurrentProjectFile == null) + { + NewProject(); + } + + if (!YmapExistsInProject(cargen.Ymap)) + { + cargen.Ymap.HasChanged = true; + AddYmapToProject(cargen.Ymap); + TrySelectCarGenTreeNode(cargen); + } + + if (cargen != CurrentCarGen) + { + CurrentCarGen = cargen; + TrySelectCarGenTreeNode(cargen); + } + + if (cargen == CurrentCarGen) + { + LoadCarGenTabPage(); + + UpdateCarGenTreeNode(cargen); + + if (cargen.Ymap != null) + { + SetYmapHasChanged(true); + } + } + + } + } + catch { } + } + + public void OnWorldPathNodeModified(YndNode node, YndLink link) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { OnWorldPathNodeModified(node, link); })); + } + else + { + if (node?.Ynd == null) return; + + if (CurrentProjectFile == null) + { + NewProject(); + } + + if (!YndExistsInProject(node.Ynd)) + { + node.Ynd.HasChanged = true; + AddYndToProject(node.Ynd); + TrySelectPathNodeTreeNode(node); + } + + if (node != CurrentPathNode) + { + CurrentPathNode = node; + TrySelectPathNodeTreeNode(node); + } + + //if (link != CurrentPathLink) + //{ + // CurrentPathLink = link; + // LoadPathNodeLinkPage(); + //} + + if (node == CurrentPathNode) + { + //LoadYndTabPage(); + LoadPathNodeTabPage(); + + //UpdatePathNodeTreeNode(node); + + if (node.Ynd != null) + { + SetYndHasChanged(true); + } + } + + } + } + catch { } + } + + public void OnWorldNavPolyModified(YnvPoly poly) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { OnWorldNavPolyModified(poly); })); + } + else + { + if (poly?.Ynv == null) return; + + if (CurrentProjectFile == null) + { + NewProject(); + } + + if (!YnvExistsInProject(poly.Ynv)) + { + poly.Ynv.HasChanged = true; + AddYnvToProject(poly.Ynv); + TrySelectNavPolyTreeNode(poly); + } + + if (poly != CurrentNavPoly) + { + CurrentNavPoly = poly; + TrySelectNavPolyTreeNode(poly); + } + + if (poly == CurrentNavPoly) + { + LoadYnvTabPage(); + + //UpdateNavPolyTreeNode(poly); + + if (poly.Ynv != null) + { + SetYnvHasChanged(true); + } + } + + } + } + catch { } + } + + public void OnWorldTrainNodeModified(TrainTrackNode node) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { OnWorldTrainNodeModified(node); })); + } + else + { + if (node?.Track == null) return; + + if (CurrentProjectFile == null) + { + NewProject(); + } + + if (!TrainTrackExistsInProject(node.Track)) + { + node.Track.HasChanged = true; + AddTrainTrackToProject(node.Track); + TrySelectTrainNodeTreeNode(node); + } + + if (node != CurrentTrainNode) + { + CurrentTrainNode = node; + TrySelectTrainNodeTreeNode(node); + } + + if (node == CurrentTrainNode) + { + LoadTrainNodeTabPage(); + + if (node.Track != null) + { + SetTrainTrackHasChanged(true); + } + } + } + } + catch { } + } + + public void OnWorldScenarioNodeModified(ScenarioNode node) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { OnWorldScenarioNodeModified(node); })); + } + else + { + if (node?.Ymt == null) return; + + if (CurrentProjectFile == null) + { + NewProject(); + } + + if (!ScenarioExistsInProject(node.Ymt)) + { + node.Ymt.HasChanged = true; + AddScenarioToProject(node.Ymt); + TrySelectScenarioNodeTreeNode(node); + } + + if (node != CurrentScenarioNode) + { + CurrentScenarioNode = node; + TrySelectScenarioNodeTreeNode(node); + } + + if (node == CurrentScenarioNode) + { + LoadScenarioTabPage(); + LoadScenarioNodeTabPages(); + + if (node?.Ymt != null) + { + SetScenarioHasChanged(true); + } + } + } + } + catch { } + } + + + + + + + + + + + private bool IsBitSet(uint value, int bit) + { + return (((value >> bit) & 1) > 0); + } + private uint SetBit(uint value, int bit) + { + return (value | (1u << bit)); + } + private uint ClearBit(uint value, int bit) + { + return (value & (~(1u << bit))); + } + private uint UpdateBit(uint value, int bit, bool flag) + { + if (flag) return SetBit(value, bit); + else return ClearBit(value, bit); + } + + + private string ShowOpenDialog(string filter, string filename) + { + OpenFileDialog.FileName = filename; + OpenFileDialog.Filter = filter; + OpenFileDialog.Multiselect = false; + if (OpenFileDialog.ShowDialog(this) != DialogResult.OK) + { + return string.Empty; + } + return OpenFileDialog.FileName; + } + private string[] ShowOpenDialogMulti(string filter, string filename) + { + OpenFileDialog.FileName = filename; + OpenFileDialog.Filter = filter; + OpenFileDialog.Multiselect = true; + if (OpenFileDialog.ShowDialog(this) != DialogResult.OK) + { + return null; + } + return OpenFileDialog.FileNames; + } + + private string ShowSaveDialog(string filter, string filename) + { + SaveFileDialog.FileName = filename; + SaveFileDialog.Filter = filter; + if (SaveFileDialog.ShowDialog(this) != DialogResult.OK) + { + return string.Empty; + } + return SaveFileDialog.FileName; + } + + + + + + + + private RpfFileEntry FindParentYmapEntry(uint hash) + { + if (CurrentProjectFile != null) + { + foreach (var ymap in CurrentProjectFile.YmapFiles) + { + if ((ymap._CMapData.name.Hash == hash) || (JenkHash.GenHash(Path.GetFileNameWithoutExtension(ymap.Name)) == hash)) + { + return ymap.RpfFileEntry; + } + } + } + + if ((GameFileCache != null) && (GameFileCache.IsInited)) + { + return GameFileCache.GetYmapEntry(hash); + } + + return null; + } + + private bool YmapExistsInProject(YmapFile ymap) + { + if (ymap == null) return false; + if (CurrentProjectFile == null) return false; + return CurrentProjectFile.ContainsYmap(ymap); + } + private bool YndExistsInProject(YndFile ynd) + { + if (ynd == null) return false; + if (CurrentProjectFile == null) return false; + return CurrentProjectFile.ContainsYnd(ynd); + } + private bool YnvExistsInProject(YnvFile ynv) + { + if (ynv == null) return false; + if (CurrentProjectFile == null) return false; + return CurrentProjectFile.ContainsYnv(ynv); + } + private bool TrainTrackExistsInProject(TrainTrack track) + { + if (track == null) return false; + if (CurrentProjectFile == null) return false; + return CurrentProjectFile.ContainsTrainTrack(track); + } + private bool ScenarioExistsInProject(YmtFile ymt) + { + if (ymt == null) return false; + if (CurrentProjectFile == null) return false; + return CurrentProjectFile.ContainsScenario(ymt); + } + + private TreeNode GetChildTreeNode(TreeNode node, string name) + { + if (node == null) return null; + var nodes = node.Nodes.Find(name, false); + if ((nodes == null) || (nodes.Length != 1)) return null; + return nodes[0]; + } + private TreeNode FindYmapTreeNode(YmapFile ymap) + { + if (ProjectTreeView.Nodes.Count <= 0) return null; + var projnode = ProjectTreeView.Nodes[0]; + var ymapsnode = GetChildTreeNode(projnode, "Ymap"); + if (ymapsnode == null) return null; + for (int i = 0; i < ymapsnode.Nodes.Count; i++) + { + var ymapnode = ymapsnode.Nodes[i]; + if (ymapnode.Tag == ymap) return ymapnode; + } + return null; + } + private TreeNode FindEntityTreeNode(YmapEntityDef ent) + { + if (ent == null) return null; + TreeNode ymapnode = FindYmapTreeNode(ent.Ymap); + if (ymapnode == null) return null; + var entsnode = GetChildTreeNode(ymapnode, "Entities"); + if (entsnode == null) return null; + for (int i = 0; i < entsnode.Nodes.Count; i++) + { + TreeNode entnode = entsnode.Nodes[i]; + if (entnode.Tag == ent) return entnode; + } + return null; + } + private TreeNode FindCarGenTreeNode(YmapCarGen cargen) + { + if (cargen == null) return null; + TreeNode ymapnode = FindYmapTreeNode(cargen.Ymap); + if (ymapnode == null) return null; + var cargensnode = GetChildTreeNode(ymapnode, "CarGens"); + if (cargensnode == null) return null; + for (int i = 0; i < cargensnode.Nodes.Count; i++) + { + TreeNode cargennode = cargensnode.Nodes[i]; + if (cargennode.Tag == cargen) return cargennode; + } + return null; + } + private TreeNode FindYndTreeNode(YndFile ynd) + { + if (ProjectTreeView.Nodes.Count <= 0) return null; + var projnode = ProjectTreeView.Nodes[0]; + var yndsnode = GetChildTreeNode(projnode, "Ynd"); + if (yndsnode == null) return null; + for (int i = 0; i < yndsnode.Nodes.Count; i++) + { + var yndnode = yndsnode.Nodes[i]; + if (yndnode.Tag == ynd) return yndnode; + } + return null; + } + private TreeNode FindPathNodeTreeNode(YndNode n) + { + if (n == null) return null; + TreeNode yndnode = FindYndTreeNode(n.Ynd); + var nodesnode = GetChildTreeNode(yndnode, "Nodes"); + if (nodesnode == null) return null; + for (int i = 0; i < nodesnode.Nodes.Count; i++) + { + TreeNode nnode = nodesnode.Nodes[i]; + if (nnode.Tag == n) return nnode; + } + return null; + } + private TreeNode FindYnvTreeNode(YnvFile ynv) + { + if (ProjectTreeView.Nodes.Count <= 0) return null; + var projnode = ProjectTreeView.Nodes[0]; + var ynvsnode = GetChildTreeNode(projnode, "Ynv"); + if (ynvsnode == null) return null; + for (int i = 0; i < ynvsnode.Nodes.Count; i++) + { + var yndnode = ynvsnode.Nodes[i]; + if (yndnode.Tag == ynv) return yndnode; + } + return null; + } + private TreeNode FindNavPolyTreeNode(YnvPoly p) + { + if (p == null) return null; + TreeNode ynvnode = FindYnvTreeNode(p.Ynv); + var polysnode = GetChildTreeNode(ynvnode, "Polygons"); + if (polysnode == null) return null; + for (int i = 0; i < polysnode.Nodes.Count; i++) + { + TreeNode pnode = polysnode.Nodes[i]; + if (pnode.Tag == p) return pnode; + } + return null; + } + private TreeNode FindTrainTrackTreeNode(TrainTrack track) + { + if (ProjectTreeView.Nodes.Count <= 0) return null; + var projnode = ProjectTreeView.Nodes[0]; + var trainsnode = GetChildTreeNode(projnode, "Trains"); + if (trainsnode == null) return null; + for (int i = 0; i < trainsnode.Nodes.Count; i++) + { + var trainnode = trainsnode.Nodes[i]; + if (trainnode.Tag == track) return trainnode; + } + return null; + } + private TreeNode FindTrainNodeTreeNode(TrainTrackNode n) + { + if (n == null) return null; + TreeNode tracknode = FindTrainTrackTreeNode(n.Track); + var nodesnode = GetChildTreeNode(tracknode, "Nodes"); + if (nodesnode == null) return null; + for (int i = 0; i < nodesnode.Nodes.Count; i++) + { + TreeNode nnode = nodesnode.Nodes[i]; + if (nnode.Tag == n) return nnode; + } + return null; + } + private TreeNode FindScenarioTreeNode(YmtFile ymt) + { + if (ProjectTreeView.Nodes.Count <= 0) return null; + var projnode = ProjectTreeView.Nodes[0]; + var scenariosnode = GetChildTreeNode(projnode, "Scenarios"); + if (scenariosnode == null) return null; + for (int i = 0; i < scenariosnode.Nodes.Count; i++) + { + var ymtnode = scenariosnode.Nodes[i]; + if (ymtnode.Tag == ymt) return ymtnode; + } + return null; + } + private TreeNode FindScenarioNodeTreeNode(ScenarioNode p) + { + if (p == null) return null; + TreeNode ymtnode = FindScenarioTreeNode(p.Ymt); + var pointsnode = GetChildTreeNode(ymtnode, "Points"); + if (pointsnode == null) return null; + for (int i = 0; i < pointsnode.Nodes.Count; i++) + { + TreeNode pnode = pointsnode.Nodes[i]; + if (pnode.Tag == p) return pnode; + } + return null; + } + + + private void TrySelectEntityTreeNode(YmapEntityDef ent) + { + TreeNode entnode = FindEntityTreeNode(ent); + if (entnode != null) + { + ProjectTreeView.SelectedNode = entnode; + } + } + + private void TrySelectCarGenTreeNode(YmapCarGen cargen) + { + TreeNode cargennode = FindCarGenTreeNode(cargen); + if (cargennode != null) + { + ProjectTreeView.SelectedNode = cargennode; + } + } + private void UpdateCarGenTreeNode(YmapCarGen cargen) + { + var tn = FindCarGenTreeNode(cargen); + if (tn != null) + { + tn.Text = cargen.ToString(); + } + } + + private void TrySelectPathNodeTreeNode(YndNode node) + { + TreeNode tnode = FindPathNodeTreeNode(node); + if (tnode == null) + { + tnode = FindYndTreeNode(node?.Ynd); + } + if (tnode != null) + { + ProjectTreeView.SelectedNode = tnode; + } + } + private void UpdatePathNodeTreeNode(YndNode node) + { + var tn = FindPathNodeTreeNode(node); + if (tn != null) + { + tn.Text = node._RawData.ToString(); + } + } + + private void TrySelectNavPolyTreeNode(YnvPoly poly) + { + TreeNode tnode = FindNavPolyTreeNode(poly); + if (tnode == null) + { + tnode = FindYnvTreeNode(poly?.Ynv); + } + if (tnode != null) + { + ProjectTreeView.SelectedNode = tnode; + } + } + private void UpdateNavPolyTreeNode(YnvPoly poly) + { + var tn = FindNavPolyTreeNode(poly); + if (tn != null) + { + tn.Text = poly._RawData.ToString(); + } + } + + private void TrySelectTrainNodeTreeNode(TrainTrackNode node) + { + TreeNode tnode = FindTrainNodeTreeNode(node); + if (tnode == null) + { + tnode = FindTrainTrackTreeNode(node?.Track); + } + if (tnode != null) + { + ProjectTreeView.SelectedNode = tnode; + } + } + private void UpdateTrainNodeTreeNode(TrainTrackNode node) + { + var tn = FindTrainNodeTreeNode(node); + if (tn != null) + { + tn.Text = node.ToString(); + } + } + + private void TrySelectScenarioTreeNode(YmtFile scenario) + { + TreeNode tnode = FindScenarioTreeNode(scenario); + if (tnode != null) + { + ProjectTreeView.SelectedNode = tnode; + } + } + private void TrySelectScenarioNodeTreeNode(ScenarioNode node) + { + TreeNode tnode = FindScenarioNodeTreeNode(node); + if (tnode == null) + { + tnode = FindScenarioTreeNode(node?.Ymt); + } + if (tnode != null) + { + ProjectTreeView.SelectedNode = tnode; + } + } + private void UpdateScenarioNodeTreeNode(ScenarioNode node) + { + var tn = FindScenarioNodeTreeNode(node); + if (tn != null) + { + tn.Text = node.MedTypeName + ": " + node.StringText; + } + } + + + + + private void ProjectForm_FormClosing(object sender, FormClosingEventArgs e) + { + CloseProject(); + } + + private void ProjectForm_FormClosed(object sender, FormClosedEventArgs e) + { + if (WorldForm != null) + { + WorldForm.OnProjectFormClosed(); + } + } + + + private void FileNewProjectMenu_Click(object sender, EventArgs e) + { + NewProject(); + } + + private void FileNewYmapMenu_Click(object sender, EventArgs e) + { + NewYmap(); + } + + private void FileNewYndMenu_Click(object sender, EventArgs e) + { + NewYnd(); + } + + private void FileNewYnvMenu_Click(object sender, EventArgs e) + { + NewYnv(); + } + + private void FileNewTrainsMenu_Click(object sender, EventArgs e) + { + NewTrainTrack(); + } + + private void FileNewScenarioMenu_Click(object sender, EventArgs e) + { + NewScenario(); + } + + private void FileOpenProjectMenu_Click(object sender, EventArgs e) + { + if (CurrentProjectFile != null) + { + ////unload current project first? + //if (MessageBox.Show("Close the current project and open an existing one?", "Confirm close project", MessageBoxButtons.YesNo) != DialogResult.Yes) + //{ + // return; + //} + CloseProject(); + } + + OpenProject(); + } + + private void FileOpenYmapMenu_Click(object sender, EventArgs e) + { + OpenYmap(); + } + + private void FileOpenYndMenu_Click(object sender, EventArgs e) + { + OpenYnd(); + } + + private void FileOpenYnvMenu_Click(object sender, EventArgs e) + { + OpenYnv(); + } + + private void FileOpenTrainsMenu_Click(object sender, EventArgs e) + { + OpenTrainTrack(); + } + + private void FileOpenScenarioMenu_Click(object sender, EventArgs e) + { + OpenScenario(); + } + + private void FileCloseProjectMenu_Click(object sender, EventArgs e) + { + CloseProject(); + } + + private void FileSaveProjectMenu_Click(object sender, EventArgs e) + { + SaveProject(false); + } + + private void FileSaveProjectAsMenu_Click(object sender, EventArgs e) + { + SaveProject(true); + } + + private void FileSaveItemMenu_Click(object sender, EventArgs e) + { + SaveCurrentItem(false); + } + + private void FileSaveItemAsMenu_Click(object sender, EventArgs e) + { + SaveCurrentItem(true); + } + + private void YmapNewEntityMenu_Click(object sender, EventArgs e) + { + NewEntity(); + } + + private void YmapNewCarGenMenu_Click(object sender, EventArgs e) + { + NewCarGen(); + } + + private void YmapAddToProjectMenu_Click(object sender, EventArgs e) + { + AddYmapToProject(CurrentYmapFile); + } + + private void YmapRemoveFromProjectMenu_Click(object sender, EventArgs e) + { + RemoveYmapFromProject(); + } + + private void YndNewNodeMenu_Click(object sender, EventArgs e) + { + NewPathNode(); + } + + private void YndAddToProjectMenu_Click(object sender, EventArgs e) + { + AddYndToProject(CurrentYndFile); + } + + private void YndRemoveFromProjectMenu_Click(object sender, EventArgs e) + { + RemoveYndFromProject(); + } + + private void YnvNewPolygonMenu_Click(object sender, EventArgs e) + { + NewNavPoly(); + } + + private void YnvAddToProjectMenu_Click(object sender, EventArgs e) + { + //AddYnvToProject(CurrentYnvFile); + } + + private void YnvRemoveFromProjectMenu_Click(object sender, EventArgs e) + { + RemoveYnvFromProject(); + } + + private void TrainsNewNodeMenu_Click(object sender, EventArgs e) + { + NewTrainNode(); + } + + private void TrainsAddToProjectMenu_Click(object sender, EventArgs e) + { + AddTrainTrackToProject(CurrentTrainTrack); + } + + private void TrainsRemoveFromProjectMenu_Click(object sender, EventArgs e) + { + RemoveTrainTrackFromProject(); + } + + private void ScenarioNewPointMenu_Click(object sender, EventArgs e) + { + CurrentScenarioNode = null; + NewScenarioNode(); + } + + private void ScenarioNewPointFromSelectedMenu_Click(object sender, EventArgs e) + { + NewScenarioNode(); + } + + private void ScenarioNewEntityOverrideMenu_Click(object sender, EventArgs e) + { + AddScenarioEntity(); + } + + private void ScenarioNewChainMenu_Click(object sender, EventArgs e) + { + AddScenarioChain(); + } + + private void ScenarioNewClusterMenu_Click(object sender, EventArgs e) + { + AddScenarioCluster(); + } + + private void ScenarioAddToProjectMenu_Click(object sender, EventArgs e) + { + AddScenarioToProject(CurrentScenario); + } + + private void ScenarioRemoveFromProjectMenu_Click(object sender, EventArgs e) + { + RemoveScenarioFromProject(); + } + + + + + + + + private void ProjectNameTextBox_TextChanged(object sender, EventArgs e) + { + if (CurrentProjectFile != null) + { + if (CurrentProjectFile.Name != ProjectNameTextBox.Text) + { + CurrentProjectFile.Name = ProjectNameTextBox.Text; + SetProjectHasChanged(true); + } + } + } + + private void ProjectTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + YmapFile ymap = null; + YmapEntityDef yent = null; + YmapCarGen ycgen = null; + YndFile ynd = null; + YndNode ynode = null; + YnvFile ynv = null; + YnvPoly ypoly = null; + TrainTrack tt = null; + TrainTrackNode ttnode = null; + YmtFile scenario = null; + ScenarioNode scenarionode = null; + object tag = null; + var node = ProjectTreeView.SelectedNode; + if (node != null) + { + tag = node.Tag; + ymap = tag as YmapFile; + yent = tag as YmapEntityDef; + ycgen = tag as YmapCarGen; + ynd = tag as YndFile; + ynode = tag as YndNode; + ynv = tag as YnvFile; + ypoly = tag as YnvPoly; + tt = tag as TrainTrack; + ttnode = tag as TrainTrackNode; + scenario = tag as YmtFile; if ((scenario != null) && (scenario.ScenarioRegion == null)) scenario = null;//incase other types of ymt files make it into the project... + scenarionode = tag as ScenarioNode; + } + + CurrentYmapFile = ymap; + CurrentEntity = yent; + CurrentCarGen = ycgen; + CurrentYndFile = ynd; + CurrentPathNode = ynode; + CurrentYnvFile = ynv; + CurrentNavPoly = ypoly; + CurrentTrainTrack = tt; + CurrentTrainNode = ttnode; + CurrentScenario = scenario; + CurrentScenarioNode = scenarionode; + + if (tag == CurrentProjectFile) + { + MainTabControl.SelectedTab = ProjectTabPage; + } + if (yent != null) + { + CurrentYmapFile = yent.Ymap; + MainTabControl.SelectedTab = YmapTabPage; + YmapTabControl.SelectedTab = YmapEntityTabPage; + } + else if (ycgen != null) + { + CurrentYmapFile = ycgen.Ymap; + MainTabControl.SelectedTab = YmapTabPage; + YmapTabControl.SelectedTab = YmapCarGenTabPage; + } + else if (ymap != null) + { + CurrentYmapFile = ymap; + MainTabControl.SelectedTab = YmapTabPage; + YmapTabControl.SelectedTab = YmapYmapTabPage; + } + if (ynode != null) + { + CurrentYndFile = ynode.Ynd; + MainTabControl.SelectedTab = YndTabPage; + YndTabControl.SelectedTab = YndNodeTabPage; + } + else if (ynd != null) + { + MainTabControl.SelectedTab = YndTabPage; + YndTabControl.SelectedTab = YndYndTabPage; + } + if (ypoly != null) + { + CurrentYnvFile = ypoly.Ynv; + MainTabControl.SelectedTab = YnvTabPage; + YnvTabControl.SelectedTab = YnvPolyTabPage; + } + else if (ynv != null) + { + MainTabControl.SelectedTab = YnvTabPage; + YnvTabControl.SelectedTab = YnvYnvTabPage; + } + if (ttnode != null) + { + CurrentTrainTrack = ttnode.Track; + MainTabControl.SelectedTab = TrainsTabPage; + TrainsTabControl.SelectedTab = TrainNodeTabPage; + } + else if (tt != null) + { + MainTabControl.SelectedTab = TrainsTabPage; + TrainsTabControl.SelectedTab = TrainTrackTabPage; + } + if (scenarionode != null) + { + CurrentScenario = scenarionode.Ymt; + MainTabControl.SelectedTab = ScenarioTabPage; + SelectScenarioNodeTabPages(scenarionode); + } + else if (scenario != null) + { + MainTabControl.SelectedTab = ScenarioTabPage; + ScenarioTabControl.SelectedTab = ScenarioYmtTabPage; + } + + RefreshUI(); + } + + private void ProjectShowEntitiesCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderentities = ProjectShowEntitiesCheckBox.Checked; + } + + private void ProjectHideMapCheckBox_CheckedChanged(object sender, EventArgs e) + { + hidegtavmap = ProjectHideMapCheckBox.Checked; + } + + + + + + + private void YmapNameTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + uint hash = 0; + string name = YmapNameTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + YmapNameHashLabel.Text = "Hash: " + hash.ToString(); + + if (CurrentYmapFile != null) + { + lock (ymapsyncroot) + { + string ymname = name + ".ymap"; + if (CurrentYmapFile.Name != ymname) + { + CurrentYmapFile.Name = ymname; + CurrentYmapFile._CMapData.name = new MetaHash(hash); + SetYmapHasChanged(true); + } + } + } + } + + private void YmapParentTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + uint hash = 0; + string name = YmapParentTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + YmapParentHashLabel.Text = "Hash: " + hash.ToString(); + + if (hash != 0) + { + var entry = FindParentYmapEntry(hash); + if (entry == null) + { + YmapParentHashLabel.Text += " (not found!)"; + } + } + + if (CurrentYmapFile != null) + { + lock (ymapsyncroot) + { + if (CurrentYmapFile._CMapData.parent.Hash != hash) + { + CurrentYmapFile._CMapData.parent = new MetaHash(hash); + SetYmapHasChanged(true); + + //TODO: confirm entity parent linkage? + } + } + } + + } + + private void YmapFlagsTextBox_TextChanged(object sender, EventArgs e) + { + SetYmapFlagsFromTextBoxes(); + } + + private void YmapContentFlagsTextBox_TextChanged(object sender, EventArgs e) + { + SetYmapFlagsFromTextBoxes(); + } + + private void YmapCFlagsHDCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsLODCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsSLOD2CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsInteriorCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsSLODCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsOcclusionCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsPhysicsCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsLODLightsCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsDistLightsCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsCriticalCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCFlagsGrassCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapFlagsScriptedCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapFlagsLODCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetYmapFlagsFromCheckBoxes(); + } + + private void YmapCalculateFlagsButton_Click(object sender, EventArgs e) + { + CalcYmapFlags(); + } + + private void YmapEntitiesExtentsMinTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentYmapFile == null) return; + Vector3 v = FloatUtil.ParseVector3String(YmapEntitiesExtentsMinTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentYmapFile._CMapData.entitiesExtentsMin != v) + { + CurrentYmapFile._CMapData.entitiesExtentsMin = v; + SetYmapHasChanged(true); + } + } + } + + private void YmapEntitiesExtentsMaxTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentYmapFile == null) return; + Vector3 v = FloatUtil.ParseVector3String(YmapEntitiesExtentsMaxTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentYmapFile._CMapData.entitiesExtentsMax != v) + { + CurrentYmapFile._CMapData.entitiesExtentsMax = v; + SetYmapHasChanged(true); + } + } + } + + private void YmapStreamingExtentsMinTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentYmapFile == null) return; + Vector3 v = FloatUtil.ParseVector3String(YmapStreamingExtentsMinTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentYmapFile._CMapData.streamingExtentsMin != v) + { + CurrentYmapFile._CMapData.streamingExtentsMin = v; + SetYmapHasChanged(true); + } + } + } + + private void YmapStreamingExtentsMaxTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentYmapFile == null) return; + Vector3 v = FloatUtil.ParseVector3String(YmapStreamingExtentsMaxTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentYmapFile._CMapData.streamingExtentsMax != v) + { + CurrentYmapFile._CMapData.streamingExtentsMax = v; + SetYmapHasChanged(true); + } + } + } + + private void YmapCalculateExtentsButton_Click(object sender, EventArgs e) + { + CalcYmapExtents(); + } + + private void YmapPhysicsDictionariesTextBox_TextChanged(object sender, EventArgs e) + { + SetYmapPhysicsDictionariesFromTextbox(); + } + + + private void EntityArchetypeTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + uint hash = 0; + string name = EntityArchetypeTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + EntityArchetypeHashLabel.Text = "Hash: " + hash.ToString(); + + var arch = GameFileCache.GetArchetype(hash); + if (arch == null) + { + EntityArchetypeHashLabel.Text += " (not found)"; + } + + TreeNode tn = FindEntityTreeNode(CurrentEntity); + if (tn != null) + { + tn.Text = name; + } + + if (CurrentEntity != null) + { + lock (ymapsyncroot) + { + CurrentEntity._CEntityDef.archetypeName = new MetaHash(hash); + if (CurrentEntity.Archetype != arch) + { + CurrentEntity.SetArchetype(arch); + SetYmapHasChanged(true); + } + } + } + } + + private void EntityFlagsTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + uint flags = 0; + uint.TryParse(EntityFlagsTextBox.Text, out flags); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.flags != flags) + { + CurrentEntity._CEntityDef.flags = flags; + SetYmapHasChanged(true); + } + } + } + + private void EntityGuidTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + uint guid = 0; + uint.TryParse(EntityGuidTextBox.Text, out guid); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.guid != guid) + { + CurrentEntity._CEntityDef.guid = guid; + SetYmapHasChanged(true); + } + } + } + + private void EntityPositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + Vector3 v = FloatUtil.ParseVector3String(EntityPositionTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentEntity.MloParent != null) + { + //TODO: positioning for interior entities! + } + else + { + if (CurrentEntity.Position != v) + { + CurrentEntity.SetPosition(v); + SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.BeginInvoke(new Action(() => + { + WorldForm.SetWidgetPosition(CurrentEntity.WidgetPosition, true); + })); + } + } + } + } + } + + private void EntityRotationTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + Vector4 v = FloatUtil.ParseVector4String(EntityRotationTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.rotation != v) + { + Quaternion q = new Quaternion(v); + CurrentEntity.SetOrientationInv(q); + SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.BeginInvoke(new Action(() => + { + WorldForm.SetWidgetRotation(CurrentEntity.WidgetOrientation, true); + })); + } + } + } + } + + private void EntityScaleXYTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + float sxy = 0; + FloatUtil.TryParse(EntityScaleXYTextBox.Text, out sxy); + lock (ymapsyncroot) + { + if (CurrentEntity.Scale.X != sxy) + { + Vector3 newscale = new Vector3(sxy, sxy, CurrentEntity.Scale.Z); + CurrentEntity.SetScale(newscale); + SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.BeginInvoke(new Action(() => + { + WorldForm.SetWidgetScale(newscale, true); + })); + } + } + } + } + + private void EntityScaleZTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + float sz = 0; + FloatUtil.TryParse(EntityScaleZTextBox.Text, out sz); + lock (ymapsyncroot) + { + if (CurrentEntity.Scale.Z != sz) + { + Vector3 newscale = new Vector3(CurrentEntity.Scale.X, CurrentEntity.Scale.Y, sz); + CurrentEntity.SetScale(newscale); + SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.BeginInvoke(new Action(() => + { + WorldForm.SetWidgetScale(newscale, true); + })); + } + } + } + } + + private void EntityParentIndexTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + int pind = 0; + int.TryParse(EntityParentIndexTextBox.Text, out pind); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.parentIndex != pind) + { + CurrentEntity._CEntityDef.parentIndex = pind; //Needs more work for LOD linking! + SetYmapHasChanged(true); + } + } + } + + private void EntityLodDistTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + float lodDist = 0; + FloatUtil.TryParse(EntityLodDistTextBox.Text, out lodDist); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.lodDist != lodDist) + { + CurrentEntity._CEntityDef.lodDist = lodDist; + SetYmapHasChanged(true); + } + } + } + + private void EntityChildLodDistTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + float childLodDist = 0; + FloatUtil.TryParse(EntityChildLodDistTextBox.Text, out childLodDist); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.childLodDist != childLodDist) + { + CurrentEntity._CEntityDef.childLodDist = childLodDist; + SetYmapHasChanged(true); + } + } + } + + private void EntityLodLevelComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + Unk_1264241711 lodLevel = (Unk_1264241711)EntityLodLevelComboBox.SelectedItem; + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.lodLevel != lodLevel) + { + CurrentEntity._CEntityDef.lodLevel = lodLevel; + SetYmapHasChanged(true); + } + } + } + + private void EntityNumChildrenTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + uint numChildren = 0; + uint.TryParse(EntityNumChildrenTextBox.Text, out numChildren); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.numChildren != numChildren) + { + CurrentEntity._CEntityDef.numChildren = numChildren; + SetYmapHasChanged(true); + } + } + } + + private void EntityPriorityLevelComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + Unk_648413703 priorityLevel = (Unk_648413703)EntityPriorityLevelComboBox.SelectedItem; + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.priorityLevel != priorityLevel) + { + CurrentEntity._CEntityDef.priorityLevel = priorityLevel; + SetYmapHasChanged(true); + } + } + } + + private void EntityAOMultiplierTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + int aomult = 0; + int.TryParse(EntityAOMultiplierTextBox.Text, out aomult); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.ambientOcclusionMultiplier != aomult) + { + CurrentEntity._CEntityDef.ambientOcclusionMultiplier = aomult; + SetYmapHasChanged(true); + } + } + } + + private void EntityArtificialAOTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + int artao = 0; + int.TryParse(EntityArtificialAOTextBox.Text, out artao); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.artificialAmbientOcclusion != artao) + { + CurrentEntity._CEntityDef.artificialAmbientOcclusion = artao; + SetYmapHasChanged(true); + } + } + } + + private void EntityTintValueTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + uint tintValue = 0; + uint.TryParse(EntityTintValueTextBox.Text, out tintValue); + lock (ymapsyncroot) + { + if (CurrentEntity._CEntityDef.tintValue != tintValue) + { + CurrentEntity._CEntityDef.tintValue = tintValue; + SetYmapHasChanged(true); + } + } + } + + private void EntityGoToButton_Click(object sender, EventArgs e) + { + if (CurrentEntity == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentEntity.Position); + } + + private void EntityNormalizeRotationButton_Click(object sender, EventArgs e) + { + Vector4 v = FloatUtil.ParseVector4String(EntityRotationTextBox.Text); + Quaternion q = Quaternion.Normalize(new Quaternion(v)); + EntityRotationTextBox.Text = FloatUtil.GetVector4String(new Vector4(q.X, q.Y, q.Z, q.W)); + } + + private void EntityAddToProjectButton_Click(object sender, EventArgs e) + { + AddEntityToProject(); + } + + private void EntityDeleteButton_Click(object sender, EventArgs e) + { + DeleteEntity(); + } + + private void EntityPivotEditCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (WorldForm != null) + { + WorldForm.EditEntityPivot = EntityPivotEditCheckBox.Checked; + } + } + + private void EntityPivotPositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + Vector3 v = FloatUtil.ParseVector3String(EntityPivotPositionTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentEntity.PivotPosition != v) + { + CurrentEntity.SetPivotPosition(v); + //SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.BeginInvoke(new Action(() => + { + bool editpivot = WorldForm.EditEntityPivot; + WorldForm.EditEntityPivot = true; + WorldForm.SetWidgetPosition(CurrentEntity.WidgetPosition, true); + WorldForm.EditEntityPivot = editpivot; + })); + } + } + } + } + + private void EntityPivotRotationTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentEntity == null) return; + Vector4 v = FloatUtil.ParseVector4String(EntityPivotRotationTextBox.Text); + Quaternion q = new Quaternion(v); + lock (ymapsyncroot) + { + if (CurrentEntity.PivotOrientation != q) + { + CurrentEntity.SetPivotOrientation(q); + //SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.BeginInvoke(new Action(() => + { + bool editpivot = WorldForm.EditEntityPivot; + WorldForm.EditEntityPivot = true; + WorldForm.SetWidgetRotation(CurrentEntity.WidgetOrientation, true); + WorldForm.EditEntityPivot = editpivot; + })); + } + } + } + } + + private void EntityPivotRotationNormalizeButton_Click(object sender, EventArgs e) + { + Vector4 v = FloatUtil.ParseVector4String(EntityPivotRotationTextBox.Text); + Quaternion q = Quaternion.Normalize(new Quaternion(v)); + EntityPivotRotationTextBox.Text = FloatUtil.GetVector4String(new Vector4(q.X, q.Y, q.Z, q.W)); + } + + + private void CarModelTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + uint hash = 0; + string name = CarModelTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + CarModelHashLabel.Text = "Hash: " + hash.ToString(); + + //var model = GameFileCache.GetCarInfo(hash); //todo: something like this for car info? + //if (model == null) + //{ + // CarModelHashLabel.Text += " (not found)"; + //} + + if (CurrentCarGen != null) + { + lock (ymapsyncroot) + { + var modelhash = new MetaHash(hash); + if (CurrentCarGen._CCarGen.carModel != modelhash) + { + CurrentCarGen._CCarGen.carModel = modelhash; + SetYmapHasChanged(true); + } + } + } + + UpdateCarGenTreeNode(CurrentCarGen); + + } + + private void CarPopGroupTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + uint hash = 0; + string name = CarPopGroupTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + CarPopGroupHashLabel.Text = "Hash: " + hash.ToString(); + + //var grp = GameFileCache.GetCarPopGroup(hash); //todo: something like this for popgroup info? + //if (grp == null) + //{ + // CarPopGroupHashLabel.Text += " (not found)"; + //} + + if (CurrentCarGen != null) + { + lock (ymapsyncroot) + { + var pghash = new MetaHash(hash); + if (CurrentCarGen._CCarGen.popGroup != pghash) + { + CurrentCarGen._CCarGen.popGroup = pghash; + SetYmapHasChanged(true); + } + } + } + + UpdateCarGenTreeNode(CurrentCarGen); + } + + private void CarFlagsTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + uint flags = 0; + uint.TryParse(CarFlagsTextBox.Text, out flags); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.flags != flags) + { + CurrentCarGen._CCarGen.flags = flags; + SetYmapHasChanged(true); + } + } + } + + private void CarPositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + Vector3 v = FloatUtil.ParseVector3String(CarPositionTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentCarGen.Position != v) + { + CurrentCarGen.SetPosition(v); + SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(v); + } + } + } + + UpdateCarGenTreeNode(CurrentCarGen); + } + + private void CarOrientXTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + float ox = FloatUtil.Parse(CarOrientXTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.orientX != ox) + { + CurrentCarGen._CCarGen.orientX = ox; + CurrentCarGen.CalcOrientation(); + SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.SetWidgetRotation(CurrentCarGen.Orientation); + } + } + } + } + + private void CarOrientYTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + float oy = FloatUtil.Parse(CarOrientYTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.orientY != oy) + { + CurrentCarGen._CCarGen.orientY = oy; + CurrentCarGen.CalcOrientation(); + SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.SetWidgetRotation(CurrentCarGen.Orientation); + } + } + } + } + + private void CarPerpendicularLengthTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + float len = FloatUtil.Parse(CarPerpendicularLengthTextBox.Text); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.perpendicularLength != len) + { + CurrentCarGen.SetLength(len); + SetYmapHasChanged(true); + if (WorldForm != null) + { + WorldForm.SetWidgetScale(new Vector3(len)); + } + } + } + } + + private void CarBodyColorRemap1TextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + int cr = 0; + int.TryParse(CarBodyColorRemap1TextBox.Text, out cr); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.bodyColorRemap1 != cr) + { + CurrentCarGen._CCarGen.bodyColorRemap1 = cr; + SetYmapHasChanged(true); + } + } + } + + private void CarBodyColorRemap2TextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + int cr = 0; + int.TryParse(CarBodyColorRemap2TextBox.Text, out cr); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.bodyColorRemap2 != cr) + { + CurrentCarGen._CCarGen.bodyColorRemap2 = cr; + SetYmapHasChanged(true); + } + } + } + + private void CarBodyColorRemap3TextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + int cr = 0; + int.TryParse(CarBodyColorRemap3TextBox.Text, out cr); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.bodyColorRemap3 != cr) + { + CurrentCarGen._CCarGen.bodyColorRemap3 = cr; + SetYmapHasChanged(true); + } + } + } + + private void CarBodyColorRemap4TextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + int cr = 0; + int.TryParse(CarBodyColorRemap4TextBox.Text, out cr); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.bodyColorRemap4 != cr) + { + CurrentCarGen._CCarGen.bodyColorRemap4 = cr; + SetYmapHasChanged(true); + } + } + } + + private void CarLiveryTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentCarGen == null) return; + sbyte cr = 0; + sbyte.TryParse(CarLiveryTextBox.Text, out cr); + lock (ymapsyncroot) + { + if (CurrentCarGen._CCarGen.livery != cr) + { + CurrentCarGen._CCarGen.livery = cr; + SetYmapHasChanged(true); + } + } + UpdateCarGenTreeNode(CurrentCarGen); + } + + private void CarGoToButton_Click(object sender, EventArgs e) + { + if (CurrentCarGen == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentCarGen.Position); + } + + private void CarAddToProjectButton_Click(object sender, EventArgs e) + { + AddCarGenToProject(); + } + + private void CarDeleteButton_Click(object sender, EventArgs e) + { + DeleteCarGen(); + } + + + + + + + + + + private void YndAreaIDUpDownChange() + { + if (populatingui) return; + if (CurrentYndFile == null) return; + int x = (int)YndAreaIDXUpDown.Value; + int y = (int)YndAreaIDYUpDown.Value; + lock (yndsyncroot) + { + var areaid = y * 32 + x; + if (CurrentYndFile.AreaID != areaid) + { + CurrentYndFile.AreaID = areaid; + CurrentYndFile.Name = "nodes" + areaid.ToString() + ".ynd"; + YndAreaIDInfoLabel.Text = "ID: " + areaid.ToString(); + SetYndHasChanged(true); + } + } + } + + private void YndAreaIDXUpDown_ValueChanged(object sender, EventArgs e) + { + YndAreaIDUpDownChange(); + } + + private void YndAreaIDYUpDown_ValueChanged(object sender, EventArgs e) + { + YndAreaIDUpDownChange(); + } + + private void YndVehicleNodesUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentYndFile == null) return; + if (CurrentYndFile.NodeDictionary == null) return; + lock (yndsyncroot) + { + var vehnodes = (int)YndVehicleNodesUpDown.Value; + if (CurrentYndFile.NodeDictionary.NodesCountVehicle != vehnodes) + { + CurrentYndFile.NodeDictionary.NodesCountVehicle = (uint)vehnodes; + SetYndHasChanged(true); + } + } + } + + private void YndPedNodesUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentYndFile == null) return; + if (CurrentYndFile.NodeDictionary == null) return; + lock (yndsyncroot) + { + var pednodes = (int)YndPedNodesUpDown.Value; + if (CurrentYndFile.NodeDictionary.NodesCountPed != pednodes) + { + CurrentYndFile.NodeDictionary.NodesCountPed = (uint)pednodes; + SetYndHasChanged(true); + } + } + } + + + private void PathNodeAreaIDUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + ushort areaid = (ushort)PathNodeAreaIDUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathNode.AreaID != areaid) + { + CurrentPathNode.AreaID = areaid; + SetYndHasChanged(true); + } + } + + UpdatePathNodeTreeNode(CurrentPathNode); + } + + private void PathNodeNodeIDUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + ushort nodeid = (ushort)PathNodeNodeIDUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathNode.NodeID != nodeid) + { + CurrentPathNode.NodeID = nodeid; + SetYndHasChanged(true); + } + } + + UpdatePathNodeTreeNode(CurrentPathNode); + } + + private void PathNodePositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + Vector3 v = FloatUtil.ParseVector3String(PathNodePositionTextBox.Text); + bool change = false; + lock (yndsyncroot) + { + if (CurrentPathNode.Position != v) + { + CurrentPathNode.SetPosition(v); + SetYndHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentPathNode.Position); + WorldForm.UpdatePathNodeGraphics(CurrentPathNode, false); + } + //PathNodePositionTextBox.Text = FloatUtil.GetVector3String(CurrentPathNode.Position); + } + } + + private void PathNodeGoToButton_Click(object sender, EventArgs e) + { + if (CurrentPathNode == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentPathNode.Position); + } + + private void PathNodeAddToProjectButton_Click(object sender, EventArgs e) + { + AddPathNodeToProject(); + } + + private void PathNodeDeleteButton_Click(object sender, EventArgs e) + { + DeletePathNode(); + } + + private void PathNodeStreetHashTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + uint hash; + uint.TryParse(PathNodeStreetHashTextBox.Text, out hash); + var streetname = GlobalText.TryGetString(hash); + PathNodeStreetNameLabel.Text = "Name: " + ((hash == 0) ? "[None]" : (string.IsNullOrEmpty(streetname) ? "[Not found]" : streetname)); + + lock (yndsyncroot) + { + if (CurrentPathNode.StreetName.Hash != hash) + { + CurrentPathNode.StreetName = hash; + SetYndHasChanged(true); + } + } + + UpdatePathNodeTreeNode(CurrentPathNode); + } + + private void PathNodeFlags0UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromUpDowns(); + } + + private void PathNodeFlags1UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromUpDowns(); + } + + private void PathNodeFlags2UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromUpDowns(); + } + + private void PathNodeFlags3UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromUpDowns(); + } + + private void PathNodeFlags4UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromUpDowns(); + } + + private void PathNodeFlags5UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromUpDowns(); + } + + private void PathNodeFlags01CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags02CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags03CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags04CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags05CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags06CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags07CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags08CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags11CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags12CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags13CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags14CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags15CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags16CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags17CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags18CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags21CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags22CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags23CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags24CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags25CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags26CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags27CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags28CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags31CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags32UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); //treat this one like checkboxes + } + + private void PathNodeFlags51CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags41CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags45CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags46CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags47CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags48CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags42UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); //treat this one like checkboxes + } + + private void PathNodeFlags52CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + private void PathNodeFlags53CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeFlagsFromCheckBoxes(); + } + + + private void PathNodeLinksListBox_SelectedIndexChanged(object sender, EventArgs e) + { + CurrentPathLink = PathNodeLinksListBox.SelectedItem as YndLink; + LoadPathNodeLinkPage(); + } + + private void PathNodeAddLinkButton_Click(object sender, EventArgs e) + { + AddPathLink(); + } + + private void PathNodeRemoveLinkButton_Click(object sender, EventArgs e) + { + RemovePathLink(); + } + + private void PathNodeLinkAreaIDUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathLink == null) return; + ushort areaid = (ushort)PathNodeLinkAreaIDUpDown.Value; + bool change = false; + lock (yndsyncroot) + { + if (CurrentPathLink._RawData.AreaID != areaid) + { + CurrentPathLink._RawData.AreaID = areaid; + SetYndHasChanged(true); + change = true; + } + } + if (change) + { + UpdatePathNodeLinkage(); + + //refresh the selected item in the list box, to update the text, and the other controls. + PathNodeLinksListBox.Items[PathNodeLinksListBox.SelectedIndex] = PathNodeLinksListBox.SelectedItem; + } + } + + private void PathNodeLinkNodeIDUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathLink == null) return; + ushort nodeid = (ushort)PathNodeLinkNodeIDUpDown.Value; + bool change = false; + lock (yndsyncroot) + { + if (CurrentPathLink._RawData.NodeID != nodeid) + { + CurrentPathLink._RawData.NodeID = nodeid; + SetYndHasChanged(true); + change = true; + } + } + if (change) + { + UpdatePathNodeLinkage(); + + //refresh the selected item in the list box, to update the text, and the other controls. + PathNodeLinksListBox.Items[PathNodeLinksListBox.SelectedIndex] = PathNodeLinksListBox.SelectedItem; + } + } + + private void PathNodeLinkFlags0UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromUpDowns(); + } + + private void PathNodeLinkFlags1UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromUpDowns(); + } + + private void PathNodeLinkFlags2UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromUpDowns(); + } + + private void PathNodeLinkFlags01CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags02CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags03UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags04UpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags11CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags12CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags13CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags14CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags18CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkOffsetSizeUpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags21CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFlags22CheckBox_CheckedChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkFwdLanesUpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkBackLanesUpDown_ValueChanged(object sender, EventArgs e) + { + SetPathNodeLinkFlagsFromCheckBoxes(); + } + + private void PathNodeLinkLengthUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathLink == null) return; + byte length = (byte)PathNodeLinkLengthUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathLink.LinkLength.Value != length) + { + CurrentPathLink.LinkLength = length; + CurrentPathLink._RawData.LinkLength = length; + SetYndHasChanged(true); + } + } + } + + private void PathNodeJunctionEnableCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + lock (yndsyncroot) + { + if (CurrentPathNode.HasJunction != PathNodeJunctionEnableCheckBox.Checked) + { + CurrentPathNode.HasJunction = PathNodeJunctionEnableCheckBox.Checked; + if (CurrentPathNode.HasJunction && (CurrentPathNode.Junction == null)) + { + var j = new YndJunction(); + //init new junction + j._RawData.HeightmapDimX = 1; + j._RawData.HeightmapDimY = 1; + j.Heightmap = new YndJunctionHeightmap(new byte[] { 255 }, j); + j.RefData = new NodeJunctionRef() { AreaID = (ushort)CurrentPathNode.AreaID, NodeID = (ushort)CurrentPathNode.NodeID }; + + CurrentPathNode.Junction = j; + } + SetYndHasChanged(true); + } + } + LoadPathNodeJunctionPage(); + } + + private void PathNodeJunctionMaxZUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + if (CurrentPathNode.Junction == null) return; + short val = (short)PathNodeJunctionMaxZUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathNode.Junction.MaxZ != val) + { + CurrentPathNode.Junction.MaxZ = val; + CurrentPathNode.Junction._RawData.MaxZ = val; + SetYndHasChanged(true); + } + } + } + + private void PathNodeJunctionMinZUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + if (CurrentPathNode.Junction == null) return; + short val = (short)PathNodeJunctionMinZUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathNode.Junction.MinZ != val) + { + CurrentPathNode.Junction.MinZ = val; + CurrentPathNode.Junction._RawData.MinZ = val; + SetYndHasChanged(true); + } + } + } + + private void PathNodeJunctionPosXUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + if (CurrentPathNode.Junction == null) return; + short val = (short)PathNodeJunctionPosXUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathNode.Junction.PositionX != val) + { + CurrentPathNode.Junction.PositionX = val; + CurrentPathNode.Junction._RawData.PositionX = val; + SetYndHasChanged(true); + } + } + } + + private void PathNodeJunctionPosYUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + if (CurrentPathNode.Junction == null) return; + short val = (short)PathNodeJunctionPosYUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathNode.Junction.PositionY != val) + { + CurrentPathNode.Junction.PositionY = val; + CurrentPathNode.Junction._RawData.PositionY = val; + SetYndHasChanged(true); + } + } + } + + private void PathNodeJunctionHeightmapDimXUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + if (CurrentPathNode.Junction == null) return; + byte val = (byte)PathNodeJunctionHeightmapDimXUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathNode.Junction._RawData.HeightmapDimX != val) + { + CurrentPathNode.Junction._RawData.HeightmapDimX = val; + CurrentPathNode.Junction.ResizeHeightmap(); + SetYndHasChanged(true); + } + } + LoadPathNodeJunctionPage(); + } + + private void PathNodeJunctionHeightmapDimYUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + if (CurrentPathNode.Junction == null) return; + byte val = (byte)PathNodeJunctionHeightmapDimYUpDown.Value; + lock (yndsyncroot) + { + if (CurrentPathNode.Junction._RawData.HeightmapDimY != val) + { + CurrentPathNode.Junction._RawData.HeightmapDimY = val; + CurrentPathNode.Junction.ResizeHeightmap(); + SetYndHasChanged(true); + } + } + LoadPathNodeJunctionPage(); + } + + private void PathNodeJunctionHeightmapBytesTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentPathNode == null) return; + if (CurrentPathNode.Junction == null) return; + lock (yndsyncroot) + { + CurrentPathNode.Junction.SetHeightmap(PathNodeJunctionHeightmapBytesTextBox.Text); + SetYndHasChanged(true); + } + //LoadPathNodeJunctionPage(); + } + + + + + + + + + private void TrainNodePositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentTrainNode == null) return; + Vector3 v = FloatUtil.ParseVector3String(TrainNodePositionTextBox.Text); + bool change = false; + lock (trainsyncroot) + { + if (CurrentTrainNode.Position != v) + { + CurrentTrainNode.SetPosition(v); + SetTrainTrackHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentTrainNode.Position); + WorldForm.UpdateTrainTrackNodeGraphics(CurrentTrainNode, false); + } + //TrainNodePositionTextBox.Text = FloatUtil.GetVector3String(CurrentTrainNode.Position); + } + } + + private void TrainNodeGoToButton_Click(object sender, EventArgs e) + { + if (CurrentTrainNode == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentTrainNode.Position); + } + + private void TrainNodeTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentTrainNode == null) return; + int type = TrainNodeTypeComboBox.SelectedIndex; + bool change = false; + lock (trainsyncroot) + { + if (CurrentTrainNode.NodeType != type) + { + CurrentTrainNode.NodeType = type; + SetTrainTrackHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.UpdateTrainTrackNodeGraphics(CurrentTrainNode, false); //change the colour... + } + } + UpdateTrainNodeTreeNode(CurrentTrainNode); + } + + private void TrainNodeAddToProjectButton_Click(object sender, EventArgs e) + { + AddTrainNodeToProject(); + } + + private void TrainNodeDeleteButton_Click(object sender, EventArgs e) + { + DeleteTrainNode(); + } + + + + + + + + + + private void ScenarioYmtVersionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenario == null) return; + if (CurrentScenario.CScenarioPointRegion == null) return; + lock (scenariosyncroot) + { + int v = 0; + int.TryParse(ScenarioYmtVersionTextBox.Text, out v); + if (CurrentScenario.CScenarioPointRegion.VersionNumber != v) + { + CurrentScenario.CScenarioPointRegion.VersionNumber = v; + SetScenarioHasChanged(true); + } + } + } + + + private void ScenarioPointCheckBox_CheckedChanged(object sender, EventArgs e) + { + + } + + private void ScenarioPointAddToProjectButton_Click(object sender, EventArgs e) + { + AddScenarioNodeToProject(); + } + + private void ScenarioPointDeleteButton_Click(object sender, EventArgs e) + { + DeleteScenarioNode(); + } + + private void ScenarioPointGoToButton_Click(object sender, EventArgs e) + { + if (CurrentScenarioNode == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentScenarioNode.Position); + } + + private void ScenarioPointPositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + Vector3 v = FloatUtil.ParseVector3String(ScenarioPointPositionTextBox.Text); + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Position != v) + { + CurrentScenarioNode.SetPosition(v); + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + private void ScenarioPointDirectionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + float dir = FloatUtil.Parse(ScenarioPointDirectionTextBox.Text); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.Direction != dir) + { + CurrentScenarioNode.MyPoint.Direction = dir; + CurrentScenarioNode.Orientation = CurrentScenarioNode.MyPoint.Orientation; + SetScenarioHasChanged(true); + if (WorldForm != null) + { + WorldForm.SetWidgetRotation(CurrentScenarioNode.Orientation); + } + } + } + } + + private void ScenarioPointTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + ScenarioType stype = ScenarioPointTypeComboBox.SelectedItem as ScenarioType; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.Type != stype) + { + CurrentScenarioNode.MyPoint.Type = stype; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioPointModelSetComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + AmbientModelSet mset = ScenarioPointModelSetComboBox.SelectedItem as AmbientModelSet; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.ModelSet != mset) + { + CurrentScenarioNode.MyPoint.ModelSet = mset; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioPointInteriorTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + uint hash = 0; + string name = ScenarioPointInteriorTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioPointInteriorHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.InteriorName != hash) + { + CurrentScenarioNode.MyPoint.InteriorName = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioPointGroupTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + uint hash = 0; + string name = ScenarioPointGroupTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioPointGroupHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.GroupName != hash) + { + CurrentScenarioNode.MyPoint.GroupName = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioPointImapTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + uint hash = 0; + string name = ScenarioPointImapTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioPointImapHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.IMapName != hash) + { + CurrentScenarioNode.MyPoint.IMapName = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioPointTimeStartUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + byte t = (byte)ScenarioPointTimeStartUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.TimeStart != t) + { + CurrentScenarioNode.MyPoint.TimeStart = t; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioPointTimeEndUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + byte t = (byte)ScenarioPointTimeEndUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.TimeEnd != t) + { + CurrentScenarioNode.MyPoint.TimeEnd = t; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioPointProbabilityUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + byte v = (byte)ScenarioPointProbabilityUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.Probability != v) + { + CurrentScenarioNode.MyPoint.Probability = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioPointSpOnlyFlagUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + byte v = (byte)ScenarioPointSpOnlyFlagUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.SpOnlyFlag != v) + { + CurrentScenarioNode.MyPoint.SpOnlyFlag = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioPointRadiusUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + byte v = (byte)ScenarioPointRadiusUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.Radius != v) + { + CurrentScenarioNode.MyPoint.Radius = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioPointWaitTimeUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + byte v = (byte)ScenarioPointWaitTimeUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.WaitTime != v) + { + CurrentScenarioNode.MyPoint.WaitTime = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioPointFlagsValueUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + var iflags = (uint)ScenarioPointFlagsValueUpDown.Value; + populatingui = true; + for (int i = 0; i < ScenarioPointFlagsCheckedListBox.Items.Count; i++) + { + var c = ((iflags & (1 << i)) > 0); + ScenarioPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); + } + populatingui = false; + Unk_700327466 f = (Unk_700327466)iflags; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.Flags != f) + { + CurrentScenarioNode.MyPoint.Flags = f; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioPointFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.MyPoint == null) return; + uint iflags = 0; + for (int i = 0; i < ScenarioPointFlagsCheckedListBox.Items.Count; i++) + { + if (e.Index == i) + { + if (e.NewValue == CheckState.Checked) + { + iflags += (uint)(1 << i); + } + } + else + { + if (ScenarioPointFlagsCheckedListBox.GetItemChecked(i)) + { + iflags += (uint)(1 << i); + } + } + } + populatingui = true; + ScenarioPointFlagsValueUpDown.Value = iflags; + populatingui = false; + Unk_700327466 f = (Unk_700327466)iflags; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.MyPoint.Flags != f) + { + CurrentScenarioNode.MyPoint.Flags = f; + SetScenarioHasChanged(true); + } + } + } + + + private void ScenarioEntityCheckBox_CheckedChanged(object sender, EventArgs e) + { + + } + + private void ScenarioEntityAddToProjectButton_Click(object sender, EventArgs e) + { + AddScenarioNodeToProject(); + } + + private void ScenarioEntityDeleteButton_Click(object sender, EventArgs e) + { + DeleteScenarioEntity(); + } + + private void ScenarioEntityGoToButton_Click(object sender, EventArgs e) + { + if (CurrentScenarioNode == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentScenarioNode.Position); + } + + private void ScenarioEntityPositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.Entity == null) return; + Vector3 v = FloatUtil.ParseVector3String(ScenarioEntityPositionTextBox.Text); + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Position != v) + { + CurrentScenarioNode.SetPosition(v); + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + private void ScenarioEntityTypeTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.Entity == null) return; + uint hash = 0; + string name = ScenarioEntityTypeTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioEntityTypeHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Entity.TypeName != hash) + { + CurrentScenarioNode.Entity.TypeName = hash; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioEntityUnk1UpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.Entity == null) return; + byte v = (byte)ScenarioEntityUnk1UpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Entity.Unk1 != v) + { + CurrentScenarioNode.Entity.Unk1 = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityUnk2UpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.Entity == null) return; + byte v = (byte)ScenarioEntityUnk2UpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Entity.Unk2 != v) + { + CurrentScenarioNode.Entity.Unk2 = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointsListBox_DoubleClick(object sender, EventArgs e) + { + var item = ScenarioEntityPointsListBox.SelectedItem as MCExtensionDefSpawnPoint; + if (item == null) return; + + var nodes = CurrentScenario?.ScenarioRegion?.Nodes; + if (nodes == null) return; + + ScenarioNode node = null; + foreach (var snode in nodes) + { + if (snode.EntityPoint == item) + { + node = snode; + break; + } + } + + if (node == null) return; + + TrySelectScenarioNodeTreeNode(node); + + } + + private void ScenarioEntityAddPointButton_Click(object sender, EventArgs e) + { + AddScenarioEntityPoint(); + } + + + private void ScenarioEntityPointCheckBox_CheckedChanged(object sender, EventArgs e) + { + + } + + private void ScenarioEntityPointAddToProjectButton_Click(object sender, EventArgs e) + { + AddScenarioNodeToProject(); + } + + private void ScenarioEntityPointDeleteButton_Click(object sender, EventArgs e) + { + DeleteScenarioNode(); + } + + private void ScenarioEntityPointGoToButton_Click(object sender, EventArgs e) + { + if (CurrentScenarioNode == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentScenarioNode.Position); + } + + private void ScenarioEntityPointPositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + Vector3 v = FloatUtil.ParseVector3String(ScenarioEntityPointPositionTextBox.Text); + v += CurrentScenarioNode.EntityPoint.ParentPosition; + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Position != v) + { + CurrentScenarioNode.SetPosition(v); + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + private void ScenarioEntityPointRotationTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + Vector4 v = FloatUtil.ParseVector4String(ScenarioEntityPointRotationTextBox.Text); + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.OffsetRotation != v) + { + CurrentScenarioNode.EntityPoint.OffsetRotation = v; + CurrentScenarioNode.Orientation = new Quaternion(v); + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetRotation(CurrentScenarioNode.Orientation); + } + } + } + + private void ScenarioEntityPointNameTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + uint hash = 0; + string name = ScenarioEntityPointNameTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioEntityPointNameHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.NameHash != hash) + { + CurrentScenarioNode.EntityPoint.NameHash = hash; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioEntityPointSpawnTypeTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + uint hash = 0; + string name = ScenarioEntityPointSpawnTypeTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioEntityPointSpawnTypeHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.SpawnType != hash) + { + CurrentScenarioNode.EntityPoint.SpawnType = hash; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioEntityPointPedTypeTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + uint hash = 0; + string name = ScenarioEntityPointPedTypeTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioEntityPointPedTypeHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.PedType != hash) + { + CurrentScenarioNode.EntityPoint.PedType = hash; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioEntityPointGroupTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + uint hash = 0; + string name = ScenarioEntityPointGroupTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioEntityPointGroupHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.Group != hash) + { + CurrentScenarioNode.EntityPoint.Group = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointInteriorTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + uint hash = 0; + string name = ScenarioEntityPointInteriorTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioEntityPointInteriorHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.Interior != hash) + { + CurrentScenarioNode.EntityPoint.Interior = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointRequiredImapTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + uint hash = 0; + string name = ScenarioEntityPointRequiredImapTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioEntityPointRequiredImapHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.RequiredImap != hash) + { + CurrentScenarioNode.EntityPoint.RequiredImap = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointAvailableInMpSpComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + Unk_3573596290 v = (Unk_3573596290)ScenarioEntityPointAvailableInMpSpComboBox.SelectedItem; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.AvailableInMpSp != v) + { + CurrentScenarioNode.EntityPoint.AvailableInMpSp = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointProbabilityTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + float v = FloatUtil.Parse(ScenarioEntityPointProbabilityTextBox.Text); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.Probability != v) + { + CurrentScenarioNode.EntityPoint.Probability = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointTimeTillPedLeavesTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + float v = FloatUtil.Parse(ScenarioEntityPointTimeTillPedLeavesTextBox.Text); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.TimeTillPedLeaves != v) + { + CurrentScenarioNode.EntityPoint.TimeTillPedLeaves = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointRadiusTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + float v = FloatUtil.Parse(ScenarioEntityPointRadiusTextBox.Text); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.Radius != v) + { + CurrentScenarioNode.EntityPoint.Radius = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointStartUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + byte v = (byte)ScenarioEntityPointStartUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.StartTime != v) + { + CurrentScenarioNode.EntityPoint.StartTime = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointEndUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + byte v = (byte)ScenarioEntityPointEndUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.EndTime != v) + { + CurrentScenarioNode.EntityPoint.EndTime = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointExtendedRangeCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + bool v = ScenarioEntityPointExtendedRangeCheckBox.Checked; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.ExtendedRange != v) + { + CurrentScenarioNode.EntityPoint.ExtendedRange = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointShortRangeCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + bool v = ScenarioEntityPointShortRangeCheckBox.Checked; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.ShortRange != v) + { + CurrentScenarioNode.EntityPoint.ShortRange = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointHighPriCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + bool v = ScenarioEntityPointHighPriCheckBox.Checked; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.HighPri != v) + { + CurrentScenarioNode.EntityPoint.HighPri = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointFlagsUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + var iflags = (uint)ScenarioEntityPointFlagsUpDown.Value; + populatingui = true; + for (int i = 0; i < ScenarioEntityPointFlagsCheckedListBox.Items.Count; i++) + { + var c = ((iflags & (1 << i)) > 0); + ScenarioEntityPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); + } + populatingui = false; + Unk_700327466 f = (Unk_700327466)iflags; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.Flags != f) + { + CurrentScenarioNode.EntityPoint.Flags = f; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioEntityPointFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.EntityPoint == null) return; + uint iflags = 0; + for (int i = 0; i < ScenarioEntityPointFlagsCheckedListBox.Items.Count; i++) + { + if (e.Index == i) + { + if (e.NewValue == CheckState.Checked) + { + iflags += (uint)(1 << i); + } + } + else + { + if (ScenarioEntityPointFlagsCheckedListBox.GetItemChecked(i)) + { + iflags += (uint)(1 << i); + } + } + } + populatingui = true; + ScenarioEntityPointFlagsUpDown.Value = iflags; + populatingui = false; + Unk_700327466 f = (Unk_700327466)iflags; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.EntityPoint.Flags != f) + { + CurrentScenarioNode.EntityPoint.Flags = f; + SetScenarioHasChanged(true); + } + } + } + + + private void ScenarioChainNodeCheckBox_CheckedChanged(object sender, EventArgs e) + { + + } + + private void ScenarioChainNodeAddToProjectButton_Click(object sender, EventArgs e) + { + AddScenarioNodeToProject(); + } + + private void ScenarioChainNodeDeleteButton_Click(object sender, EventArgs e) + { + DeleteScenarioNode(); + } + + private void ScenarioChainNodeGoToButton_Click(object sender, EventArgs e) + { + if (CurrentScenarioNode == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentScenarioNode.Position); + } + + private void ScenarioChainNodePositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + Vector3 v = FloatUtil.ParseVector3String(ScenarioChainNodePositionTextBox.Text); + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Position != v) + { + CurrentScenarioNode.SetPosition(v); + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + private void ScenarioChainNodeUnk1TextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ChainingNode == null) return; + uint hash = 0; + string name = ScenarioChainNodeUnk1TextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioChainNodeUnk1HashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ChainingNode.Unk1 != hash) + { + CurrentScenarioNode.ChainingNode.Unk1 = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioChainNodeTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ChainingNode == null) return; + ScenarioType stype = ScenarioChainNodeTypeComboBox.SelectedItem as ScenarioType; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ChainingNode.Type != stype) + { + CurrentScenarioNode.ChainingNode.Type = stype; + CurrentScenarioNode.ChainingNode.TypeHash = stype?.NameHash ?? 0; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioChainNodeFirstCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ChainingNode == null) return; + bool v = !ScenarioChainNodeFirstCheckBox.Checked; + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ChainingNode.NotFirst != v) + { + CurrentScenarioNode.ChainingNode.NotFirst = v; + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + private void ScenarioChainNodeLastCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ChainingNode == null) return; + bool v = !ScenarioChainNodeLastCheckBox.Checked; + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ChainingNode.NotLast != v) + { + CurrentScenarioNode.ChainingNode.NotLast = v; + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + + private void ScenarioChainAddToProjectButton_Click(object sender, EventArgs e) + { + AddScenarioNodeToProject(); + } + + private void ScenarioChainDeleteButton_Click(object sender, EventArgs e) + { + DeleteScenarioChain(); + } + + private void ScenarioChainEdgesListBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + CurrentScenarioChainEdge = ScenarioChainEdgesListBox.SelectedItem as MCScenarioChainingEdge; + populatingui = true; + LoadScenarioChainEdgeTabPage(); + populatingui = false; + } + + private void ScenarioChainAddEdgeButton_Click(object sender, EventArgs e) + { + AddScenarioEdge(); + } + + private void ScenarioChainRemoveEdgeButton_Click(object sender, EventArgs e) + { + RemoveScenarioEdge(); + } + + private void ScenarioChainMoveEdgeUpButton_Click(object sender, EventArgs e) + { + MoveScenarioEdge(false); + } + + private void ScenarioChainMoveEdgeDownButton_Click(object sender, EventArgs e) + { + MoveScenarioEdge(true); + } + + private void ScenarioChainUnk1UpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ChainingNode == null) return; + if (CurrentScenarioNode.ChainingNode.Chain == null) return; + byte v = (byte)ScenarioChainUnk1UpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ChainingNode.Chain.Unk1 != v) + { + CurrentScenarioNode.ChainingNode.Chain.Unk1 = v; + SetScenarioHasChanged(true); + } + } + } + + + private void ScenarioChainEdgeNodeIndexFromUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioChainEdge == null) return; + ushort nodeid = (ushort)ScenarioChainEdgeNodeIndexFromUpDown.Value; + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioChainEdge.NodeIndexFrom != nodeid) + { + CurrentScenarioChainEdge.NodeIndexFrom = nodeid; + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + UpdateScenarioEdgeLinkage(); + + //refresh the selected item in the list box, to update the text, and the other controls. + ScenarioChainEdgesListBox.Items[ScenarioChainEdgesListBox.SelectedIndex] = ScenarioChainEdgesListBox.SelectedItem; + } + } + + private void ScenarioChainEdgeNodeIndexToUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioChainEdge == null) return; + ushort nodeid = (ushort)ScenarioChainEdgeNodeIndexToUpDown.Value; + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioChainEdge.NodeIndexTo != nodeid) + { + CurrentScenarioChainEdge.NodeIndexTo = nodeid; + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + UpdateScenarioEdgeLinkage(); + + //refresh the selected item in the list box, to update the text, and the other controls. + ScenarioChainEdgesListBox.Items[ScenarioChainEdgesListBox.SelectedIndex] = ScenarioChainEdgesListBox.SelectedItem; + } + } + + private void ScenarioChainEdgeActionComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioChainEdge == null) return; + Unk_3609807418 v = (Unk_3609807418)ScenarioChainEdgeActionComboBox.SelectedItem; + lock (scenariosyncroot) + { + if (CurrentScenarioChainEdge.Action != v) + { + CurrentScenarioChainEdge.Action = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioChainEdgeNavModeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioChainEdge == null) return; + Unk_3971773454 v = (Unk_3971773454)ScenarioChainEdgeNavModeComboBox.SelectedItem; + lock (scenariosyncroot) + { + if (CurrentScenarioChainEdge.NavMode != v) + { + CurrentScenarioChainEdge.NavMode = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioChainEdgeNavSpeedComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioChainEdge == null) return; + Unk_941086046 v = (Unk_941086046)ScenarioChainEdgeNavSpeedComboBox.SelectedItem; + lock (scenariosyncroot) + { + if (CurrentScenarioChainEdge.NavSpeed != v) + { + CurrentScenarioChainEdge.NavSpeed = v; + SetScenarioHasChanged(true); + } + } + } + + + private void ScenarioClusterCheckBox_CheckedChanged(object sender, EventArgs e) + { + + } + + private void ScenarioClusterAddToProjectButton_Click(object sender, EventArgs e) + { + AddScenarioNodeToProject(); + } + + private void ScenarioClusterDeleteButton_Click(object sender, EventArgs e) + { + DeleteScenarioCluster(); + } + + private void ScenarioClusterGoToButton_Click(object sender, EventArgs e) + { + if (CurrentScenarioNode == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentScenarioNode.Position); + } + + private void ScenarioClusterCenterTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + Vector3 v = FloatUtil.ParseVector3String(ScenarioClusterCenterTextBox.Text); + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Position != v) + { + CurrentScenarioNode.SetPosition(v); + SetScenarioHasChanged(true); + change = true; + } + if ((CurrentScenarioNode.Cluster != null) && (CurrentScenarioNode.Cluster.Position != v)) + { + CurrentScenarioNode.Cluster.Position = v; + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + private void ScenarioClusterRadiusTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + float r = FloatUtil.Parse(ScenarioClusterRadiusTextBox.Text); + bool change = false; + lock (scenariosyncroot) + { + if ((CurrentScenarioNode.Cluster != null) && (CurrentScenarioNode.Cluster.Radius != r)) + { + CurrentScenarioNode.Cluster.Radius = r; + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + private void ScenarioClusterUnk1TextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.Cluster == null) return; + float v = FloatUtil.Parse(ScenarioClusterUnk1TextBox.Text); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Cluster.Unk1 != v) + { + CurrentScenarioNode.Cluster.Unk1 = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterUnk2CheckBox_CheckedChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.Cluster == null) return; + bool v = ScenarioClusterUnk2CheckBox.Checked; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Cluster.Unk2 != v) + { + CurrentScenarioNode.Cluster.Unk2 = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointsListBox_DoubleClick(object sender, EventArgs e) + { + var item = ScenarioClusterPointsListBox.SelectedItem as MCScenarioPoint; + if (item == null) return; + + var nodes = CurrentScenario?.ScenarioRegion?.Nodes; + if (nodes == null) return; + + ScenarioNode node = null; + foreach (var snode in nodes) + { + if (snode.ClusterMyPoint == item) + { + node = snode; + break; + } + } + + if (node == null) return; + + TrySelectScenarioNodeTreeNode(node); + + } + + private void ScenarioClusterAddPointButton_Click(object sender, EventArgs e) + { + AddScenarioClusterPoint(); + } + + + private void ScenarioClusterPointCheckBox_CheckedChanged(object sender, EventArgs e) + { + + } + + private void ScenarioClusterPointAddToProjectButton_Click(object sender, EventArgs e) + { + AddScenarioNodeToProject(); + } + + private void ScenarioClusterPointDeleteButton_Click(object sender, EventArgs e) + { + DeleteScenarioNode(); + } + + private void ScenarioClusterPointGoToButton_Click(object sender, EventArgs e) + { + if (CurrentScenarioNode == null) return; + if (WorldForm == null) return; + WorldForm.GoToPosition(CurrentScenarioNode.Position); + } + + private void ScenarioClusterPointPositionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + Vector3 v = FloatUtil.ParseVector3String(ScenarioClusterPointPositionTextBox.Text); + bool change = false; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.Position != v) + { + CurrentScenarioNode.SetPosition(v); + SetScenarioHasChanged(true); + change = true; + } + } + if (change) + { + if (WorldForm != null) + { + WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); + WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + } + } + } + + private void ScenarioClusterPointDirectionTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + float dir = FloatUtil.Parse(ScenarioClusterPointDirectionTextBox.Text); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.Direction != dir) + { + CurrentScenarioNode.ClusterMyPoint.Direction = dir; + CurrentScenarioNode.Orientation = CurrentScenarioNode.ClusterMyPoint.Orientation; + SetScenarioHasChanged(true); + if (WorldForm != null) + { + WorldForm.SetWidgetRotation(CurrentScenarioNode.Orientation); + } + } + } + } + + private void ScenarioClusterPointTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + ScenarioType stype = ScenarioClusterPointTypeComboBox.SelectedItem as ScenarioType; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.Type != stype) + { + CurrentScenarioNode.ClusterMyPoint.Type = stype; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioClusterPointModelSetComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + AmbientModelSet mset = ScenarioClusterPointModelSetComboBox.SelectedItem as AmbientModelSet; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.ModelSet != mset) + { + CurrentScenarioNode.ClusterMyPoint.ModelSet = mset; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioClusterPointInteriorTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + uint hash = 0; + string name = ScenarioClusterPointInteriorTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioClusterPointInteriorHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.InteriorName != hash) + { + CurrentScenarioNode.ClusterMyPoint.InteriorName = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointGroupTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + uint hash = 0; + string name = ScenarioClusterPointGroupTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioClusterPointGroupHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.GroupName != hash) + { + CurrentScenarioNode.ClusterMyPoint.GroupName = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointImapTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + uint hash = 0; + string name = ScenarioClusterPointImapTextBox.Text; + if (!uint.TryParse(name, out hash))//don't re-hash hashes + { + hash = JenkHash.GenHash(name); + JenkIndex.Ensure(name); + } + ScenarioClusterPointImapHashLabel.Text = "Hash: " + hash.ToString(); + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.IMapName != hash) + { + CurrentScenarioNode.ClusterMyPoint.IMapName = hash; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointTimeStartUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + byte t = (byte)ScenarioClusterPointTimeStartUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.TimeStart != t) + { + CurrentScenarioNode.ClusterMyPoint.TimeStart = t; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioClusterPointTimeEndUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + byte t = (byte)ScenarioClusterPointTimeEndUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.TimeEnd != t) + { + CurrentScenarioNode.ClusterMyPoint.TimeEnd = t; + SetScenarioHasChanged(true); + } + } + UpdateScenarioNodeTreeNode(CurrentScenarioNode); + } + + private void ScenarioClusterPointProbabilityUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + byte v = (byte)ScenarioClusterPointProbabilityUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.Probability != v) + { + CurrentScenarioNode.ClusterMyPoint.Probability = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointAnimalFlagUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + byte v = (byte)ScenarioClusterPointAnimalFlagUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.SpOnlyFlag != v) + { + CurrentScenarioNode.ClusterMyPoint.SpOnlyFlag = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointRadiusUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + byte v = (byte)ScenarioClusterPointRadiusUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.Radius != v) + { + CurrentScenarioNode.ClusterMyPoint.Radius = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointWaitTimeUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + byte v = (byte)ScenarioClusterPointWaitTimeUpDown.Value; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.WaitTime != v) + { + CurrentScenarioNode.ClusterMyPoint.WaitTime = v; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointFlagsUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + var iflags = (uint)ScenarioClusterPointFlagsUpDown.Value; + populatingui = true; + for (int i = 0; i < ScenarioClusterPointFlagsCheckedListBox.Items.Count; i++) + { + var c = ((iflags & (1 << i)) > 0); + ScenarioClusterPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); + } + populatingui = false; + Unk_700327466 f = (Unk_700327466)iflags; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.Flags != f) + { + CurrentScenarioNode.ClusterMyPoint.Flags = f; + SetScenarioHasChanged(true); + } + } + } + + private void ScenarioClusterPointFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) + { + if (populatingui) return; + if (CurrentScenarioNode == null) return; + if (CurrentScenarioNode.ClusterMyPoint == null) return; + uint iflags = 0; + for (int i = 0; i < ScenarioClusterPointFlagsCheckedListBox.Items.Count; i++) + { + if (e.Index == i) + { + if (e.NewValue == CheckState.Checked) + { + iflags += (uint)(1 << i); + } + } + else + { + if (ScenarioClusterPointFlagsCheckedListBox.GetItemChecked(i)) + { + iflags += (uint)(1 << i); + } + } + } + populatingui = true; + ScenarioClusterPointFlagsUpDown.Value = iflags; + populatingui = false; + Unk_700327466 f = (Unk_700327466)iflags; + lock (scenariosyncroot) + { + if (CurrentScenarioNode.ClusterMyPoint.Flags != f) + { + CurrentScenarioNode.ClusterMyPoint.Flags = f; + SetScenarioHasChanged(true); + } + } + } + } +} diff --git a/ProjectForm.resx b/ProjectForm.resx new file mode 100644 index 0000000..5a54a89 --- /dev/null +++ b/ProjectForm.resx @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 146, 17 + + + 277, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..278cd8a --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CodeWalker")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CodeWalker")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3bb16320-99bf-4e30-9065-ca0877a36bf4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs new file mode 100644 index 0000000..72d1e2f --- /dev/null +++ b/Properties/Resources.Designer.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CodeWalker.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeWalker.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon CW { + get { + object obj = ResourceManager.GetObject("CW", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] magic { + get { + object obj = ResourceManager.GetObject("magic", resourceCulture); + return ((byte[])(obj)); + } + } + } +} diff --git a/Properties/Resources.resx b/Properties/Resources.resx new file mode 100644 index 0000000..a7076d4 --- /dev/null +++ b/Properties/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\CW.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\magic.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs new file mode 100644 index 0000000..a5ce74f --- /dev/null +++ b/Properties/Settings.Designer.cs @@ -0,0 +1,678 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CodeWalker.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string Key { + get { + return ((string)(this["Key"])); + } + set { + this["Key"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("C:\\Program Files (x86)\\Steam\\SteamApps\\common\\Grand Theft Auto V")] + public string GTAFolder { + get { + return ((string)(this["GTAFolder"])); + } + set { + this["GTAFolder"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string CompiledScriptFolder { + get { + return ((string)(this["CompiledScriptFolder"])); + } + set { + this["CompiledScriptFolder"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string DecompiledScriptFolder { + get { + return ((string)(this["DecompiledScriptFolder"])); + } + set { + this["DecompiledScriptFolder"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string GTAExeDumpFile { + get { + return ((string)(this["GTAExeDumpFile"])); + } + set { + this["GTAExeDumpFile"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string ExtractedTexturesFolder { + get { + return ((string)(this["ExtractedTexturesFolder"])); + } + set { + this["ExtractedTexturesFolder"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string ExtractedRawFilesFolder { + get { + return ((string)(this["ExtractedRawFilesFolder"])); + } + set { + this["ExtractedRawFilesFolder"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string ExtractedShadersFolder { + get { + return ((string)(this["ExtractedShadersFolder"])); + } + set { + this["ExtractedShadersFolder"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool FullScreen { + get { + return ((bool)(this["FullScreen"])); + } + set { + this["FullScreen"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool Wireframe { + get { + return ((bool)(this["Wireframe"])); + } + set { + this["Wireframe"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool Skydome { + get { + return ((bool)(this["Skydome"])); + } + set { + this["Skydome"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ShowTimedEntities { + get { + return ((bool)(this["ShowTimedEntities"])); + } + set { + this["ShowTimedEntities"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool ShowCollisionMeshes { + get { + return ((bool)(this["ShowCollisionMeshes"])); + } + set { + this["ShowCollisionMeshes"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("4")] + public int CollisionMeshRange { + get { + return ((int)(this["CollisionMeshRange"])); + } + set { + this["CollisionMeshRange"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool DynamicLOD { + get { + return ((bool)(this["DynamicLOD"])); + } + set { + this["DynamicLOD"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("5")] + public int DetailDist { + get { + return ((int)(this["DetailDist"])); + } + set { + this["DetailDist"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Glokon Marker")] + public string MarkerStyle { + get { + return ((string)(this["MarkerStyle"])); + } + set { + this["MarkerStyle"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Glokon Debug")] + public string LocatorStyle { + get { + return ((string)(this["LocatorStyle"])); + } + set { + this["LocatorStyle"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool MarkerDepthClip { + get { + return ((bool)(this["MarkerDepthClip"])); + } + set { + this["MarkerDepthClip"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("None")] + public string BoundsStyle { + get { + return ((string)(this["BoundsStyle"])); + } + set { + this["BoundsStyle"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool BoundsDepthClip { + get { + return ((bool)(this["BoundsDepthClip"])); + } + set { + this["BoundsDepthClip"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("100")] + public int BoundsRange { + get { + return ((int)(this["BoundsRange"])); + } + set { + this["BoundsRange"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool ShowErrorConsole { + get { + return ((bool)(this["ShowErrorConsole"])); + } + set { + this["ShowErrorConsole"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool Shadows { + get { + return ((bool)(this["Shadows"])); + } + set { + this["Shadows"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("6")] + public int ShadowCascades { + get { + return ((int)(this["ShadowCascades"])); + } + set { + this["ShadowCascades"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ShowStatusBar { + get { + return ((bool)(this["ShowStatusBar"])); + } + set { + this["ShowStatusBar"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool WaitForChildren { + get { + return ((bool)(this["WaitForChildren"])); + } + set { + this["WaitForChildren"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("2147483648")] + public long CacheSize { + get { + return ((long)(this["CacheSize"])); + } + set { + this["CacheSize"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("10")] + public double CacheTime { + get { + return ((double)(this["CacheTime"])); + } + set { + this["CacheTime"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("536870912")] + public long GPUGeometryCacheSize { + get { + return ((long)(this["GPUGeometryCacheSize"])); + } + set { + this["GPUGeometryCacheSize"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("1073741824")] + public long GPUTextureCacheSize { + get { + return ((long)(this["GPUTextureCacheSize"])); + } + set { + this["GPUTextureCacheSize"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("134217728")] + public long GPUBoundCompCacheSize { + get { + return ((long)(this["GPUBoundCompCacheSize"])); + } + set { + this["GPUBoundCompCacheSize"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("1")] + public double GPUCacheTime { + get { + return ((double)(this["GPUCacheTime"])); + } + set { + this["GPUCacheTime"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0.1")] + public double GPUCacheFlushTime { + get { + return ((double)(this["GPUCacheFlushTime"])); + } + set { + this["GPUCacheFlushTime"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("10")] + public float CameraSmoothing { + get { + return ((float)(this["CameraSmoothing"])); + } + set { + this["CameraSmoothing"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0.005")] + public float CameraSensitivity { + get { + return ((float)(this["CameraSensitivity"])); + } + set { + this["CameraSensitivity"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("1")] + public float CameraFieldOfView { + get { + return ((float)(this["CameraFieldOfView"])); + } + set { + this["CameraFieldOfView"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Default")] + public string RenderMode { + get { + return ((string)(this["RenderMode"])); + } + set { + this["RenderMode"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("DiffuseSampler")] + public string RenderTextureSampler { + get { + return ((string)(this["RenderTextureSampler"])); + } + set { + this["RenderTextureSampler"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Texture coord 1")] + public string RenderTextureSamplerCoord { + get { + return ((string)(this["RenderTextureSamplerCoord"])); + } + set { + this["RenderTextureSamplerCoord"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Installers;_CommonRedist")] + public string ExcludeFolders { + get { + return ((string)(this["ExcludeFolders"])); + } + set { + this["ExcludeFolders"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool AnisotropicFiltering { + get { + return ((bool)(this["AnisotropicFiltering"])); + } + set { + this["AnisotropicFiltering"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool HDR { + get { + return ((bool)(this["HDR"])); + } + set { + this["HDR"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool WindowMaximized { + get { + return ((bool)(this["WindowMaximized"])); + } + set { + this["WindowMaximized"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool EnableMods { + get { + return ((bool)(this["EnableMods"])); + } + set { + this["EnableMods"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string DLC { + get { + return ((string)(this["DLC"])); + } + set { + this["DLC"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute(@" + + Move Forwards: W + Move Backwards: S + Move Left: A + Move Right: D + Move Up: R + Move Down: F + Move Slower / Zoom In: Z + Move Faster / Zoom Out: X + Toggle Mouse Select: C + Toggle Toolbar: T + Exit Edit Mode: Q + Edit Position: W + Edit Rotation: E + Edit Scale: R +")] + public global::System.Collections.Specialized.StringCollection KeyBindings { + get { + return ((global::System.Collections.Specialized.StringCollection)(this["KeyBindings"])); + } + set { + this["KeyBindings"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool XInputLThumbInvert { + get { + return ((bool)(this["XInputLThumbInvert"])); + } + set { + this["XInputLThumbInvert"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool XInputRThumbInvert { + get { + return ((bool)(this["XInputRThumbInvert"])); + } + set { + this["XInputRThumbInvert"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("2")] + public float XInputLThumbSensitivity { + get { + return ((float)(this["XInputLThumbSensitivity"])); + } + set { + this["XInputLThumbSensitivity"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("2")] + public float XInputRThumbSensitivity { + get { + return ((float)(this["XInputRThumbSensitivity"])); + } + set { + this["XInputRThumbSensitivity"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("2")] + public float XInputZoomSpeed { + get { + return ((float)(this["XInputZoomSpeed"])); + } + set { + this["XInputZoomSpeed"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("15")] + public float XInputMoveSpeed { + get { + return ((float)(this["XInputMoveSpeed"])); + } + set { + this["XInputMoveSpeed"] = value; + } + } + } +} diff --git a/Properties/Settings.settings b/Properties/Settings.settings new file mode 100644 index 0000000..eb9b7c8 --- /dev/null +++ b/Properties/Settings.settings @@ -0,0 +1,181 @@ + + + + + + + + + C:\Program Files (x86)\Steam\SteamApps\common\Grand Theft Auto V + + + + + + + + + + + + + + + + + + + + + False + + + False + + + True + + + True + + + False + + + 4 + + + True + + + 5 + + + Glokon Marker + + + Glokon Debug + + + False + + + None + + + True + + + 100 + + + False + + + True + + + 6 + + + True + + + False + + + 2147483648 + + + 10 + + + 536870912 + + + 1073741824 + + + 134217728 + + + 1 + + + 0.1 + + + 10 + + + 0.005 + + + 1 + + + Default + + + DiffuseSampler + + + Texture coord 1 + + + Installers;_CommonRedist + + + True + + + True + + + False + + + False + + + + + + <?xml version="1.0" encoding="utf-16"?> +<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <string>Move Forwards: W</string> + <string>Move Backwards: S</string> + <string>Move Left: A</string> + <string>Move Right: D</string> + <string>Move Up: R</string> + <string>Move Down: F</string> + <string>Move Slower / Zoom In: Z</string> + <string>Move Faster / Zoom Out: X</string> + <string>Toggle Mouse Select: C</string> + <string>Toggle Toolbar: T</string> + <string>Exit Edit Mode: Q</string> + <string>Edit Position: W</string> + <string>Edit Rotation: E</string> + <string>Edit Scale: R</string> +</ArrayOfString> + + + True + + + False + + + 2 + + + 2 + + + 2 + + + 15 + + + \ No newline at end of file diff --git a/Readme.txt b/Readme.txt new file mode 100644 index 0000000..08c0821 --- /dev/null +++ b/Readme.txt @@ -0,0 +1,119 @@ +CodeWalker by dexyfex +---------------------- + +This program is for viewing the contents of GTAV RPF archives. + + +Requirements: +-------------- +- PC version of GTAV +- DirectX 11 and Shader Model 4.0 capable graphics +- Windows 7 and above, x64 processor +- 4GB RAM (8+ recommended) +- .NET framework 4.5 or newer (download from Microsoft..?) + + + +Using the app: +--------------- +On first startup, the app will prompt to browse for the GTAV game folder. If you have the Steam version installed +in the default location (C:\Program Files (x86)\Steam\SteamApps\common\Grand Theft Auto V), then this step will +be skipped automatically. + +The World View will load by default. It will take a while to load. +Use the WASD keys to move the camera. +Drag the left mouse button to rotate the view. +Use the mouse wheel to zoom in/out, and change the movement speed. (Zoom in = slower motion) +XBox controller input is also supported. +The Toolbox can be shown by clicking the "<<" button in the top right-hand corner of the screen. +T opens the toolbar. + +First-person mode can be activated with the P key, or by pressing the Start button on the XBox controller. +While in first-person mode, the left mouse button (or right trigger) will fire an egg. + +Entities can be selected (with the right mouse button) by enabling the option on the Selection tab in the +toolbox. The details of the selected entity, its archetype, and its drawable can be explored in the relevant +sub-tabs. (This option can also be activated with the arrow button on the toolbar) + +When an entity is selected, E will switch to edit mode (or alternatively, edit mode can be activated by +switching the Widget mode to anything other than Default). When in edit mode, Q will exit edit mode, W toggles +the position widget, E toggles rotation, and R toggles scale. Also when in edit mode, movement is still WSAD, +but only while you're holding the left mouse button down, and not interacting with the widget. + +Ctrl-Z and Ctrl-Y will Undo and Redo entity transformation (position/rotation/scale) actions. + +The Project Window allows a CodeWalker project to be created (.cwproj), and files added to it. Editing +entities while the Project Window is open will add the entity's .ymap to the current project. Ymap files can then +be saved to disk, for use in a map mod. New ymap files can also be created, and entities can be added and removed. +Also supported for editing are .ynd files (traffic paths), trains .dat files (train tracks), and scenarios (.ymt). +(A full tutorial on making map mods is out of the scope of this readme.) + +A full explanation of all the tools in this application is still on the to-do list! +The user is currently left to explore the options at their own peril. +Note some options may cause CodeWalker to crash, or otherwise stop working properly. Restart the program if this +happens! +Also note that this program is a constant work in progress, so bugs and crashes are to be expected. +Some parts of the world do not yet render correctly, but expect updates in the future to fix these issues. + + +Menu mode: +---------- +The app can also be started with a main menu instead of loading the world view. This can be useful for situations +where the world view is not needed, and the world loading can be avoided. +To activate the menu mode, run CodeWalker with the 'menu' command line argument, e.g: +CodeWalker.exe menu + + +Explorer mode: +-------------- +The app can be started with the 'explorer' command line argument. This displays an interface much like OpenIV, +with a Windows-Explorer style interface for browsing the game's .rpf archives. Double-click on files to open them. +Viewers for most file types are available, but hex view will be shown as a fallback. +To activate the explorer mode, run the command: +CodeWalker.exe explorer +Alternatively, run the CodeWalker Explorer batch file in the program's directory. + + + +Regarding game files: (FYI) +---------------------------- + +The PC GTAV world is stored in the RPF archives in many different file formats. As expected, some formats are +used for storing rendering-related content, for example the textures and 3d models, while other formats are used +for storing game and engine related data. + +The main formats when it comes to rendering GTAV content are: + +.ytd - Texture Dictionary - Stores texture data in a DirectX format convenient for loading to the GPU. +.ydr - Drawable - Contains a single asset's 3d model. Can contain a Texture Dictionary, and up to 4 LODs of a model. +.ydd - Drawable Dictionary - A collection of Drawables packed into a single file. +.yft - Fragment - Contains a Drawable, along with other metadata for example physics data. + + +The content Assets are pieced together to create the GTAV world via MapTypes (Archetypes) and MapData +(Entity placements). At a high level, Archeypes define objects that are placeable, and Entities define +where those objects are placed to make up the world. The collision mesh data for the world is stored in Bounds +files. +The formats for these are: + +.ytyp - MapTypes - Contains a group of MapTypes (Archetypes), each defining an object that could be placed. +.ymap - MapData - Contains placements of Archetypes, each defining an Entity in the world. +.ybn - Bounds - Contains collision mesh / bounding data for pieces of the world. + + +The EntityData contained within the MapData (.ymap) files forms the LOD hierarchy. This heierarchy is arranged +such that the lowest detail version of the world, at the root of the hierarchy, is represented by a small number +of large models that can all be rendered simultaneously to draw the world at a great distance. The next branch +in the hierarchy splits each of these large models into a group of smaller objects, each represented in a higher +detail than the previous level. This pattern is continued for up to 6 levels of detail. When rendering the world, +the correct level of detail for each branch in the hierarchy needs to be determined, as obviously the highest +detail objects cannot all be rendered at once due to limited computing resources. + +In CodeWalker, This is done by recursing the LOD tree from the roots, checking how far away from the camera the +node's Entity is. If it is below a certain value, then the current level is used, otherwise it moves to the +next higher level, depending on the LOD distance setting. +(In the Ymap view, the highest LOD, ORPHANHD, is not rendered by default. The ORPHANHD entities can often be +manually renderd by specifying the correct _strm_ ymap file for the area in question in the ymap text box. The +_strm ymap name can often be found by mouse-selecting a high detail object in the area and noting what ymap the +Entity is contained in, in the selection details panel.) + diff --git a/Readme_Src.txt b/Readme_Src.txt new file mode 100644 index 0000000..2aca231 --- /dev/null +++ b/Readme_Src.txt @@ -0,0 +1,3 @@ +CodeWalker by dexyfex - Source Code + +This source code is released for educational purposes only. \ No newline at end of file diff --git a/Rendering/DirectX/DXForm.cs b/Rendering/DirectX/DXForm.cs new file mode 100644 index 0000000..2792083 --- /dev/null +++ b/Rendering/DirectX/DXForm.cs @@ -0,0 +1,28 @@ +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.Rendering +{ + public interface DXForm + { + //unfortunately this can't be made a base class for the main render forms, because the + //form designer causes an error when inheriting from a form in the same project, if + //the architecture is set to x64. really annoying! + //So, i've used an interface instead, since really just some of the form properties + //and a couple of extra methods (these callbacks) are needed by DXManager. + + Form Form { get; } + + + void InitScene(Device device); + void CleanupScene(); + void RenderScene(DeviceContext context); + void BuffersResized(int w, int h); + } +} diff --git a/Rendering/DirectX/DXManager.cs b/Rendering/DirectX/DXManager.cs new file mode 100644 index 0000000..7c6a1c9 --- /dev/null +++ b/Rendering/DirectX/DXManager.cs @@ -0,0 +1,337 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using Color = SharpDX.Color; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using DriverType = SharpDX.Direct3D.DriverType; +using System.Threading; +using System.Windows.Forms; +using SharpDX; +using SharpDX.Direct3D; + +namespace CodeWalker.Rendering +{ + public class DXManager + { + private DXForm dxform; + + public Device device { get; private set; } + public DeviceContext context { get; private set; } + public SwapChain swapchain { get; private set; } + public Texture2D backbuffer { get; private set; } + public Texture2D depthbuffer { get; private set; } + public RenderTargetView targetview { get; private set; } + public DepthStencilView depthview { get; private set; } + + private volatile bool Running = false; + private volatile bool Rendering = false; + private volatile bool Resizing = false; + private object syncroot = new object(); //for thread safety + public int multisamplecount { get; private set; } = 4; //should be a setting.. + public int multisamplequality { get; private set; } = 0; //should be a setting... + public Color clearcolour { get; private set; } = new Color(0.2f, 0.4f, 0.6f, 1.0f); //gross + private System.Drawing.Size beginSize; + private ViewportF Viewport; + private bool autoStartLoop = false; + + public bool Init(DXForm form, bool autostart = true) + { + dxform = form; + autoStartLoop = autostart; + + try + { + + SwapChainDescription scd = new SwapChainDescription() + { + BufferCount = 2, + Flags = SwapChainFlags.None, + IsWindowed = true, + ModeDescription = new ModeDescription( + form.Form.ClientSize.Width, + form.Form.ClientSize.Height, + new Rational(0, 0), + Format.R8G8B8A8_UNorm), + OutputHandle = form.Form.Handle, + SampleDescription = new SampleDescription(multisamplecount, multisamplequality), + SwapEffect = SwapEffect.Discard, + Usage = Usage.RenderTargetOutput + }; + + FeatureLevel[] levels = new FeatureLevel[] { FeatureLevel.Level_10_0 }; + + DeviceCreationFlags flags = DeviceCreationFlags.None; + //#if DEBUG + // flags = DeviceCreationFlags.Debug; + //#endif + Device dev = null; + SwapChain sc = null; + + bool success = false; + try + { + Device.CreateWithSwapChain(DriverType.Hardware, flags, levels, scd, out dev, out sc); + success = true; + } + catch { } + + if (!success) + { + multisamplecount = 1; + multisamplequality = 0; + scd.SampleDescription = new SampleDescription(1, 0); //try no AA + try + { + Device.CreateWithSwapChain(DriverType.Hardware, flags, levels, scd, out dev, out sc); + success = true; + } + catch { } + } + + if (!success) + { + throw new Exception("CodeWalker was unable to initialise the graphics device. Please ensure your system meets the minimum requirements and that your graphics drivers and DirectX are up to date."); + } + + device = dev; + swapchain = sc; + + + var factory = swapchain.GetParent(); //ignore windows events... + factory.MakeWindowAssociation(form.Form.Handle, WindowAssociationFlags.IgnoreAll); + + + + context = device.ImmediateContext; + + + + CreateRenderBuffers(); + + + + dxform.Form.Load += Dxform_Load; + dxform.Form.FormClosing += Dxform_FormClosing; + dxform.Form.ClientSizeChanged += Dxform_ClientSizeChanged; + dxform.Form.ResizeBegin += DxForm_ResizeBegin; + dxform.Form.ResizeEnd += DxForm_ResizeEnd; + + if (autostart) + { + dxform.InitScene(device); + } + + return true; + } + catch (Exception ex) + { + MessageBox.Show("Unable to initialise DirectX11.\n" + ex.ToString()); + return false; + } + } + + + private void Cleanup() + { + Running = false; + int count = 0; + while (Rendering && (count < 1000)) + { + Thread.Sleep(1); //try to gracefully exit... + count++; + } + + dxform.CleanupScene(); + + //dipose of all objects + if (depthview != null) depthview.Dispose(); + if (depthbuffer != null) depthbuffer.Dispose(); + if (targetview != null) targetview.Dispose(); + if (backbuffer != null) backbuffer.Dispose(); + if (swapchain != null) swapchain.Dispose(); + if (device != null) device.Dispose(); + + GC.Collect(); + } + private void CreateRenderBuffers() + { + if (targetview != null) targetview.Dispose(); + if (backbuffer != null) backbuffer.Dispose(); + if (depthview != null) depthview.Dispose(); + if (depthbuffer != null) depthbuffer.Dispose(); + + + backbuffer = Texture2D.FromSwapChain(swapchain, 0); + targetview = new RenderTargetView(device, backbuffer); + + depthbuffer = new Texture2D(device, new Texture2DDescription() + { + Format = Format.D32_Float, + ArraySize = 1, + MipLevels = 1, + Width = backbuffer.Description.Width, + Height = backbuffer.Description.Height, + SampleDescription = new SampleDescription(multisamplecount, 0), + Usage = ResourceUsage.Default, + BindFlags = BindFlags.DepthStencil, + CpuAccessFlags = CpuAccessFlags.None, + OptionFlags = ResourceOptionFlags.None + }); + + depthview = new DepthStencilView(device, depthbuffer); + + Viewport.Width = (float)backbuffer.Description.Width; + Viewport.Height = (float)backbuffer.Description.Height; + Viewport.MinDepth = 0.0f; + Viewport.MaxDepth = 1.0f; + Viewport.X = 0; + Viewport.Y = 0; + } + private void Resize() + { + if (Resizing) return; + Monitor.Enter(syncroot); + + int width = dxform.Form.ClientSize.Width; + int height = dxform.Form.ClientSize.Height; + + if (targetview != null) targetview.Dispose(); + if (backbuffer != null) backbuffer.Dispose(); + + swapchain.ResizeBuffers(1, width, height, Format.Unknown, SwapChainFlags.AllowModeSwitch); + + CreateRenderBuffers(); + + Monitor.Exit(syncroot); + + dxform.BuffersResized(width, height); + } + + private void Dxform_Load(object sender, EventArgs e) + { + if (autoStartLoop) + { + StartRenderLoop(); + } + } + private void Dxform_FormClosing(object sender, FormClosingEventArgs e) + { + Cleanup(); + } + private void Dxform_ClientSizeChanged(object sender, EventArgs e) + { + Resize(); + } + private void DxForm_ResizeBegin(object sender, EventArgs e) + { + beginSize = dxform.Form.ClientSize; + Resizing = true; + } + private void DxForm_ResizeEnd(object sender, EventArgs e) + { + Resizing = false; + if (dxform.Form.ClientSize != beginSize) + { + Resize(); + } + } + + + public void Start() + { + dxform.InitScene(device); + StartRenderLoop(); + } + private void StartRenderLoop() + { + Running = true; + new Thread(new ThreadStart(RenderLoop)).Start(); + } + private void RenderLoop() + { + while (Running) + { + while (Resizing) + { + swapchain.Present(1, PresentFlags.None); //just flip buffers when resizing; don't draw + } + while (dxform.Form.WindowState == FormWindowState.Minimized) + { + Thread.Sleep(10); //don't hog CPU when minimised + if (dxform.Form.IsDisposed) return; //if closed while minimised + } + + Rendering = true; + if(!Monitor.TryEnter(syncroot, 50)) + { + Thread.Sleep(10); //don't hog CPU when not able to render... + continue; + } + + bool ok = true; + try + { + context.OutputMerger.SetRenderTargets(depthview, targetview); + context.Rasterizer.SetViewport(0, 0, dxform.Form.ClientSize.Width, dxform.Form.ClientSize.Height); + } + catch (Exception ex) + { + MessageBox.Show("Error setting main render target!\n" + ex.ToString()); + ok = false; + } + + if (ok) + { + if (dxform.Form.IsDisposed) + { + Monitor.Exit(syncroot); + Rendering = false; + return; //the form was closed... stop!! + } + + dxform.RenderScene(context); + + try + { + swapchain.Present(1, PresentFlags.None); + } + catch (Exception ex) + { + MessageBox.Show("Error presenting swap chain!\n" + ex.ToString()); + } + } + + Monitor.Exit(syncroot); + Rendering = false; + + } + } + + + public void ClearRenderTarget(DeviceContext ctx) + { + ctx.ClearRenderTargetView(targetview, clearcolour); + ctx.ClearDepthStencilView(depthview, DepthStencilClearFlags.Depth, 1.0f, 0); + } + public void ClearDepth(DeviceContext ctx) + { + ctx.ClearDepthStencilView(depthview, DepthStencilClearFlags.Depth, 1.0f, 0); + } + public void SetDefaultRenderTarget(DeviceContext ctx) + { + ctx.OutputMerger.SetRenderTargets(depthview, targetview); + ctx.Rasterizer.SetViewport(Viewport); + //ctx.Rasterizer.State = RasterizerStateSolid; + } + + + + + + } +} diff --git a/Rendering/DirectX/DXUtility.cs b/Rendering/DirectX/DXUtility.cs new file mode 100644 index 0000000..0b4dec7 --- /dev/null +++ b/Rendering/DirectX/DXUtility.cs @@ -0,0 +1,463 @@ +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using Resource = SharpDX.Direct3D11.Resource; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX.Mathematics.Interop; +using SharpDX.Direct3D; + +namespace CodeWalker.Rendering +{ + public static class DXUtility + { + + public static Buffer CreateBuffer(Device device, int size, ResourceUsage usage, BindFlags bindFlags, CpuAccessFlags cpuAccessFlags, ResourceOptionFlags miscFlags, int structByteStride) + { + BufferDescription desc = new BufferDescription(); + desc.SizeInBytes = size; + desc.Usage = usage; + desc.BindFlags = bindFlags; + desc.CpuAccessFlags = cpuAccessFlags; + desc.OptionFlags = miscFlags; + desc.StructureByteStride = structByteStride; + + Buffer b = new Buffer(device, desc); + + //D3D11_SUBRESOURCE_DATA srd; + //srd.pSysMem = data; + //ComPtr b; + + //Try(DXManager::GetDevice()->CreateBuffer(&desc, data != nullptr? &srd : nullptr, &b), name); + //DXManager::AddVramUsage(size); + return b; + } + + + public static Texture2D CreateTexture2D(Device device, int width, int height, int mipLevels, int arraySize, Format format, int sampleCount, int sampleQuality, ResourceUsage usage, BindFlags bindFlags, CpuAccessFlags cpuAccessFlags, ResourceOptionFlags miscFlags) + { + Texture2DDescription td = new Texture2DDescription(); + td.Width = width; + td.Height = height; + td.MipLevels = mipLevels; + td.ArraySize = arraySize; + td.Format = format; + td.SampleDescription = new SampleDescription(sampleCount, sampleQuality); + td.Usage = usage; + td.BindFlags = bindFlags; + td.CpuAccessFlags = cpuAccessFlags; + td.OptionFlags = miscFlags; + Texture2D t = new Texture2D(device, td); + return t; + } + //static ComPtr CreateTexture2D(UINT width, UINT height, UINT mipLevels, UINT arraySize, DXGI_FORMAT format, UINT sampleCount, UINT sampleQuality, D3D11_USAGE usage, UINT bindFlags, UINT cpuAccessFlags, UINT miscFlags, const void* data, const string& name) + //{ + // D3D11_TEXTURE2D_DESC td; + // td.Width = width; + // td.Height = height; + // td.MipLevels = mipLevels; + // td.ArraySize = arraySize; + // td.Format = format; + // td.SampleDesc.Count = sampleCount; + // td.SampleDesc.Quality = sampleQuality; + // td.Usage = usage; + // td.BindFlags = bindFlags; + // td.CPUAccessFlags = cpuAccessFlags; + // td.MiscFlags = miscFlags; + // D3D11_SUBRESOURCE_DATA srd; + // srd.pSysMem = data; + // srd.SysMemPitch = 1; + // srd.SysMemSlicePitch = 0; + // ComPtr t; + // Try(DXManager::GetDevice()->CreateTexture2D(&td, data != nullptr ? &srd : nullptr, &t), name); + // DXManager::AddVramUsage(ElementSize(format) * width * height * arraySize); + // return t; + //} + + + public static SamplerState CreateSamplerState(Device device, TextureAddressMode addressU, TextureAddressMode addressV, TextureAddressMode addressW, RawColor4 border, Comparison comparisonFunc, Filter filter, int maxAnisotropy, float maxLOD, float minLOD, float mipLODBias) + { + SamplerStateDescription smpDesc = new SamplerStateDescription(); + smpDesc.AddressU = addressU; + smpDesc.AddressV = addressV; + smpDesc.AddressW = addressW; + smpDesc.BorderColor = border; + smpDesc.ComparisonFunction = comparisonFunc; + smpDesc.Filter = filter; + smpDesc.MaximumAnisotropy = maxAnisotropy; + smpDesc.MaximumLod = maxLOD; + smpDesc.MinimumLod = minLOD; + smpDesc.MipLodBias = mipLODBias; + SamplerState smp = new SamplerState(device, smpDesc); + return smp; + } + public static SamplerState CreateSamplerState(Device device, TextureAddressMode address, RawColor4 border, Comparison comparisonFunc, Filter filter, int maxAnisotropy, float maxLOD, float minLOD, float mipLODBias) + { + return CreateSamplerState(device, address, address, address, border, comparisonFunc, filter, maxAnisotropy, maxLOD, minLOD, mipLODBias); + } + + public static ShaderResourceView CreateShaderResourceView(Device device, Resource resource, Format format, ShaderResourceViewDimension viewDimension, int mipLevels, int mostDetailedMip, int arraySize, int firstArraySlice) + { + ShaderResourceViewDescription srvd = new ShaderResourceViewDescription(); + srvd.Format = format; + srvd.Dimension = viewDimension; + switch (viewDimension) + { + case ShaderResourceViewDimension.Buffer:// D3D11_SRV_DIMENSION_BUFFER: + srvd.Buffer.ElementOffset = mipLevels; + srvd.Buffer.ElementWidth = ElementSize(format); + srvd.Buffer.ElementCount = arraySize; + srvd.Buffer.FirstElement = firstArraySlice; + break; + case ShaderResourceViewDimension.Texture2D:// D3D11_SRV_DIMENSION_TEXTURE2D: + srvd.Texture2D.MipLevels = mipLevels; + srvd.Texture2D.MostDetailedMip = mostDetailedMip; + break; + case ShaderResourceViewDimension.Texture2DArray:// D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + srvd.Texture2DArray.MipLevels = mipLevels; + srvd.Texture2DArray.MostDetailedMip = mostDetailedMip; + srvd.Texture2DArray.ArraySize = arraySize; + srvd.Texture2DArray.FirstArraySlice = firstArraySlice; + break; + case ShaderResourceViewDimension.TextureCube:// D3D11_SRV_DIMENSION_TEXTURECUBE: + srvd.TextureCube.MipLevels = mipLevels; + srvd.TextureCube.MostDetailedMip = mostDetailedMip; + break; + case ShaderResourceViewDimension.Texture3D:// D3D11_SRV_DIMENSION_TEXTURE3D: + srvd.Texture3D.MipLevels = mipLevels; + srvd.Texture3D.MostDetailedMip = mostDetailedMip; + break; + default: + throw new Exception(); //not implemented.... + } + ShaderResourceView srv = new ShaderResourceView(device, resource, srvd); + return srv; + } + + public static UnorderedAccessView CreateUnorderedAccessView(Device device, Resource resource, Format format, UnorderedAccessViewDimension viewDimension, int firstElement, int numElements, UnorderedAccessViewBufferFlags flags, int mipSlice) + { + UnorderedAccessViewDescription uavd = new UnorderedAccessViewDescription(); + uavd.Format = format; + uavd.Dimension = viewDimension; + + switch(viewDimension) + { + case UnorderedAccessViewDimension.Texture1D: + uavd.Texture1D.MipSlice = mipSlice; + break; + case UnorderedAccessViewDimension.Texture1DArray: + uavd.Texture1DArray.MipSlice = mipSlice; + uavd.Texture1DArray.ArraySize = numElements; + uavd.Texture1DArray.FirstArraySlice = firstElement; + break; + case UnorderedAccessViewDimension.Texture2D: + uavd.Texture2D.MipSlice = mipSlice; + break; + case UnorderedAccessViewDimension.Texture2DArray: + uavd.Texture2DArray.MipSlice = mipSlice; + uavd.Texture2DArray.ArraySize = numElements; + uavd.Texture2DArray.FirstArraySlice = firstElement; + break; + case UnorderedAccessViewDimension.Texture3D: + uavd.Texture3D.MipSlice = mipSlice; + uavd.Texture3D.WSize = numElements; + uavd.Texture3D.FirstWSlice = firstElement; + break; + case UnorderedAccessViewDimension.Buffer: + uavd.Buffer.ElementCount = numElements; + uavd.Buffer.FirstElement = firstElement; + uavd.Buffer.Flags = flags; + break; + case UnorderedAccessViewDimension.Unknown: + default: + return null; + } + var uav = new UnorderedAccessView(device, resource, uavd); + return uav; + } + + + public static RenderTargetView CreateRenderTargetView(Device device, Resource renderTarget, Format format, RenderTargetViewDimension viewDimension, int mipSlice, int arraySize, int firstArraySlice) + { + RenderTargetView rtv; + RenderTargetViewDescription rtvd = new RenderTargetViewDescription(); + rtvd.Format = format; + rtvd.Dimension = viewDimension; + switch(viewDimension) + { + case RenderTargetViewDimension.Buffer:// D3D11_RTV_DIMENSION_BUFFER: + rtvd.Buffer.ElementOffset = mipSlice; + rtvd.Buffer.ElementWidth = arraySize* ElementSize(format);// arraySize; //assume square buffer... is this the width? + rtvd.Buffer.FirstElement = 0*ElementSize(format);//firstArraySlice; + rtvd.Buffer.ElementCount = arraySize;//*arraySize*ElementSize(format); //does this represent the height?? + break; + case RenderTargetViewDimension.Texture2D:// D3D11_RTV_DIMENSION_TEXTURE2D: + rtvd.Texture2D.MipSlice = mipSlice; + break; + case RenderTargetViewDimension.Texture2DArray:// D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + rtvd.Texture2DArray.MipSlice = mipSlice; + rtvd.Texture2DArray.ArraySize = arraySize; + rtvd.Texture2DArray.FirstArraySlice = firstArraySlice; + break; + case RenderTargetViewDimension.Texture2DMultisampled:// D3D11_RTV_DIMENSION_TEXTURE2DMS: + break; + case RenderTargetViewDimension.Texture2DMultisampledArray:// D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + rtvd.Texture2DMSArray.ArraySize = arraySize; + rtvd.Texture2DMSArray.FirstArraySlice = firstArraySlice; + break; + case RenderTargetViewDimension.Texture3D:// D3D11_RTV_DIMENSION_TEXTURE3D: + rtvd.Texture3D.MipSlice = mipSlice; + rtvd.Texture3D.DepthSliceCount = arraySize; + rtvd.Texture3D.FirstDepthSlice = firstArraySlice; + break; + } + rtv = new RenderTargetView(device, renderTarget, rtvd); + return rtv; + } + + + public static DepthStencilView CreateDepthStencilView(Device device, Texture2D depthStencil, Format format, DepthStencilViewDimension viewDimension) + { + DepthStencilViewDescription dsvd = new DepthStencilViewDescription(); + dsvd.Format = format; + dsvd.Flags = 0; + dsvd.Dimension = viewDimension; + dsvd.Texture2D.MipSlice = 0; + DepthStencilView dsv = new DepthStencilView(device, depthStencil, dsvd); + return dsv; + } + public static DepthStencilView CreateDepthStencilView(Device device, Texture2D depthStencil, Format format, int arraySlice) + { + DepthStencilViewDescription dsvd = new DepthStencilViewDescription(); + dsvd.Format = format; + dsvd.Flags = 0; + dsvd.Dimension = DepthStencilViewDimension.Texture2DArray;// D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvd.Texture2DArray.ArraySize = 1; + dsvd.Texture2DArray.FirstArraySlice = arraySlice; + dsvd.Texture2DArray.MipSlice = 0; + DepthStencilView dsv = new DepthStencilView(device, depthStencil, dsvd); + return dsv; + } + + + public static DepthStencilState CreateDepthStencilState(Device device, bool depthEnable, DepthWriteMask writeMask, Comparison func, bool stencilEnable, byte stencilReadMask, byte stencilWriteMask, DepthStencilOperationDescription frontFace, DepthStencilOperationDescription backFace) + { + DepthStencilStateDescription dsd; + dsd.IsDepthEnabled = depthEnable; + dsd.DepthWriteMask = writeMask; + dsd.DepthComparison = func; + dsd.IsStencilEnabled = stencilEnable; + dsd.StencilReadMask = stencilReadMask; + dsd.StencilWriteMask = stencilWriteMask; + dsd.FrontFace = frontFace; + dsd.BackFace = backFace; + DepthStencilState s = new DepthStencilState(device, dsd); + return s; + } + public static DepthStencilState CreateDepthStencilState(Device device, bool depthEnable, DepthWriteMask writeMask) + { + DepthStencilOperationDescription frontFace = new DepthStencilOperationDescription(); + DepthStencilOperationDescription backFace = new DepthStencilOperationDescription(); + bool stencil = false;//depthEnable; + byte rm = 0; + byte wm = 0; + if (stencil) + { + rm = 0xFF; + wm = 0xFF; + // Stencil operations if pixel is front-facing + frontFace.FailOperation = StencilOperation.Keep;// D3D11_STENCIL_OP_KEEP; + frontFace.DepthFailOperation = StencilOperation.Increment;// D3D11_STENCIL_OP_INCR; + frontFace.PassOperation = StencilOperation.Keep;// D3D11_STENCIL_OP_KEEP; + frontFace.Comparison = Comparison.Always;// D3D11_COMPARISON_ALWAYS; + + // Stencil operations if pixel is back-facing + backFace.FailOperation = StencilOperation.Keep;// D3D11_STENCIL_OP_KEEP; + backFace.DepthFailOperation = StencilOperation.Decrement;// D3D11_STENCIL_OP_DECR; + backFace.PassOperation = StencilOperation.Keep;// D3D11_STENCIL_OP_KEEP; + backFace.Comparison = Comparison.Always;// D3D11_COMPARISON_ALWAYS; + } + + return CreateDepthStencilState(device, depthEnable, writeMask, Comparison.LessEqual, stencil, rm, wm, frontFace, backFace); + } + + + public static RasterizerState CreateRasterizerState(Device device, FillMode fillMode, CullMode cullMode, bool depthClipEnable, bool scissorEnable, bool multisampleEnable, int depthBias, float depthBiasClamp, float slopeScaledDepthBias) + { + RasterizerStateDescription drd = new RasterizerStateDescription(); + drd.FillMode = fillMode; //D3D11_FILL_MODE FillMode; + drd.CullMode = cullMode;//D3D11_CULL_MODE CullMode; + drd.IsFrontCounterClockwise = false; //BOOL FrontCounterClockwise; + drd.DepthBias = depthBias; //INT DepthBias; + drd.DepthBiasClamp = depthBiasClamp;//FLOAT DepthBiasClamp; + drd.SlopeScaledDepthBias = slopeScaledDepthBias;//FLOAT SlopeScaledDepthBias; + drd.IsDepthClipEnabled = depthClipEnable;//BOOL DepthClipEnable; + drd.IsScissorEnabled = scissorEnable;//BOOL ScissorEnable; + drd.IsMultisampleEnabled = multisampleEnable;//BOOL MultisampleEnable; + drd.IsAntialiasedLineEnabled = false;//BOOL AntialiasedLineEnable; + RasterizerState rs = new RasterizerState(device, drd); + return rs; + } + public static RasterizerState CreateRasterizerState(Device device, FillMode fillMode, CullMode cullMode, bool depthClipEnable, bool scissorEnable, bool multisampleEnable) + { + return CreateRasterizerState(device, fillMode, cullMode, depthClipEnable, scissorEnable, multisampleEnable, 0, 0.0f, 0.0f); + } + public static RasterizerState CreateRasterizerState(Device device, FillMode fillMode, CullMode cullMode, bool depthClipEnable, bool multisampleEnable) + { + return CreateRasterizerState(device, fillMode, cullMode, depthClipEnable, false, multisampleEnable); + } + public static RasterizerState CreateRasterizerState(Device device, bool depthClipEnable, bool multisampleEnable) + { + return CreateRasterizerState(device, FillMode.Solid, CullMode.Back, depthClipEnable, false, multisampleEnable); + } + + public static BlendState CreateBlendState(Device device, bool blendEnable, BlendOperation op, BlendOption src, BlendOption dst, BlendOperation opAlpha, BlendOption srcAlpha, BlendOption dstAlpha, ColorWriteMaskFlags writeMask) + { + BlendStateDescription bsd = new BlendStateDescription(); + //ZeroMemory(&bsd, sizeof(bsd)); + bsd.RenderTarget[0].IsBlendEnabled = blendEnable; + bsd.RenderTarget[0].BlendOperation = op; + bsd.RenderTarget[0].SourceBlend = src; + bsd.RenderTarget[0].DestinationBlend = dst; + bsd.RenderTarget[0].AlphaBlendOperation = opAlpha; + bsd.RenderTarget[0].SourceAlphaBlend = srcAlpha; + bsd.RenderTarget[0].DestinationAlphaBlend = dstAlpha; + bsd.RenderTarget[0].RenderTargetWriteMask = writeMask; + BlendState bs = new BlendState(device, bsd); + return bs; + } + + + public static int ElementSize(Format format) + { + //FormatHelper.SizeOfInBytes? + switch (format) + { + case Format.R32G32B32A32_Typeless: + case Format.R32G32B32A32_Float: + case Format.R32G32B32A32_UInt: + case Format.R32G32B32A32_SInt: + return 16; + + case Format.R32G32B32_Typeless: + case Format.R32G32B32_Float: + case Format.R32G32B32_UInt: + case Format.R32G32B32_SInt: + return 12; + + case Format.R16G16B16A16_Typeless: + case Format.R16G16B16A16_Float: + case Format.R16G16B16A16_UNorm: + case Format.R16G16B16A16_UInt: + case Format.R16G16B16A16_SNorm: + case Format.R16G16B16A16_SInt: + case Format.R32G32_Typeless: + case Format.R32G32_Float: + case Format.R32G32_UInt: + case Format.R32G32_SInt: + case Format.R32G8X24_Typeless: + case Format.D32_Float_S8X24_UInt: + case Format.R32_Float_X8X24_Typeless: + case Format.X32_Typeless_G8X24_UInt: + return 8; + + case Format.R10G10B10A2_Typeless: + case Format.R10G10B10A2_UNorm: + case Format.R10G10B10A2_UInt: + case Format.R11G11B10_Float: + case Format.R8G8B8A8_Typeless: + case Format.R8G8B8A8_UNorm: + case Format.R8G8B8A8_UNorm_SRgb: + case Format.R8G8B8A8_UInt: + case Format.R8G8B8A8_SNorm: + case Format.R8G8B8A8_SInt: + case Format.R16G16_Typeless: + case Format.R16G16_Float: + case Format.R16G16_UNorm: + case Format.R16G16_UInt: + case Format.R16G16_SNorm: + case Format.R16G16_SInt: + case Format.R32_Typeless: + case Format.D32_Float: + case Format.R32_Float: + case Format.R32_UInt: + case Format.R32_SInt: + case Format.R24G8_Typeless: + case Format.D24_UNorm_S8_UInt: + case Format.R24_UNorm_X8_Typeless: + case Format.X24_Typeless_G8_UInt: + case Format.B8G8R8A8_UNorm: + case Format.B8G8R8X8_UNorm: + return 4; + + case Format.R8G8_Typeless: + case Format.R8G8_UNorm: + case Format.R8G8_UInt: + case Format.R8G8_SNorm: + case Format.R8G8_SInt: + case Format.R16_Typeless: + case Format.R16_Float: + case Format.D16_UNorm: + case Format.R16_UNorm: + case Format.R16_UInt: + case Format.R16_SNorm: + case Format.R16_SInt: + case Format.B5G6R5_UNorm: + case Format.B5G5R5A1_UNorm: + return 2; + + case Format.R8_Typeless: + case Format.R8_UNorm: + case Format.R8_UInt: + case Format.R8_SNorm: + case Format.R8_SInt: + case Format.A8_UNorm: + return 1; + + // Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx + case Format.BC2_Typeless: + case Format.BC2_UNorm: + case Format.BC2_UNorm_SRgb: + case Format.BC3_Typeless: + case Format.BC3_UNorm: + case Format.BC3_UNorm_SRgb: + case Format.BC5_Typeless: + case Format.BC5_UNorm: + case Format.BC5_SNorm: + return 16; + + // Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx + case Format.R1_UNorm: + case Format.BC1_Typeless: + case Format.BC1_UNorm: + case Format.BC1_UNorm_SRgb: + case Format.BC4_Typeless: + case Format.BC4_UNorm: + case Format.BC4_SNorm: + return 8; + + // Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx + case Format.R9G9B9E5_Sharedexp: + return 4; + + // These are compressed, but bit-size information is unclear. + case Format.R8G8_B8G8_UNorm: + case Format.G8R8_G8B8_UNorm: + return 4; + + case Format.Unknown: + default: + return 0; + } + } + + + + + } +} diff --git a/Rendering/Renderable.cs b/Rendering/Renderable.cs new file mode 100644 index 0000000..e1e32c2 --- /dev/null +++ b/Rendering/Renderable.cs @@ -0,0 +1,1642 @@ +using CodeWalker.GameFiles; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using CodeWalker.World; +using SharpDX.Direct3D; +using SharpDX; + +namespace CodeWalker.Rendering +{ + public struct RenderableInst + { + public Renderable Renderable; + public Vector3 CamRel; + public Vector3 Position; + public Vector3 BBMin; + public Vector3 BBMax; + public Vector3 BSCenter; + public float Radius; + public float Distance; + public Quaternion Orientation; + public Vector3 Scale; + public uint TintPaletteIndex; + } + public struct RenderableGeometryInst + { + public RenderableGeometry Geom; + public RenderableInst Inst; + } + + public struct RenderableBoundCompositeInst + { + public RenderableBoundComposite Renderable; + public Vector3 CamRel; + public Vector3 Position; + public Quaternion Orientation; + public Vector3 Scale; + } + public struct RenderableBoundGeometryInst + { + public RenderableBoundGeometry Geom; + public RenderableBoundCompositeInst Inst; + } + + public struct RenderableInstanceBatchInst + { + public RenderableInstanceBatch Batch; + public Renderable Renderable; + } + + + public class Renderable : RenderableCacheItem + { + public bool AllTexturesLoaded = false; + + public RenderableModel[] HDModels; + public RenderableModel[] AllModels; + //public Dictionary TextureDict { get; private set; } + //public long EmbeddedTextureSize { get; private set; } + + public bool HasSkeleton; + public bool HasTransforms; + + + public override void Init(DrawableBase drawable) + { + Key = drawable; + + DataSize = 0; + + var hd = Key.DrawableModelsHigh.data_items; + var med = Key.DrawableModelsMedium?.data_items; + var low = Key.DrawableModelsLow?.data_items; + var vlow = Key.DrawableModelsVeryLow?.data_items; + int totmodels = hd.Length + ((med != null) ? med.Length : 0) + ((low != null) ? low.Length : 0) + ((vlow != null) ? vlow.Length : 0); + int curmodel = hd.Length; + AllModels = new RenderableModel[totmodels]; + HDModels = new RenderableModel[hd.Length]; + for (int i = 0; i < hd.Length; i++) + { + HDModels[i] = InitModel(hd[i]); + AllModels[i] = HDModels[i]; + } + if (med != null) + { + for (int i = 0; i < med.Length; i++) + { + AllModels[curmodel + i] = InitModel(med[i]); + } + curmodel += med.Length; + } + if (low != null) + { + for (int i = 0; i < low.Length; i++) + { + AllModels[curmodel + i] = InitModel(low[i]); + } + curmodel += low.Length; + } + if (vlow != null) + { + for (int i = 0; i < vlow.Length; i++) + { + AllModels[curmodel + i] = InitModel(vlow[i]); + } + curmodel += vlow.Length; + } + + + //var sg = Drawable.ShaderGroup; + //if ((sg != null) && (sg.TextureDictionary != null)) + //{ + // EmbeddedTextureSize = sg.TextureDictionary.MemoryUsage; + // TextureDict = sg.TextureDictionary.GetDictionary(); + //} + + + + + + bool hasskeleton = false; + bool hastransforms = false; + bool hasbones = false; + Skeleton skeleton = drawable.Skeleton; + Matrix[] modeltransforms = null; + List bones = null; + bool usepose = false; + if (skeleton != null) + { + hasskeleton = true; + modeltransforms = skeleton.Transformations; + + //for fragments, get the default pose from the root fragment... + var fd = drawable as FragDrawable; + if (fd != null) + { + var frag = fd.OwnerFragment; + var pose = frag?.Unknown_A8h_Data; + if ((pose != null) && (pose.Data != null)) //seems to be the default pose + { + var posebonecount = pose.Data.Length; + if ((modeltransforms == null))// || (modeltransforms.Length != posebonecount)) + { + modeltransforms = new Matrix[posebonecount]; + } + var modelbonecount = modeltransforms.Length; + var maxbonecount = Math.Min(posebonecount, modelbonecount); + for (int i = 0; i < maxbonecount; i++) + { + var p = pose.Data[i]; + Vector4 r1 = p.Row1; + Vector4 r2 = p.Row2; + Vector4 r3 = p.Row3; + modeltransforms[i] = new Matrix(r1.X, r2.X, r3.X, 0.0f, r1.Y, r2.Y, r3.Y, 0.0f, r1.Z, r2.Z, r3.Z, 0.0f, r1.W, r2.W, r3.W, 1.0f); + } + usepose = true; + } + } + + hastransforms = (modeltransforms != null); + hasbones = ((skeleton.Bones != null) && (skeleton.Bones.Data != null)); + bones = hasbones ? skeleton.Bones.Data : null; + } + + HasSkeleton = hasskeleton; + HasTransforms = hastransforms; + + + + //calculate transforms for the models if there are any. (TODO: move this to a method for re-use...) + for (int mi = 0; mi < AllModels.Length; mi++) + { + var model = AllModels[mi]; + + model.UseTransform = hastransforms; + if (hastransforms) + { + int boneidx = (int)((model.Unk28h >> 24) & 0xFF); + + Matrix trans = (boneidx < modeltransforms.Length) ? modeltransforms[boneidx] : Matrix.Identity; + Bone bone = (hasbones && (boneidx < bones.Count)) ? bones[boneidx] : null; + + if (!usepose) //when using the skeleton's matrices, they need to be transformed by parent + { + trans.Column4 = Vector4.UnitW; + ushort[] pinds = skeleton.ParentIndices; + ushort parentind = ((pinds != null) && (boneidx < pinds.Length)) ? pinds[boneidx] : (ushort)65535; + while (parentind < pinds.Length) + { + Matrix ptrans = (parentind < modeltransforms.Length) ? modeltransforms[parentind] : Matrix.Identity; + ptrans.Column4 = Vector4.UnitW; + trans = Matrix.Multiply(ptrans, trans); + parentind = ((pinds != null) && (parentind < pinds.Length)) ? pinds[parentind] : (ushort)65535; + } + } + + model.Transform = trans; + } + } + } + + private RenderableModel InitModel(DrawableModel dm) + { + var rmodel = new RenderableModel(); + rmodel.Owner = this; + rmodel.Init(dm); + DataSize += rmodel.GeometrySize; + return rmodel; + } + + public override void Load(Device device) + { + if (AllModels != null) + { + foreach (var model in AllModels) + { + if (model.Geometries == null) continue; + foreach (var geom in model.Geometries) + { + geom.Load(device); + } + } + } + //LastUseTime = DateTime.Now; //reset usage timer + IsLoaded = true; + } + + public override void Unload() + { + IsLoaded = false; + if (AllModels != null) + { + foreach (var model in AllModels) + { + if (model.Geometries == null) continue; + foreach (var geom in model.Geometries) + { + geom.Unload(); + } + } + } + LoadQueued = false; + } + + public override string ToString() + { + return Key.ToString(); + } + + } + + public class RenderableModel + { + public Renderable Owner; + public DrawableModel DrawableModel; + public RenderableGeometry[] Geometries; + public AABB_s[] GeometryBounds; + public long GeometrySize { get; private set; } + + public uint Unk4h; + public uint Unk14h; + public uint Unk28h; + public uint Unk2Ch; //flags....... + + public bool UseTransform; + public Matrix Transform; + + public void Init(DrawableModel dmodel) + { + Unk4h = dmodel.Unknown_4h; + Unk14h = dmodel.Unknown_14h; + Unk28h = dmodel.Unknown_28h; + Unk2Ch = dmodel.Unknown_2Ch; + + + DrawableModel = dmodel; + long geomcount = dmodel.Geometries.data_items.Length; + Geometries = new RenderableGeometry[geomcount]; + GeometryBounds = new AABB_s[geomcount]; + + GeometrySize = 0; + for (int i = 0; i < geomcount; i++) + { + var dgeom = dmodel.Geometries.data_items[i]; + var rgeom = new RenderableGeometry(); + rgeom.Init(dgeom); + rgeom.Owner = this; + Geometries[i] = rgeom; + GeometrySize += rgeom.TotalDataSize; + + if ((dmodel.Unknown_18h_Data != null) && (i < dmodel.Unknown_18h_Data.Length)) + { + GeometryBounds[i] = dmodel.Unknown_18h_Data[i]; + } + else + { + //GeometryBounds[i] = new AABB_s();//what to default to? + } + + if (Owner.Key is FragDrawable) + { + rgeom.IsFragment = true; + } + } + + + } + + } + + public class RenderableGeometry + { + public RenderableModel Owner; + public Buffer VertexBuffer { get; set; } + public Buffer IndexBuffer { get; set; } + public VertexBufferBinding VBBinding; + public DrawableGeometry DrawableGeom; + public VertexType VertexType { get; set; } + public int VertexStride { get; set; } + public int VertexCount { get; set; } + public int IndexCount { get; set; } + public uint VertexDataSize { get; set; } + public uint IndexDataSize { get; set; } + public uint TotalDataSize { get; set; } + public TextureBase[] Textures; + public RenderableTexture[] RenderableTextures; + public MetaName[] TextureParamHashes; + public PrimitiveTopology Topology { get; set; } + public bool IsFragment = false; + public bool IsEmissive { get; set; } = false; + public bool EnableWind { get; set; } = false; + public float HardAlphaBlend { get; set; } = 0.0f; + public float useTessellation { get; set; } = 0.0f; + public float wetnessMultiplier { get; set; } = 0.0f; + public float bumpiness { get; set; } = 1.0f; + public Vector4 detailSettings { get; set; } = Vector4.Zero; + public Vector3 specMapIntMask { get; set; } = Vector3.Zero; + public float specularIntensityMult { get; set; } = 0.0f; + public float specularFalloffMult { get; set; } = 0.0f; + public float specularFresnel { get; set; } = 0.0f; + public float RippleSpeed { get; set; } = 1.0f; + public float RippleScale { get; set; } = 1.0f; + public float RippleBumpiness { get; set; } = 1.0f; + public Vector4 WindGlobalParams { get; set; } = Vector4.Zero; + public Vector4 WindOverrideParams { get; set; } = Vector4.One; + public Vector4 globalAnimUV0 { get; set; } = Vector4.Zero; + public Vector4 globalAnimUV1 { get; set; } = Vector4.Zero; + public bool SpecOnly { get; set; } = false; + public float WaveOffset { get; set; } = 0; //for terrainfoam + public float WaterHeight { get; set; } = 0; //for terrainfoam + public float WaveMovement { get; set; } = 0; //for terrainfoam + public float HeightOpacity { get; set; } = 0; //for terrainfoam + + + public static MetaName[] GetTextureSamplerList() + { + return new MetaName[] + { + MetaName.DiffuseSampler, //base diffuse + MetaName.SpecSampler, //base specular + MetaName.BumpSampler, //base normal + MetaName.TintPaletteSampler, // _pal + MetaName.DetailSampler, // ENV_ + MetaName.FlowSampler, //river _flow + MetaName.FogSampler, //river _fog , water slod + MetaName.TextureSampler_layer0, //CS_RSN_SL_Road_0007 + MetaName.BumpSampler_layer0, //CS_RSN_SL_Road_0007_n + MetaName.heightMapSamplerLayer0, //nxg_cs_rsn_sl_road_0007_h + MetaName.TextureSampler_layer1, //IM_Road_009b + MetaName.BumpSampler_layer1, //IM_Road_010b_N + MetaName.heightMapSamplerLayer1, //nxg_im_road_010b_h + MetaName.TextureSampler_layer2, //IM_Concrete10 + MetaName.BumpSampler_layer2, //IM_Concrete13_N + MetaName.heightMapSamplerLayer2, //nxg_im_concrete13_h + MetaName.TextureSampler_layer3, //SC1_RSN_NS_ground_0009 + MetaName.BumpSampler_layer3, //sc1_rsn_ns_ground_0010_n + MetaName.heightMapSamplerLayer3, //nxg_sc1_rsn_ns_ground_0010_b_h + MetaName.lookupSampler, //TF_RSN_Msk_CS1_DesHill1, bh1_43_golf_blendmap_04_LOD + MetaName.heightSampler, //nxg_prop_tree_palm2_displ_l + MetaName.FoamSampler, //bj_beachfoam01_lod, CS_RSN_SL_RiverFoam_01_A_lodCS_RSN_SL_RiverFoam_01_A + MetaName.textureSamp, + MetaName.DiffuseSampler2, + MetaName.DiffuseHfSampler, + MetaName.ComboHeightSamplerFur01, + MetaName.ComboHeightSamplerFur23, + MetaName.ComboHeightSamplerFur45, + MetaName.ComboHeightSamplerFur67, + MetaName.StippleSampler, + MetaName.FurMaskSampler, + MetaName.EnvironmentSampler, + MetaName.distanceMapSampler, + MetaName.textureSamp, + }; + } + + public void Init(DrawableGeometry dgeom) + { + DrawableGeom = dgeom; + VertexType = dgeom.VertexData.VertexType; + VertexStride = dgeom.VertexStride; + VertexCount = dgeom.VerticesCount; + IndexCount = (int)dgeom.IndicesCount; + VertexDataSize = (uint)(VertexCount * VertexStride); + IndexDataSize = (uint)(IndexCount * 2); //ushort indices... + TotalDataSize = VertexDataSize + IndexDataSize; + Topology = PrimitiveTopology.TriangleList; + + var shader = DrawableGeom.Shader; + if ((shader != null) && (shader.ParametersList != null)) + { + if (shader.FileName == 3854885487)//{cable.sps} + { + Topology = PrimitiveTopology.LineList; + } + + + var shaderName = shader.Name; + var shaderFile = shader.FileName; + switch (shaderFile.Hash) + { + case 2245870123: //trees_normal_diffspec_tnt.sps + case 3334613197: //trees_tnt.sps + case 1229591973://{trees_normal_spec_tnt.sps} + case 2322653400://{trees.sps} + case 3192134330://{trees_normal.sps} + case 1224713457://{trees_normal_spec.sps} + case 4265705004://{trees_normal_diffspec.sps} + case 1581835696://{default_um.sps} + case 3326705511://{normal_um.sps} + case 3085209681://{normal_spec_um.sps} + case 3190732435://{cutout_um.sps} + case 748520668://{normal_cutout_um.sps} + EnableWind = true; + break; + case 1332909972://{normal_spec_emissive.sps} + case 2072061694://{normal_spec_reflect_emissivenight.sps} + case 2635608835://{emissive.sps} + case 443538781://{emissive_clip.sps} + case 2049580179://{emissive_speclum.sps} + case 1193295596://{emissive_tnt.sps} + case 1434302180://{emissivenight.sps} + case 1897917258://{emissivenight_geomnightonly.sps} + case 140448747://{emissivestrong.sps} + case 1436689415://{normal_spec_reflect_emissivenight_alpha.sps} + case 179247185://{emissive_alpha.sps} + case 1314864030://{emissive_alpha_tnt.sps} + case 1478174766://{emissive_additive_alpha.sps} + case 3733846327://{emissivenight_alpha.sps} + case 3174327089://{emissivestrong_alpha.sps} + case 3924045432://{glass_emissive.sps} + case 837003310://{glass_emissivenight.sps} + case 485710087://{glass_emissivenight_alpha.sps} + case 2055615352://{glass_emissive_alpha.sps} + case 2918136469://{decal_emissive_only.sps} + case 2698880237://{decal_emissivenight_only.sps} + IsEmissive = true; + break; + case 3880384844://{decal_spec_only.sps} + case 341123999://{decal_normal_only.sps} + case 600733812://{decal_amb_only.sps} + SpecOnly = true; //this needs more work. + break; + } + + + + var pl = shader.ParametersList.Parameters; + var hl = shader.ParametersList.Hashes; + List texs = new List(); + List phashes = new List(); + if ((pl != null) && (hl != null)) + { + for (int i = 0; (i < pl.Length) && (i < hl.Length); i++) + { + var param = pl[i]; + if (param.Data is TextureBase) + { + texs.Add(param.Data as TextureBase); + phashes.Add(hl[i]); + } + + switch (hl[i]) + { + case MetaName.HardAlphaBlend: + HardAlphaBlend = ((Vector4)param.Data).X; + break; + case MetaName.useTessellation: + useTessellation = ((Vector4)param.Data).X; + break; + case MetaName.wetnessMultiplier: + wetnessMultiplier = ((Vector4)param.Data).X; + break; + case MetaName.bumpiness: //float + bumpiness = ((Vector4)param.Data).X; + break; + case MetaName.detailSettings: //float4 + detailSettings = (Vector4)param.Data; + break; + case MetaName.specMapIntMask: //float3 + specMapIntMask = ((Vector4)param.Data).XYZ(); + break; + case MetaName.specularIntensityMult: //float + specularIntensityMult = ((Vector4)param.Data).X; + break; + case MetaName.specularFalloffMult: //float + specularFalloffMult = ((Vector4)param.Data).X; + break; + case MetaName.specularFresnel: //float + specularFresnel= ((Vector4)param.Data).X; + break; + case MetaName.WindGlobalParams: + case MetaName.umGlobalOverrideParams: + //WindOverrideParams = ((Vector4)param.Data); //todo... + break; + case MetaName.umGlobalParams: + WindGlobalParams = ((Vector4)param.Data); + break; + case MetaName.RippleSpeed: + RippleSpeed = ((Vector4)param.Data).X; + break; + case MetaName.RippleScale: + RippleScale = ((Vector4)param.Data).X; + break; + case MetaName.RippleBumpiness: + RippleBumpiness = ((Vector4)param.Data).X; + break; + case MetaName.globalAnimUV0: + globalAnimUV0 = (Vector4)param.Data; + break; + case MetaName.globalAnimUV1: + globalAnimUV1 = (Vector4)param.Data; + break; + case MetaName.WaveOffset: + WaveOffset = ((Vector4)param.Data).X; + break; + case MetaName.WaterHeight: + WaterHeight = ((Vector4)param.Data).X; + break; + case MetaName.WaveMovement: + WaveMovement = ((Vector4)param.Data).X; + break; + case MetaName.HeightOpacity: + HeightOpacity = ((Vector4)param.Data).X; + break; + } + + } + } + if (texs.Count > 0) + { + TextureParamHashes = phashes.ToArray(); + Textures = texs.ToArray(); + RenderableTextures = new RenderableTexture[texs.Count]; //these will get populated at render time. + //Textures = new RenderableTexture[texs.Count]; + for (int i = 0; i < texs.Count; i++) + { + //RenderableTexture tex = new RenderableTexture(); + //tex.Init(texs[i]); + //Textures[i] = tex; + + + ////testing texture usage + //MetaName thash = phashes[i]; + //switch (thash) + //{ + // case MetaName.DiffuseSampler: //base diffuse + // case MetaName.SpecSampler: //base specular + // case MetaName.BumpSampler: //base normal + // case MetaName.TintPaletteSampler: // _pal + // case MetaName.DetailSampler: // ENV_ + // case MetaName.FlowSampler: //river _flow + // case MetaName.FogSampler: //river _fog , water slod + // case MetaName.TextureSampler_layer0: //CS_RSN_SL_Road_0007 + // case MetaName.BumpSampler_layer0: //CS_RSN_SL_Road_0007_n + // case MetaName.heightMapSamplerLayer0: //nxg_cs_rsn_sl_road_0007_h + // case MetaName.TextureSampler_layer1: //IM_Road_009b + // case MetaName.BumpSampler_layer1: //IM_Road_010b_N + // case MetaName.heightMapSamplerLayer1: //nxg_im_road_010b_h + // case MetaName.TextureSampler_layer2: //IM_Concrete10 + // case MetaName.BumpSampler_layer2: //IM_Concrete13_N + // case MetaName.heightMapSamplerLayer2: //nxg_im_concrete13_h + // case MetaName.TextureSampler_layer3: //SC1_RSN_NS_ground_0009 + // case MetaName.BumpSampler_layer3: //sc1_rsn_ns_ground_0010_n + // case MetaName.heightMapSamplerLayer3: //nxg_sc1_rsn_ns_ground_0010_b_h + // case MetaName.lookupSampler: //TF_RSN_Msk_CS1_DesHill1, bh1_43_golf_blendmap_04_LOD + // case MetaName.heightSampler: //nxg_prop_tree_palm2_displ_l + // case MetaName.FoamSampler: //bj_beachfoam01_lod, CS_RSN_SL_RiverFoam_01_A_lodCS_RSN_SL_RiverFoam_01_A + // case MetaName.textureSamp://cable... + // break; + // //not yet implemented: + // case MetaName.DiffuseSampler2: + // case MetaName.DiffuseHfSampler: + // case MetaName.ComboHeightSamplerFur01: + // case MetaName.ComboHeightSamplerFur23: + // case MetaName.ComboHeightSamplerFur45: + // case MetaName.ComboHeightSamplerFur67: + // case MetaName.StippleSampler: + // case MetaName.FurMaskSampler: + // case MetaName.EnvironmentSampler: + // case MetaName.distanceMapSampler: + // break; + // default: + // break; + //} + + } + } + } + + + } + + public void Load(Device device) + { + + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, DrawableGeom.VertexData.VertexBytes); + + //object v = DrawableGeom.VertexData.Vertices; + //switch (VertexType) + //{ + // case VertexType.Default: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypeDefault[]); + // break; //P,N,C,T + // case VertexType.DefaultEx: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypeDefaultEx[]); + // break; //P,N,C,T,Ext + // case VertexType.PNCCT: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCT[]); + // break; + // case VertexType.PNCCTTTT: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTTTT[]); + // break; + // case VertexType.PCCNCCTTX: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCCTTX[]); + // break; + // case VertexType.PCCNCCT: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCCT[]); + // break; + // case VertexType.PNCTTTX: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCTTTX[]); + // break; + // case VertexType.PNCTTTX_2: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCTTTX_2[]); + // break; + // case VertexType.PNCTTTX_3: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCTTTX_3[]); + // break; + // case VertexType.PNCTTX: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCTTX[]); + // break; + // case VertexType.PNCCTTX: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTTX[]); + // break; + // case VertexType.PNCCTTX_2: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTTX_2[]); + // break; + // case VertexType.PNCCTTTX: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTTTX[]); + // break; + // case VertexType.PCCNCCTX: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCCTX[]); + // break; + // case VertexType.PCCNCTX: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCTX[]); + // break; + // case VertexType.PCCNCT: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCT[]); + // break; + // case VertexType.PNCCTT: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTT[]); + // break; + // case VertexType.PNCCTX: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTX[]); + // break; + // case VertexType.PTT: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePTT[]); + // break; + // case VertexType.PNC: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNC[]); + // break; + // case VertexType.PCT: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCT[]); + // break; + // case VertexType.PT: + // VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePT[]); + // break; + // default: + // break; + //} + if (VertexBuffer != null) + { + VBBinding = new VertexBufferBinding(VertexBuffer, VertexStride, 0); + } + + if (DrawableGeom.IndexBuffer != null) + { + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, DrawableGeom.IndexBuffer.Indices); + } + else if (DrawableGeom.BoneIds != null) + { + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, DrawableGeom.BoneIds); + } + + } + + public void Unload() + { + if (VertexBuffer != null) + { + VBBinding.Buffer = null; + VertexBuffer.Dispose(); + VertexBuffer = null; + } + if (IndexBuffer != null) + { + IndexBuffer.Dispose(); + IndexBuffer = null; + } + //DrawableGeom = null; + + if (RenderableTextures != null) + { + for (int i = 0; i < RenderableTextures.Length; i++) + { + RenderableTextures[i] = null; + } + RenderableTextures = null; + } + + } + + public void Render(DeviceContext context) + { + if ((VertexBuffer == null) || (IndexBuffer == null)) + { + return; + } + + context.InputAssembler.PrimitiveTopology = Topology; + context.InputAssembler.SetVertexBuffers(0, VBBinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R16_UInt, 0); + + context.DrawIndexed(IndexCount, 0, 0); + } + + public void RenderInstanced(DeviceContext context, int instCount) + { + if ((VertexBuffer == null) || (IndexBuffer == null)) + { + return; + } + + context.InputAssembler.PrimitiveTopology = Topology; + context.InputAssembler.SetVertexBuffers(0, VBBinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R16_UInt, 0); + + context.DrawIndexedInstanced(IndexCount, instCount, 0, 0, 0); + } + + } + + public class RenderableTexture : RenderableCacheItem + { + public uint Hash { get; private set; } + public string Name { get; private set; } + public Texture2D Texture2D { get; set; } + public ShaderResourceView ShaderResourceView { get; set; } + + + public override void Init(Texture tex) + { + Key = tex; + + if ((Key != null) && (Key.Data != null) && (Key.Data.FullData != null)) + { + DataSize = Key.Data.FullData.Length; + } + + } + + public override void Load(Device device) + { + if ((Key != null) && (Key.Data != null) && (Key.Data.FullData != null)) + { + using (var stream = DataStream.Create(Key.Data.FullData, true, false)) + { + + var format = TextureFormats.GetDXGIFormat(Key.Format); + var width = Key.Width; + var height = Key.Height; + int mips = Key.Levels; + int rowpitch, slicepitch; + var totlength = Key.Data.FullData.Length; + int pxsize = TextureFormats.ByteSize(Key.Format); // SharpDX.DXGI.FormatHelper.SizeOfInBytes(desc.Format); + + //get databoxes for mips + int offset = 0; + int level = 1; + List boxes = new List(); + for (int i = 0; i < mips; i++) + { + if (offset >= totlength) break; //only load as many mips as there are.. + + var mipw = width / level; + var miph = height / level; + + TextureFormats.ComputePitch(format, mipw, miph, out rowpitch, out slicepitch, 0); + var mipbox = new DataBox(stream.DataPointer + offset, rowpitch, slicepitch); + boxes.Add(mipbox); + + offset += slicepitch; + level *= 2; + } + mips = boxes.Count; + + + //single mip.. + //TextureFormats.ComputePitch(format, width, height, out rowpitch, out slicepitch, 0); + //var box = new DataBox(stream.DataPointer, rowpitch, slicepitch); + + + var desc = new Texture2DDescription() + { + ArraySize = 1, + BindFlags = BindFlags.ShaderResource, + CpuAccessFlags = CpuAccessFlags.None, + Format = format, + Height = Key.Height, + MipLevels = mips,//Texture.Levels, + OptionFlags = ResourceOptionFlags.None, + SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), + Usage = ResourceUsage.Default, + Width = Key.Width + }; + + + try + { + //Texture2D = new Texture2D(device, desc, new[] { box }); //single mip + Texture2D = new Texture2D(device, desc, boxes.ToArray()); //multiple mips + ShaderResourceView = new ShaderResourceView(device, Texture2D); + } + catch //(Exception ex) + { + //string str = ex.ToString(); //todo: don't fail silently.. + } + } + } + + + //LastUseTime = DateTime.Now; //reset usage timer + IsLoaded = true; + } + + public void SetVSResource(DeviceContext context, int slot) + { + context.VertexShader.SetShaderResource(slot, ShaderResourceView); + //LastUseTime = DateTime.Now; + } + public void SetPSResource(DeviceContext context, int slot) + { + context.PixelShader.SetShaderResource(slot, ShaderResourceView); + //LastUseTime = DateTime.Now; + } + + public override void Unload() + { + IsLoaded = false; + if (ShaderResourceView != null) + { + ShaderResourceView.Dispose(); + ShaderResourceView = null; + } + if (Texture2D != null) + { + Texture2D.Dispose(); + Texture2D = null; + } + LoadQueued = false; + } + + public override string ToString() + { + return (Key != null) ? Key.ToString() : base.ToString(); + } + } + + + public class RenderableInstanceBatch : RenderableCacheItem + { + public rage__fwGrassInstanceListDef__InstanceData[] GrassInstanceData { get; set; } + public GpuSBuffer GrassInstanceBuffer { get; set; } + public int InstanceCount { get; set; } + + public override void Init(YmapGrassInstanceBatch batch) + { + Key = batch; + if (batch.Instances == null) + { + return; + } + + InstanceCount = batch.Instances.Length; + + DataSize = (InstanceCount * 16); + + GrassInstanceData = batch.Instances; + + } + + public override void Load(Device device) + { + if ((GrassInstanceData != null) && (GrassInstanceData.Length > 0)) + { + GrassInstanceBuffer = new GpuSBuffer(device, GrassInstanceData); + } + //LastUseTime = DateTime.Now; //reset usage timer + IsLoaded = true; + } + + public override void Unload() + { + IsLoaded = false; + if (GrassInstanceBuffer != null) + { + GrassInstanceBuffer.Dispose(); + GrassInstanceBuffer = null; + } + LoadQueued = false; + } + } + + public class RenderableDistantLODLights : RenderableCacheItem + { + public struct DistLODLight + { + public Vector3 Position; + public uint Colour; + } + + private DistLODLight[] InstanceData { get; set; } + public GpuSBuffer InstanceBuffer { get; set; } + public int InstanceCount { get; set; } + public ushort Category { get; set; } + public ushort NumStreetLights { get; set; } + public RenderableTexture Texture { get; set; } + + public override void Init(YmapDistantLODLights key) + { + Key = key; + if ((key.positions == null) || (key.colours == null)) + { + return; + } + + InstanceCount = Math.Min(key.positions.Length, key.colours.Length); + + DataSize = InstanceCount * 16; + + InstanceData = new DistLODLight[InstanceCount]; + for (int i = 0; i < InstanceCount; i++) + { + InstanceData[i].Position = key.positions[i].ToVector3(); + InstanceData[i].Colour = key.colours[i]; + } + + Category = key.CDistantLODLight.category; + NumStreetLights = key.CDistantLODLight.numStreetLights; + + } + + public override void Load(Device device) + { + if ((InstanceData != null) && (InstanceData.Length > 0)) + { + InstanceBuffer = new GpuSBuffer(device, InstanceData); + } + //LastUseTime = DateTime.Now; //reset usage timer + IsLoaded = true; + } + + public override void Unload() + { + IsLoaded = false; + if (InstanceBuffer != null) + { + InstanceBuffer.Dispose(); + InstanceBuffer = null; + } + } + + } + + + public class RenderablePathBatch : RenderableCacheItem + { + public int VertexStride { get { return 16; } } + + public VertexTypePC[] PathVertices; + public int PathVertexCount { get; set; } + public Buffer PathVertexBuffer { get; set; } + public VertexBufferBinding PathVBBinding; + + public VertexTypePC[] TriangleVertices; + public int TriangleVertexCount { get; set; } + public Buffer TriangleVertexBuffer { get; set; } + public VertexBufferBinding TriangleVBBinding; + + public Vector4[] Nodes; + public GpuSBuffer NodeBuffer { get; set; } + + public override void Init(BasePathData key) + { + Key = key; + + DataSize = 0; + PathVertices = key.GetPathVertices(); + if (PathVertices != null) + { + PathVertexCount = PathVertices.Length; + DataSize = PathVertices.Length * VertexStride; + } + + TriangleVertices = key.GetTriangleVertices(); + if (TriangleVertices != null) + { + TriangleVertexCount = TriangleVertices.Length; + DataSize += TriangleVertices.Length * VertexStride; + } + + Nodes = key.GetNodePositions(); + if (Nodes != null) + { + DataSize += Nodes.Length * 16;//sizeof(Vector4) + } + + } + + public override void Load(Device device) + { + if ((PathVertices != null) && (PathVertices.Length > 0)) + { + PathVertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, PathVertices); + if (PathVertexBuffer != null) + { + PathVBBinding = new VertexBufferBinding(PathVertexBuffer, VertexStride, 0); + } + } + + if ((TriangleVertices != null) && (TriangleVertices.Length > 0)) + { + TriangleVertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, TriangleVertices); + if (TriangleVertexBuffer != null) + { + TriangleVBBinding = new VertexBufferBinding(TriangleVertexBuffer, VertexStride, 0); + } + } + + if ((Nodes != null) && (Nodes.Length > 0)) + { + NodeBuffer = new GpuSBuffer(device, Nodes); + } + + //LastUseTime = DateTime.Now; //reset usage timer + IsLoaded = true; + } + + public override void Unload() + { + IsLoaded = false; + if (PathVertexBuffer != null) + { + PathVBBinding.Buffer = null; + PathVertexBuffer.Dispose(); + PathVertexBuffer = null; + } + if (TriangleVertexBuffer != null) + { + TriangleVBBinding.Buffer = null; + TriangleVertexBuffer.Dispose(); + TriangleVertexBuffer = null; + } + if (NodeBuffer != null) + { + NodeBuffer.Dispose(); + NodeBuffer = null; + } + } + } + + + public class RenderableWaterQuad : RenderableCacheItem + { + public VertexTypePCT[] Vertices; + public uint[] Indices; + public int IndexCount { get; set; } + public int VertexCount { get; set; } + public int VertexStride { get; set; } = 24; + public Buffer VertexBuffer { get; set; } + public Buffer IndexBuffer { get; set; } + public VertexBufferBinding VBBinding; + public Vector3 CamRel { get; set; } //verts are in world space, so camrel should just be -campos + + public override void Init(WaterQuad key) + { + Key = key; + + float sx = key.maxX - key.minX; + float sy = key.maxY - key.minY; + + VertexCount = 4; + Vertices = new VertexTypePCT[4]; + Vertices[0].Position = new Vector3(key.minX, key.minY, key.z); + Vertices[0].Texcoord = new Vector2(0.0f, 0.0f); + Vertices[0].Colour = (uint)new Color4(key.a1 / 255.0f).ToRgba(); + Vertices[1].Position = new Vector3(key.maxX, key.minY, key.z); + Vertices[1].Texcoord = new Vector2(sx, 0.0f); + Vertices[1].Colour = (uint)new Color4(key.a2 / 255.0f).ToRgba(); + Vertices[2].Position = new Vector3(key.minX, key.maxY, key.z); + Vertices[2].Texcoord = new Vector2(0.0f, sy); + Vertices[2].Colour = (uint)new Color4(key.a3 / 255.0f).ToRgba(); + Vertices[3].Position = new Vector3(key.maxX, key.maxY, key.z); + Vertices[3].Texcoord = new Vector2(sx, sy); + Vertices[3].Colour = (uint)new Color4(key.a4 / 255.0f).ToRgba(); + + if (key.Type == 0) + { + IndexCount = 6; + Indices = new uint[6]; + Indices[0] = 0; + Indices[1] = 2; + Indices[2] = 1; + Indices[3] = 1; + Indices[4] = 2; + Indices[5] = 3; + } + else + { + IndexCount = 3; + Indices = new uint[3]; + switch (key.Type) + { + case 1: + Indices[0] = 0; + Indices[1] = 1; + Indices[2] = 2; + break; + case 2: + Indices[0] = 0; + Indices[1] = 3; + Indices[2] = 2; + break; + case 3: + Indices[0] = 1; + Indices[1] = 3; + Indices[2] = 2; + break; + case 4: + Indices[0] = 0; + Indices[1] = 1; + Indices[2] = 3; + break; + default: + break;//shouldn't ever get here... + } + } + + DataSize = VertexCount * VertexStride + IndexCount * 4; + } + + public override void Load(Device device) + { + if ((Vertices != null) && (Vertices.Length > 0)) + { + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, Vertices); + if (VertexBuffer != null) + { + VBBinding = new VertexBufferBinding(VertexBuffer, VertexStride, 0); + } + } + if ((Indices != null) && (Indices.Length > 0)) + { + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, Indices); + } + //LastUseTime = DateTime.Now; //reset usage timer + IsLoaded = true; + } + + public override void Unload() + { + IsLoaded = false; + if (VertexBuffer != null) + { + VBBinding.Buffer = null; + VertexBuffer.Dispose(); + VertexBuffer = null; + } + if (IndexBuffer != null) + { + IndexBuffer.Dispose(); + IndexBuffer = null; + } + LoadQueued = false; + } + + public void Render(DeviceContext context) + { + if ((VertexBuffer == null) || (IndexBuffer == null)) + { + return; + } + + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, VBBinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R32_UInt, 0); + + context.DrawIndexed(IndexCount, 0, 0); + } + + } + + + public class RenderableBoundComposite : RenderableCacheItem + { + public RenderableBoundGeometry[] Geometries; + + + public override void Init(BoundComposite bound) + { + Key = bound; + + if (bound.Children == null) + { + return; + } + + RenderableBoundGeometry[] geoms = new RenderableBoundGeometry[bound.Children.data_items.Length]; + long dsize = 0; + for (int i = 0; i < bound.Children.data_items.Length; i++) + { + var child = bound.Children.data_items[i]; + if (child is BoundGeometry) + { + var rgeom = new RenderableBoundGeometry(); + rgeom.Init(child as BoundGeometry); + rgeom.Owner = this; + geoms[i] = rgeom; + dsize += rgeom.TotalDataSize; + } + else + { + //other types of bound might be here, eg BoundBox + geoms[i] = null;//not really necessary + } + } + + Geometries = geoms; + + DataSize = dsize; + + } + + public override void Load(Device device) + { + if (Geometries == null) return; + foreach (var geom in Geometries) + { + if (geom == null) continue; + geom.Load(device); + } + //LastUseTime = DateTime.Now; //reset usage timer + IsLoaded = true; + } + + public override void Unload() + { + IsLoaded = false; + if (Geometries == null) return; + foreach (var geom in Geometries) + { + if (geom == null) continue; + geom.Unload(); + } + LoadQueued = false; + } + + public override string ToString() + { + return Key.ToString(); + } + } + + public class RenderableBoundGeometry + { + public RenderableBoundComposite Owner; + public Buffer VertexBuffer { get; set; } + //public Buffer IndexBuffer { get; set; } + public VertexBufferBinding VBBinding; + public BoundGeometry BoundGeom; + public VertexType VertexType { get; set; } = VertexType.Default; + public int VertexStride { get; set; } = 36; + public int VertexCount { get; set; } = 0; + public uint VertexDataSize { get; set; } = 0; + public uint TotalDataSize { get; set; } = 0; + public VertexTypeDefault[] Vertices { get; set; } + + public RenderableBox[] Boxes { get; set; } + public RenderableSphere[] Spheres { get; set; } + public RenderableCapsule[] Capsules { get; set; } + public RenderableCylinder[] Cylinders { get; set; } + public GpuSBuffer BoxBuffer { get; set; } + public GpuSBuffer SphereBuffer { get; set; } + public GpuSBuffer CapsuleBuffer { get; set; } + public GpuSBuffer CylinderBuffer { get; set; } + + public void Init(BoundGeometry bgeom) + { + BoundGeom = bgeom; + + if ((bgeom.Polygons == null) || (bgeom.Vertices == null)) + { + return; + } + + Vector3 vbox = (bgeom.BoundingBoxMax - bgeom.BoundingBoxMin); + //var verts = bgeom.Vertices; + //int vertcount = bgeom.Vertices.Length; + + int rvertcount = 0, curvert = 0; + int rboxcount = 0, curbox = 0; + int rspherecount = 0, cursphere = 0; + int rcapsulecount = 0, curcapsule = 0; + int rcylindercount = 0, curcylinder = 0; + for (int i = 0; i < bgeom.Polygons.Length; i++) + { + if (bgeom.Polygons[i] == null) continue; + var type = bgeom.Polygons[i].Type; + switch(type) + { + case BoundPolygonType.Triangle: rvertcount += 3; + break; + case BoundPolygonType.Sphere: rspherecount++; + break; + case BoundPolygonType.Capsule: rcapsulecount++; + break; + case BoundPolygonType.Box: rboxcount++; + break; + case BoundPolygonType.Cylinder: rcylindercount++; + break; + } + } + + VertexTypeDefault[] rverts = (rvertcount > 0) ? new VertexTypeDefault[rvertcount] : null; + RenderableBox[] rboxes = (rboxcount > 0) ? new RenderableBox[rboxcount] : null; + RenderableSphere[] rspheres = (rspherecount > 0) ? new RenderableSphere[rspherecount] : null; + RenderableCapsule[] rcapsules = (rcapsulecount > 0) ? new RenderableCapsule[rcapsulecount] : null; + RenderableCylinder[] rcylinders = (rcylindercount > 0) ? new RenderableCylinder[rcylindercount] : null; + for (int i = 0; i < bgeom.Polygons.Length; i++) + { + var poly = bgeom.Polygons[i]; + if (poly == null) continue; + byte matind = ((bgeom.PolygonMaterialIndices != null) && (i < bgeom.PolygonMaterialIndices.Length)) ? bgeom.PolygonMaterialIndices[i] : (byte)0; + BoundMaterial_s mat = ((bgeom.Materials != null) && (matind < bgeom.Materials.Length)) ? bgeom.Materials[matind] : new BoundMaterial_s(); + Color4 color = BoundsMaterialTypes.GetMaterialColour(mat.Type); + Vector3 p1, p2, p3, p4, a1, n1;//, n2, n3, p5, p7, p8; + Vector3 norm = Vector3.Zero; + uint colour = (uint)color.ToRgba(); + switch (poly.Type) + { + case BoundPolygonType.Triangle: + var ptri = poly as BoundPolygonTriangle; + p1 = bgeom.GetVertex(ptri.vertIndex1); + p2 = bgeom.GetVertex(ptri.vertIndex2); + p3 = bgeom.GetVertex(ptri.vertIndex3); + n1 = Vector3.Normalize(Vector3.Cross(p2 - p1, p3 - p1)); + AddVertex(p1, n1, colour, rverts, ref curvert); + AddVertex(p2, n1, colour, rverts, ref curvert); + AddVertex(p3, n1, colour, rverts, ref curvert); + break; + case BoundPolygonType.Sphere: + var psph = poly as BoundPolygonSphere; + rspheres[cursphere].Center = bgeom.GetVertex(psph.sphereIndex); + rspheres[cursphere].Radius = psph.sphereRadius;// * 0.5f;//diameter? + rspheres[cursphere].Colour = colour; + cursphere++; + break; + case BoundPolygonType.Capsule: + var bcap = poly as BoundPolygonCapsule; + p1 = bgeom.GetVertex(bcap.capsuleIndex1); + p2 = bgeom.GetVertex(bcap.capsuleIndex2); + a1 = p2 - p1; + n1 = Vector3.Normalize(a1); + p3 = Vector3.Normalize(GetPerpVec(n1)); + //p4 = Vector3.Normalize(Vector3.Cross(n1, p3)); + Quaternion q1 = Quaternion.Invert(Quaternion.LookAtRH(Vector3.Zero, p3, n1)); + rcapsules[curcapsule].Point1 = p1; + rcapsules[curcapsule].Orientation = q1; + rcapsules[curcapsule].Length = a1.Length(); + rcapsules[curcapsule].Radius = bcap.capsuleRadius;// * 0.5f;//diameter? + rcapsules[curcapsule].Colour = colour; + curcapsule++; + break; + case BoundPolygonType.Box: //(...only 4 inds... = diagonal corners) + var pbox = poly as BoundPolygonBox; + p1 = bgeom.GetVertex(pbox.boxIndex1); + p2 = bgeom.GetVertex(pbox.boxIndex2); + p3 = bgeom.GetVertex(pbox.boxIndex3); + p4 = bgeom.GetVertex(pbox.boxIndex4); + a1 = ((p3 + p4) - (p1 + p2)) * 0.5f; + p2 = p1 + a1; + p3 = p3 - a1; + p4 = p4 - a1; + rboxes[curbox].Corner = p1; + rboxes[curbox].Edge1 = (p2 - p1); + rboxes[curbox].Edge2 = (p3 - p1); + rboxes[curbox].Edge3 = (p4 - p1); + rboxes[curbox].Colour = colour; + curbox++; + break; + case BoundPolygonType.Cylinder: + var pcyl = poly as BoundPolygonCylinder; + p1 = bgeom.GetVertex(pcyl.cylinderIndex1); + p2 = bgeom.GetVertex(pcyl.cylinderIndex2); + a1 = p2 - p1; + n1 = Vector3.Normalize(a1); + p3 = Vector3.Normalize(GetPerpVec(n1)); + //p4 = Vector3.Normalize(Vector3.Cross(n1, p3)); + Quaternion q2 = Quaternion.Invert(Quaternion.LookAtRH(Vector3.Zero, p3, n1)); + rcylinders[curcylinder].Point1 = p1; + rcylinders[curcylinder].Orientation = q2; + rcylinders[curcylinder].Length = a1.Length(); + rcylinders[curcylinder].Radius = pcyl.cylinderRadius; + rcylinders[curcylinder].Colour = colour; + curcylinder++; + break; + default: + break; + } + + + } + + Vertices = rverts; + VertexCount = (rverts!=null) ? rverts.Length : 0; + + Boxes = rboxes; + Spheres = rspheres; + Capsules = rcapsules; + Cylinders = rcylinders; + + VertexDataSize = (uint)(VertexCount * VertexStride); + TotalDataSize = VertexDataSize; + + } + + private ushort AddVertex(Vector3 pos, Vector3 norm, uint colour, List list) + { + VertexTypeDefault v = new VertexTypeDefault(); + v.Position = pos; + v.Normal = norm; + v.Colour = colour; + v.Texcoord = Vector2.Zero; + var rv = list.Count; + list.Add(v); + return (ushort)rv; + } + private void AddVertex(Vector3 pos, Vector3 norm, uint colour, VertexTypeDefault[] arr, ref int index) + { + arr[index].Position = pos; + arr[index].Normal = norm; + arr[index].Colour = colour; + arr[index].Texcoord = Vector2.Zero; + index++; + } + + private Vector3 GetPerpVec(Vector3 n) + { + //make a vector perpendicular to the given one + float nx = Math.Abs(n.X); + float ny = Math.Abs(n.Y); + float nz = Math.Abs(n.Z); + if ((nx < ny) && (nx < nz)) + { + return Vector3.Cross(n, Vector3.Right); + } + else if (ny < nz) + { + return Vector3.Cross(n, Vector3.Up); + } + else + { + return Vector3.Cross(n, Vector3.ForwardLH); + } + } + + + public void Load(Device device) + { + //if (Vertices.Length == 0) return; //nothing to see here.. + + if ((Vertices != null) && (Vertices.Length > 0)) + { + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, Vertices); + if (VertexBuffer != null) + { + VBBinding = new VertexBufferBinding(VertexBuffer, VertexStride, 0); + } + //IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, Indices); + } + + if ((Boxes != null) && (Boxes.Length > 0)) + { + BoxBuffer = new GpuSBuffer(device, Boxes); + } + if ((Spheres != null) && (Spheres.Length > 0)) + { + SphereBuffer = new GpuSBuffer(device, Spheres); + } + if ((Capsules != null) && (Capsules.Length > 0)) + { + CapsuleBuffer = new GpuSBuffer(device, Capsules); + } + if ((Cylinders != null) && (Cylinders.Length > 0)) + { + CylinderBuffer = new GpuSBuffer(device, Cylinders); + } + + } + + public void Unload() + { + + + if (VertexBuffer != null) + { + VBBinding.Buffer = null; + VertexBuffer.Dispose(); + VertexBuffer = null; + } + //if (IndexBuffer != null) + //{ + // IndexBuffer.Dispose(); + // IndexBuffer = null; + //} + //BoundGeom = null; + + if (BoxBuffer != null) + { + BoxBuffer.Dispose(); + BoxBuffer = null; + } + if (SphereBuffer != null) + { + SphereBuffer.Dispose(); + SphereBuffer = null; + } + if (CapsuleBuffer != null) + { + CapsuleBuffer.Dispose(); + CapsuleBuffer = null; + } + if (CylinderBuffer != null) + { + CylinderBuffer.Dispose(); + CylinderBuffer = null; + } + } + + public void RenderTriangles(DeviceContext context) + { + if ((VertexBuffer == null))// || (IndexBuffer == null)) + { + return; + } + + //Owner.LastUseTime = DateTime.Now; //cache timer reset + + + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, VBBinding); + context.InputAssembler.SetIndexBuffer(null, SharpDX.DXGI.Format.R16_UInt, 0); + //context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R16_UInt, 0); + + context.Draw(VertexCount, 0); + + } + + } + + public struct RenderableBox + { + public Vector3 Corner { get; set; } + public uint Colour { get; set; } + public Vector3 Edge1 { get; set; } + public float Pad1 { get; set; } + public Vector3 Edge2 { get; set; } + public float Pad2 { get; set; } + public Vector3 Edge3 { get; set; } + public float Pad3 { get; set; } + } + public struct RenderableSphere + { + public Vector3 Center { get; set; } + public float Radius { get; set; } + public Vector3 Pad0 { get; set; } + public uint Colour { get; set; } + } + public struct RenderableCapsule + { + public Vector3 Point1 { get; set; } + public float Radius { get; set; } + public Quaternion Orientation { get; set; } + public float Length { get; set; } + public uint Colour { get; set; } + public float Pad0 { get; set; } + public float Pad1 { get; set; } + } + public struct RenderableCylinder + { + public Vector3 Point1 { get; set; } + public float Radius { get; set; } + public Quaternion Orientation { get; set; } + public float Length { get; set; } + public uint Colour { get; set; } + public float Pad0 { get; set; } + public float Pad1 { get; set; } + } + + + public struct RenderableEntity + { + public YmapEntityDef Entity; + public Renderable Renderable; + } + + +} diff --git a/Rendering/RenderableCache.cs b/Rendering/RenderableCache.cs new file mode 100644 index 0000000..be00618 --- /dev/null +++ b/Rendering/RenderableCache.cs @@ -0,0 +1,376 @@ +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using CodeWalker.World; +using System.Collections.Concurrent; +using CodeWalker.GameFiles; +using System.Threading; +using CodeWalker.Properties; + +namespace CodeWalker.Rendering +{ + public class RenderableCache + { + public DateTime LastUpdate = DateTime.Now; + public DateTime LastUnload = DateTime.Now; + public double CacheTime = Settings.Default.GPUCacheTime;// 10.0; //seconds to keep something that's not used + public double UnloadTime = Settings.Default.GPUCacheFlushTime;// 0.1; //seconds between running unload cycles + public int MaxItemsPerLoop = 1; //to keep things flowing + public bool ItemsStillPending = false; //whether or not we need another content thread loop + + public long TotalGraphicsMemoryUse + { + get + { + //return (GeometryCacheUse + TextureCacheUse + BoundCompCacheUse + InstanceCacheUse); + return (renderables.CacheUse + textures.CacheUse + boundcomps.CacheUse + instbatches.CacheUse); + } + } + public int LoadedRenderableCount + { + get + { + return renderables.CurrentLoadedCount;// loadedRenderables.Count; + } + } + public int LoadedTextureCount + { + get + { + return textures.CurrentLoadedCount;// loadedTextures.Count; + } + } + public int MemCachedRenderableCount + { + get + { + return renderables.CurrentCacheCount;// cacheRenderables.Count; + } + } + public int MemCachedTextureCount + { + get + { + return textures.CurrentCacheCount;// cacheTextures.Count; + } + } + + + private RenderableCacheLookup renderables = new RenderableCacheLookup(Settings.Default.GPUGeometryCacheSize, Settings.Default.GPUCacheTime); + private RenderableCacheLookup textures = new RenderableCacheLookup(Settings.Default.GPUTextureCacheSize, Settings.Default.GPUCacheTime); + private RenderableCacheLookup boundcomps = new RenderableCacheLookup(Settings.Default.GPUBoundCompCacheSize, Settings.Default.GPUCacheTime); + private RenderableCacheLookup instbatches = new RenderableCacheLookup(67108864, Settings.Default.GPUCacheTime); //64MB - todo: make this a setting + private RenderableCacheLookup distlodlights = new RenderableCacheLookup(33554432, Settings.Default.GPUCacheTime); //32MB - todo: make this a setting + private RenderableCacheLookup pathbatches = new RenderableCacheLookup(536870912 /*33554432*/, Settings.Default.GPUCacheTime); // 512MB /*32MB*/ - todo: make this a setting + private RenderableCacheLookup waterquads = new RenderableCacheLookup(4194304, Settings.Default.GPUCacheTime); //4MB - todo: make this a setting + + + private object updateSyncRoot = new object(); + + private Device currentDevice; + + + public void OnDeviceCreated(Device device) + { + currentDevice = device; + } + public void OnDeviceDestroyed() + { + currentDevice = null; + + renderables.Clear(); + textures.Clear(); + boundcomps.Clear(); + instbatches.Clear(); + distlodlights.Clear(); + pathbatches.Clear(); + waterquads.Clear(); + } + + public void ContentThreadProc() + { + if (currentDevice == null) return; //can't do anything with no device + + Monitor.Enter(updateSyncRoot); + + + //load the queued items if possible + int renderablecount = renderables.LoadProc(currentDevice, MaxItemsPerLoop); + int texturecount = textures.LoadProc(currentDevice, MaxItemsPerLoop); + int boundcompcount = boundcomps.LoadProc(currentDevice, MaxItemsPerLoop); + int instbatchcount = instbatches.LoadProc(currentDevice, MaxItemsPerLoop); + int distlodlightcount = distlodlights.LoadProc(currentDevice, MaxItemsPerLoop); + int pathbatchcount = pathbatches.LoadProc(currentDevice, MaxItemsPerLoop); + int waterquadcount = waterquads.LoadProc(currentDevice, MaxItemsPerLoop); + + + ItemsStillPending = (renderablecount >= MaxItemsPerLoop) || + (texturecount >= MaxItemsPerLoop) || + (boundcompcount >= MaxItemsPerLoop) || + (instbatchcount >= MaxItemsPerLoop) || + (distlodlightcount >= MaxItemsPerLoop) || + (pathbatchcount >= MaxItemsPerLoop) || + (waterquadcount >= MaxItemsPerLoop); + + + //todo: change this to unload only when necessary (ie when something is loaded) + var now = DateTime.Now; + var deltat = (now - LastUpdate).TotalSeconds; + var unloadt = (now - LastUnload).TotalSeconds; + if ((unloadt > UnloadTime) && (deltat < 0.25)) //don't try the unload on every loop... or when really busy + { + + //unload items that haven't been used in longer than the cache period. + renderables.UnloadProc(); + textures.UnloadProc(); + boundcomps.UnloadProc(); + instbatches.UnloadProc(); + distlodlights.UnloadProc(); + pathbatches.UnloadProc(); + waterquads.UnloadProc(); + + LastUnload = DateTime.Now; + } + + + LastUpdate = DateTime.Now; + + Monitor.Exit(updateSyncRoot); + } + + public void RenderThreadSync() + { + renderables.RenderThreadSync(); + textures.RenderThreadSync(); + boundcomps.RenderThreadSync(); + instbatches.RenderThreadSync(); + distlodlights.RenderThreadSync(); + pathbatches.RenderThreadSync(); + waterquads.RenderThreadSync(); + } + + public Renderable GetRenderable(DrawableBase drawable) + { + return renderables.Get(drawable); + } + public RenderableTexture GetRenderableTexture(Texture texture) + { + return textures.Get(texture); + } + public RenderableBoundComposite GetRenderableBoundComp(BoundComposite boundcomp) + { + return boundcomps.Get(boundcomp); + } + public RenderableInstanceBatch GetRenderableInstanceBatch(YmapGrassInstanceBatch batch) + { + return instbatches.Get(batch); + } + public RenderableDistantLODLights GetRenderableDistantLODLights(YmapDistantLODLights lights) + { + return distlodlights.Get(lights); + } + public RenderablePathBatch GetRenderablePathBatch(BasePathData pathdata) + { + return pathbatches.Get(pathdata); + } + public RenderableWaterQuad GetRenderableWaterQuad(WaterQuad quad) + { + return waterquads.Get(quad); + } + + + + public void Invalidate(BasePathData path) + { + lock (updateSyncRoot) + { + pathbatches.Invalidate(path); + } + } + + + } + + + public abstract class RenderableCacheItem + { + public TKey Key; + public volatile bool IsLoaded = false; + public volatile bool LoadQueued = false; + public long LastUseTime = 0; + //public DateTime LastUseTime { get; set; } + public long DataSize { get; set; } + + public abstract void Init(TKey key); + public abstract void Load(Device device); + public abstract void Unload(); + } + + public class RenderableCacheLookup where TVal: RenderableCacheItem, new() + { + private ConcurrentStack itemsToLoad = new ConcurrentStack(); + private ConcurrentStack itemsToUnload = new ConcurrentStack(); + private LinkedList loadeditems = new LinkedList(); + private Dictionary cacheitems = new Dictionary(); + public long CacheLimit; + public long CacheUse = 0; + public double CacheTime; + public int LoadedCount = 0;//temporary, per loop + + public RenderableCacheLookup(long limit, double time) + { + CacheLimit = limit; + CacheTime = time; + } + + public int CurrentLoadedCount + { + get + { + return loadeditems.Count; + } + } + public int CurrentCacheCount + { + get + { + return cacheitems.Count; + } + } + + public void Clear() + { + TVal item; + while (itemsToLoad.TryPop(out item)) + { } + foreach (TVal rnd in loadeditems) + { + rnd.Unload(); + } + loadeditems.Clear(); + cacheitems.Clear(); + while (itemsToUnload.TryPop(out item)) + { } + } + + + public int LoadProc(Device device, int maxitemsperloop) + { + TVal item; + LoadedCount = 0; + while (itemsToLoad.TryPop(out item)) + { + if (item.IsLoaded) continue; //don't load it again... + LoadedCount++; + long gcachefree = CacheLimit - CacheUse; + if (gcachefree > item.DataSize) + { + try + { + item.Load(device); + loadeditems.AddLast(item); + Interlocked.Add(ref CacheUse, item.DataSize); + } + catch //(Exception ex) + { + //todo: error handling... + } + } + else + { + item.LoadQueued = false; //can try load it again later.. + } + if (LoadedCount >= maxitemsperloop) break; + } + return LoadedCount; + } + + public void UnloadProc() + { + //unload items that haven't been used in longer than the cache period. + var now = DateTime.Now; + var rnode = loadeditems.First; + while (rnode != null) + { + var lu = DateTime.FromBinary(Interlocked.Read(ref rnode.Value.LastUseTime)); + if ((now - lu).TotalSeconds > CacheTime) + { + var nextnode = rnode.Next; + itemsToUnload.Push(rnode.Value); + loadeditems.Remove(rnode); + rnode = nextnode; + } + else + { + rnode = rnode.Next; + } + } + + } + + public void RenderThreadSync() + { + TVal item; + while (itemsToUnload.TryPop(out item)) + { + if ((item.Key != null) && (cacheitems.ContainsKey(item.Key))) + { + cacheitems.Remove(item.Key); + } + item.Unload(); + item.LoadQueued = false; + Interlocked.Add(ref CacheUse, -item.DataSize); + } + + } + + public TVal Get(TKey key) + { + if (key == null) return null; + TVal item = null; + if (!cacheitems.TryGetValue(key, out item)) + { + item = new TVal(); + item.Init(key); + cacheitems.Add(key, item); + } + Interlocked.Exchange(ref item.LastUseTime, DateTime.Now.ToBinary()); + if ((!item.IsLoaded) && (!item.LoadQueued))// || + { + item.LoadQueued = true; + itemsToLoad.Push(item); + } + return item; + } + + + public void Invalidate(TKey key) + { + if (key == null) return; + TVal item = null; + if (!cacheitems.TryGetValue(key, out item)) return; + if (item == null) return; + + if ((item.Key != null) && (cacheitems.ContainsKey(item.Key))) + { + + cacheitems.Remove(item.Key); + + item.Unload(); + item.LoadQueued = false; + Interlocked.Add(ref CacheUse, -item.DataSize); + Interlocked.Exchange(ref item.LastUseTime, DateTime.Now.AddHours(-1).ToBinary()); + + loadeditems.Remove(item);//slow... + } + + } + + } + +} diff --git a/Rendering/ShaderManager.cs b/Rendering/ShaderManager.cs new file mode 100644 index 0000000..450dfc7 --- /dev/null +++ b/Rendering/ShaderManager.cs @@ -0,0 +1,1294 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using CodeWalker.World; +using SharpDX; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.Rendering +{ + public class ShaderManager + { + private DXManager DXMan; + + private int GeometryCount; + public int RenderedGeometries; + + private Device Device; + + public bool wireframe = Settings.Default.Wireframe; + RasterizerState rsSolid; + RasterizerState rsWireframe; + RasterizerState rsSolidDblSided; + RasterizerState rsWireframeDblSided; + BlendState bsDefault; + BlendState bsAlpha; + BlendState bsAdd; + DepthStencilState dsEnabled; + DepthStencilState dsDisableAll; + DepthStencilState dsDisableComp; + DepthStencilState dsDisableWrite; + + + + public PostProcessor HDR { get; set; } + public BasicShader Basic { get; set; } + public CableShader Cable { get; set; } + public WaterShader Water { get; set; } + public TerrainShader Terrain { get; set; } + public TreesLodShader TreesLod { get; set; } + public SkydomeShader Skydome { get; set; } + public CloudsShader Clouds { get; set; } + public MarkerShader Marker { get; set; } + public BoundsShader Bounds { get; set; } + public ShadowShader Shadow { get; set; } + public DistantLightsShader DistLights { get; set; } + public PathShader Paths { get; set; } + public WidgetShader Widgets { get; set; } + + public bool shadows = Settings.Default.Shadows; + public Shadowmap Shadowmap { get; set; } + List shadowcasters = new List(); + List shadowbatch = new List(); + List shadowbatches = new List(); + int shadowcastercount = 0; //total casters rendered + + public bool hdr = Settings.Default.HDR; + public float hdrLumBlendSpeed = 1.0f; + int Width; + int Height; + + private bool disposed = false; + + + public List RenderBuckets = new List(); + public List RenderBoundGeoms = new List(); + public List RenderInstBatches = new List(); + public List RenderDistLODLights = new List(); + public List RenderPathBatches = new List(); + public List RenderWaterQuads = new List(); + + public bool AnisotropicFiltering = true; + public WorldRenderMode RenderMode = WorldRenderMode.Default; + public int RenderVertexColourIndex = 1; + public int RenderTextureCoordIndex = 1; + public int RenderTextureSamplerCoord = 1; + public MetaName RenderTextureSampler = MetaName.DiffuseSampler; + public double CurrentRealTime = 0; + public float CurrentElapsedTime = 0; + + private Camera Camera; + public ShaderGlobalLights GlobalLights = new ShaderGlobalLights(); + public bool PathsDepthClip = false;//true;// + + private GameFileCache GameFileCache; + private RenderableCache RenderableCache; + + + public long TotalGraphicsMemoryUse + { + get + { + long u = 0; + if (HDR != null) + { + u += HDR.VramUsage; + } + if (Shadowmap != null) + { + u += Shadowmap.VramUsage; + } + return u; + } + } + + + public ShaderManager(Device device, DXManager dxman) + { + Device = device; + DXMan = dxman; + + //HDR = new PostProcessor(dxman); + Basic = new BasicShader(device); + Cable = new CableShader(device); + Water = new WaterShader(device); + Terrain = new TerrainShader(device); + TreesLod = new TreesLodShader(device); + Skydome = new SkydomeShader(device); + Clouds = new CloudsShader(device); + Marker = new MarkerShader(device); + Bounds = new BoundsShader(device); + Shadow = new ShadowShader(device); + DistLights = new DistantLightsShader(device); + Paths = new PathShader(device); + Widgets = new WidgetShader(device); + + + RasterizerStateDescription rsd = new RasterizerStateDescription() + { + CullMode = CullMode.Back, + DepthBias = 0, + DepthBiasClamp = 0.0f, + FillMode = FillMode.Solid, + IsAntialiasedLineEnabled = true, + IsDepthClipEnabled = true, + IsFrontCounterClockwise = true, + IsMultisampleEnabled = true, + IsScissorEnabled = false, + SlopeScaledDepthBias = 0.0f + }; + rsSolid = new RasterizerState(device, rsd); + rsd.FillMode = FillMode.Wireframe; + rsWireframe = new RasterizerState(device, rsd); + rsd.CullMode = CullMode.None; + rsWireframeDblSided = new RasterizerState(device, rsd); + rsd.FillMode = FillMode.Solid; + rsSolidDblSided = new RasterizerState(device, rsd); + + + BlendStateDescription bsd = new BlendStateDescription() + { + AlphaToCoverageEnable = false,//true, + IndependentBlendEnable = false, + }; + bsd.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add; + bsd.RenderTarget[0].BlendOperation = BlendOperation.Add; + bsd.RenderTarget[0].DestinationAlphaBlend = BlendOption.One; + bsd.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha; + bsd.RenderTarget[0].IsBlendEnabled = true; + bsd.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All; + bsd.RenderTarget[0].SourceAlphaBlend = BlendOption.Zero; + bsd.RenderTarget[0].SourceBlend = BlendOption.SourceAlpha; + bsDefault = new BlendState(device, bsd); + + bsd.AlphaToCoverageEnable = true; + bsAlpha = new BlendState(device, bsd); + + bsd.AlphaToCoverageEnable = false; + bsd.RenderTarget[0].DestinationBlend = BlendOption.One; + bsAdd = new BlendState(device, bsd); + + DepthStencilStateDescription dsd = new DepthStencilStateDescription() + { + BackFace = new DepthStencilOperationDescription() + { + Comparison = Comparison.LessEqual, + DepthFailOperation = StencilOperation.Zero, + FailOperation = StencilOperation.Zero, + PassOperation = StencilOperation.Zero, + }, + DepthComparison = Comparison.LessEqual, + DepthWriteMask = DepthWriteMask.All, + FrontFace = new DepthStencilOperationDescription() + { + Comparison = Comparison.LessEqual, + DepthFailOperation = StencilOperation.Zero, + FailOperation = StencilOperation.Zero, + PassOperation = StencilOperation.Zero + }, + IsDepthEnabled = true, + IsStencilEnabled = false, + StencilReadMask = 0, + StencilWriteMask = 0 + }; + dsEnabled = new DepthStencilState(device, dsd); + dsd.DepthWriteMask = DepthWriteMask.Zero; + dsDisableWrite = new DepthStencilState(device, dsd); + dsd.DepthComparison = Comparison.Always; + dsDisableComp = new DepthStencilState(device, dsd); + dsd.IsDepthEnabled = false; + dsDisableAll = new DepthStencilState(device, dsd); + } + + + + public void Dispose() + { + if (disposed) return; + disposed = true; + + dsEnabled.Dispose(); + dsDisableWrite.Dispose(); + dsDisableComp.Dispose(); + dsDisableAll.Dispose(); + bsDefault.Dispose(); + bsAlpha.Dispose(); + bsAdd.Dispose(); + rsSolid.Dispose(); + rsWireframe.Dispose(); + + Widgets.Dispose(); + Paths.Dispose(); + DistLights.Dispose(); + Shadow.Dispose(); + Bounds.Dispose(); + Marker.Dispose(); + Terrain.Dispose(); + TreesLod.Dispose(); + Skydome.Dispose(); + Clouds.Dispose(); + Basic.Dispose(); + Cable.Dispose(); + Water.Dispose(); + + if (HDR != null) + { + HDR.Dispose(); + HDR = null; + } + + if (Shadowmap != null) + { + Shadowmap.Dispose(); + Shadowmap = null; + } + } + + + public void SetGlobalLightParams(ShaderGlobalLights lights) + { + GlobalLights.CurrentSunDir = lights.CurrentSunDir; + GlobalLights.CurrentMoonDir = lights.CurrentMoonDir; + GlobalLights.HdrEnabled = lights.HdrEnabled; + GlobalLights.HdrIntensity = lights.HdrIntensity; + GlobalLights.SpecularEnabled = lights.SpecularEnabled; + GlobalLights.Weather = lights.Weather; + GlobalLights.Params = lights.Params; + } + + public void BeginFrame(DeviceContext context, double currentRealTime, float elapsedTime) + { + CurrentRealTime = currentRealTime; + CurrentElapsedTime = elapsedTime; + + shadowcasters.Clear(); + if (shadows && (Shadowmap == null)) + { + Shadowmap = new Shadowmap(Device); + } + if (!shadows && (Shadowmap != null)) + { + Shadowmap.Dispose(); + Shadowmap = null; + } + if (hdr && (HDR == null)) + { + HDR = new PostProcessor(DXMan); + HDR.OnWindowResize(DXMan); + HDR.LumBlendSpeed = hdrLumBlendSpeed; + } + if (!hdr && (HDR != null)) + { + HDR.Dispose(); + HDR = null; + } + + + foreach (var bucket in RenderBuckets) + { + bucket.Clear(); + } + + RenderBoundGeoms.Clear(); + RenderInstBatches.Clear(); + RenderDistLODLights.Clear(); + RenderPathBatches.Clear(); + RenderWaterQuads.Clear(); + + if (HDR != null) + { + HDR.Clear(context); + HDR.ClearDepth(context); + HDR.SetPrimary(context); //for rendering some things before shadowmaps... (eg sky) + } + else + { + DXMan.SetDefaultRenderTarget(context); + } + + Skydome.EnableHDR = hdr; + Clouds.EnableHDR = hdr; + } + + + public void EnsureShaderTextures(GameFileCache gameFileCache, RenderableCache renderableCache) + { + if (!gameFileCache.IsInited) return; + + GameFileCache = gameFileCache; + RenderableCache = renderableCache; + + uint graphics = 3154743001; //JenkHash.GenHash("graphics"); + uint waterbump = 2826194296; //JenkHash.GenHash("waterbump"); + uint waterbump2 = 209023451; //JenkHash.GenHash("waterbump2"); + uint waterfog = 4047019542; + Water.waterbump = EnsureTexture(graphics, waterbump); + Water.waterbump2 = EnsureTexture(graphics, waterbump2); + Water.waterfog = EnsureTexture(graphics, waterfog); + + + + } + + private RenderableTexture EnsureTexture(uint texDict, uint texName) + { + YtdFile ytd = GameFileCache.GetYtd(texDict); + if ((ytd != null) && (ytd.Loaded) && (ytd.TextureDict != null)) + { + var dtex = ytd.TextureDict.Lookup(texName); + return RenderableCache.GetRenderableTexture(dtex); + } + return null; + } + + public void RenderQueued(DeviceContext context, Camera camera, Vector4 wind) + { + GeometryCount = 0; + Camera = camera; + + + SetShaderRenderModeParams(); + + Basic.WindVector = wind; + Shadow.WindVector = wind; + Water.CurrentRealTime = CurrentRealTime; + Water.CurrentElapsedTime = CurrentElapsedTime; + + shadowbatches.Clear(); + for (int i = 0; i < RenderBuckets.Count; i++) + { + var bucket = RenderBuckets[i]; + + //sort the bucket's batches based on the shader file hashes + bucket.GroupBatches(); + + if (shadows) + { + shadowbatches.AddRange(bucket.BasicBatches); + shadowbatches.AddRange(bucket.TerrainBatches); + shadowbatches.AddRange(bucket.CableBatches); + shadowbatches.AddRange(bucket.AlphaBatches); + shadowbatches.AddRange(bucket.CutoutBatches); + shadowbatches.AddRange(bucket.ClothBatches); + } + } + + + if (shadows) + { + RenderShadowmap(context); + } + + + if (HDR != null) + { + HDR.SetPrimary(context); + } + else + { + DXMan.SetDefaultRenderTarget(context); + } + + for (int i = 0; i < RenderBuckets.Count; i++) //"solid" objects pass + { + var bucket = RenderBuckets[i]; + + context.OutputMerger.BlendState = bsDefault; + context.OutputMerger.DepthStencilState = dsEnabled; + context.Rasterizer.State = wireframe ? rsWireframe : rsSolid; + + if (bucket.TerrainBatches.Count > 0) + { + RenderGeometryBatches(context, bucket.TerrainBatches, Terrain); + } + if (bucket.BasicBatches.Count > 0) + { + RenderGeometryBatches(context, bucket.BasicBatches, Basic); + } + if (bucket.TreesLodBatches.Count > 0) + { + context.Rasterizer.State = wireframe ? rsWireframeDblSided : rsSolidDblSided; + RenderGeometryBatches(context, bucket.TreesLodBatches, TreesLod); + } + if (bucket.CutoutBatches.Count > 0) + { + context.Rasterizer.State = wireframe ? rsWireframeDblSided : rsSolidDblSided; + RenderGeometryBatches(context, bucket.CutoutBatches, Basic); + } + if (bucket.ClothBatches.Count > 0) + { + context.Rasterizer.State = wireframe ? rsWireframeDblSided : rsSolidDblSided; + RenderGeometryBatches(context, bucket.ClothBatches, Basic); + } + if (bucket.CableBatches.Count > 0) + { + context.Rasterizer.State = wireframe ? rsWireframe : rsSolid; + RenderGeometryBatches(context, bucket.CableBatches, Cable); + } + if (bucket.DecalBatches.Count > 0) + { + context.Rasterizer.State = wireframe ? rsWireframe : rsSolid; + context.OutputMerger.DepthStencilState = dsDisableWrite; + Basic.DecalMode = true; + RenderGeometryBatches(context, bucket.DecalBatches, Basic); + Basic.DecalMode = false; + context.OutputMerger.DepthStencilState = dsEnabled; + } + } + + + if (RenderInstBatches.Count > 0) //grass pass + { + context.Rasterizer.State = wireframe ? rsWireframeDblSided : rsSolidDblSided; + context.OutputMerger.BlendState = bsAlpha; //alpha to coverage for grass... + Basic.DecalMode = true; + Basic.AlphaScale = 7.0f; //instanced grass alpha scale... + Basic.SetShader(context); + Basic.SetSceneVars(context, Camera, Shadowmap, GlobalLights); + for (int i = 0; i < RenderInstBatches.Count; i++) + { + RenderInstancedBatch(context, RenderInstBatches[i]); + } + Basic.UnbindResources(context); + Basic.AlphaScale = 1.0f; + Basic.DecalMode = false; + context.OutputMerger.BlendState = bsDefault; + } + + if (RenderDistLODLights.Count > 0) //LOD lights pass + { + context.Rasterizer.State = rsSolidDblSided; + context.OutputMerger.BlendState = bsAdd; //additive blend for distant lod lights... + context.OutputMerger.DepthStencilState = dsDisableWrite; + DistLights.SetShader(context); + DistLights.SetSceneVars(context, Camera, Shadowmap, GlobalLights); + for (int i = 0; i < RenderDistLODLights.Count; i++) + { + DistLights.RenderBatch(context, RenderDistLODLights[i]); + } + DistLights.UnbindResources(context); + context.OutputMerger.BlendState = bsDefault; + context.OutputMerger.DepthStencilState = dsEnabled; + } + + + + + context.OutputMerger.BlendState = bsDefault; + context.Rasterizer.State = wireframe ? rsWireframeDblSided : rsSolidDblSided; + context.OutputMerger.DepthStencilState = dsDisableWrite; + + for (int i = 0; i < RenderBuckets.Count; i++) //water pass + { + var bucket = RenderBuckets[i]; + if (bucket.WaterBatches.Count > 0) + { + RenderGeometryBatches(context, bucket.WaterBatches, Water); + } + if (bucket.Water2Batches.Count > 0) + { + RenderGeometryBatches(context, bucket.Water2Batches, Water); + } + } + if (RenderWaterQuads.Count > 0) //also render water quads here + { + Water.SetShader(context); + Water.SetSceneVars(context, Camera, Shadowmap, GlobalLights); + for (int i = 0; i < RenderWaterQuads.Count; i++) + { + Water.RenderWaterQuad(context, RenderWaterQuads[i]); + } + Water.UnbindResources(context); + } + + Basic.DecalMode = true; + for (int i = 0; i < RenderBuckets.Count; i++) //alphablended and glass pass + { + var bucket = RenderBuckets[i]; + + if (bucket.AlphaBatches.Count > 0) + { + //context.OutputMerger.BlendState = bsAlpha; + RenderGeometryBatches(context, bucket.AlphaBatches, Basic); + } + if (bucket.GlassBatches.Count > 0) + { + RenderGeometryBatches(context, bucket.GlassBatches, Basic); + } + } + Basic.DecalMode = false; + context.OutputMerger.DepthStencilState = dsEnabled; + + + + if (RenderBoundGeoms.Count > 0) //collision meshes pass + { + ClearDepth(context); //draw over everything else + + context.OutputMerger.BlendState = bsDefault; + context.OutputMerger.DepthStencilState = dsEnabled; + context.Rasterizer.State = wireframe ? rsWireframe : rsSolid; + + RenderBoundGeometryBatch(context, RenderBoundGeoms); + } + + + if (RenderPathBatches.Count > 0) //paths pass + { + //ClearDepth(context); //draw over everything else + + context.OutputMerger.BlendState = bsDefault; + context.OutputMerger.DepthStencilState = PathsDepthClip ? dsEnabled : dsDisableAll;// dsEnabled; // + context.Rasterizer.State = rsSolid; + + Paths.RenderBatches(context, RenderPathBatches, camera, GlobalLights); + } + + + + RenderedGeometries = GeometryCount; + + } + + public void RenderFinalPass(DeviceContext context) + { + context.Rasterizer.State = rsSolid; + context.OutputMerger.BlendState = bsDefault; + context.OutputMerger.DepthStencilState = dsEnabled; + + if (HDR != null) + { + HDR.Render(DXMan, CurrentElapsedTime); + } + + } + + private void RenderShadowmap(DeviceContext context) + { + context.OutputMerger.BlendState = bsDefault; + context.OutputMerger.DepthStencilState = dsEnabled; + context.Rasterizer.State = rsSolid; + + //find the casters + shadowcasters.Clear(); + shadowcastercount = 0; + foreach (var sbatch in shadowbatches) + { + foreach (var srend in sbatch.Geometries) + { + shadowcasters.Add(srend); + } + } + + //render cascades + Shadowmap.BeginUpdate(context, Camera, GlobalLights.Params.LightDir, shadowcasters); + for (int i = 0; i < Shadowmap.CascadeCount; i++) + { + var cascade = Shadowmap.Cascades[i]; + + Shadowmap.BeginDepthRender(context, i); + + float cfar = 3000.0f;// cascade.IntervalFar * 5.0f; + + float worldtocascade = cascade.WorldUnitsToCascadeUnits * 2.0f; + + shadowbatch.Clear(); + for (int c=0; c cfar) continue; //performance improvement? + Vector3 iscenepos = caster.Inst.Position - Shadowmap.SceneOrigin; + Vector3 ilightpos = cascade.Matrix.Multiply(iscenepos - caster.Inst.BSCenter); + //Vector3 ilightrad = cascade.Matrix.Multiply(new Vector3(caster.Inst.Radius)); + //float ilightradf = caster.Inst.Radius;// ilightrad.Length(); + float ilightradf = caster.Inst.Radius * worldtocascade; + float ilightminx = ilightpos.X - ilightradf; + float ilightmaxx = ilightpos.X + ilightradf; + float ilightminy = ilightpos.Y - ilightradf; + float ilightmaxy = ilightpos.Y + ilightradf; + if ((ilightmaxx > -1.0f) && (ilightminx < 1.0f) && (ilightmaxy > -1.0f) && (ilightminy < 1.0f)) + { + shadowcastercount++; + caster.Inst.CamRel = iscenepos; + shadowbatch.Add(caster); + } + } + + Shadow.SetShader(context); + Shadow.SetSceneVars(context, cascade.Matrix); + RenderGeometryBatch(context, shadowbatch, Shadow); + + } + Shadowmap.EndUpdate(context); + Shadow.UnbindResources(context); + + context.OutputMerger.BlendState = bsDefault; + context.OutputMerger.DepthStencilState = dsEnabled; + context.Rasterizer.State = rsSolid; + } + + + private void RenderGeometryBatches(DeviceContext context, List batches, Shader shader) + { + shader.SetShader(context); + shader.SetSceneVars(context, Camera, Shadowmap, GlobalLights); + foreach (var batch in batches) + { + RenderGeometryBatch(context, batch.Geometries, shader); + } + shader.UnbindResources(context); + } + private void RenderGeometryBatch(DeviceContext context, List batch, Shader shader) + { + GeometryCount += batch.Count; + + RenderableModel model = null; + + VertexType vtyp = 0; + bool vtypok = false; + for (int i = 0; i < batch.Count; i++) + { + var geom = batch[i]; + var gmodel = geom.Geom.Owner; + shader.SetEntityVars(context, ref geom.Inst); + + if (gmodel != model) + { + model = gmodel; + shader.SetModelVars(context, model); + } + if (geom.Geom.VertexType != vtyp) + { + vtyp = geom.Geom.VertexType; + if (!shader.SetInputLayout(context, vtyp)) + { + //vertex type not supported... + vtypok = false; + } + else + { + vtypok = true; + } + } + if (vtypok) + { + + shader.SetGeomVars(context, geom.Geom); + geom.Geom.Render(context); + + } + } + + } + + private void RenderBoundGeometryBatch(DeviceContext context, List batch) + { + Basic.RenderMode = WorldRenderMode.VertexColour; + Basic.SetShader(context); + Basic.SetSceneVars(context, Camera, Shadowmap, GlobalLights); + Basic.SetInputLayout(context, VertexType.Default); + + GeometryCount += batch.Count; + + foreach (var geom in batch) + { + Basic.RenderBoundGeom(context, geom); + } + + Basic.UnbindResources(context); + } + + private void RenderInstancedBatch(DeviceContext context, RenderableInstanceBatchInst batch) + { + Basic.SetInstanceVars(context, batch.Batch); + + if (batch.Renderable.HDModels.Length > 1) + { } + + foreach (var model in batch.Renderable.HDModels) + { + if (model.Geometries.Length > 1) + { } + + Basic.SetModelVars(context, model); + foreach (var geom in model.Geometries) + { + if (Basic.SetInputLayout(context, geom.VertexType)) + { + Basic.SetGeomVars(context, geom); + geom.RenderInstanced(context, batch.Batch.InstanceCount); + } + } + } + } + + + + public void Enqueue(RenderableGeometryInst geom) + { + var shader = geom.Geom.DrawableGeom.Shader; + + var b = (shader!=null) ? shader.Unknown_11h : 0; //rage render bucket? + + var bucket = EnsureRenderBucket(b); + + ShaderBatch batch = null; + ShaderKey key = new ShaderKey(); + key.ShaderName = (shader!=null) ? shader.Name : new MetaHash(0); + key.ShaderFile = (shader!=null) ? shader.FileName : new MetaHash(0); + + if (!bucket.Batches.TryGetValue(key, out batch)) + { + batch = new ShaderBatch(key); + bucket.Batches.Add(key, batch); + } + + batch.Geometries.Add(geom); + } + public void Enqueue(RenderableBoundGeometryInst geom) + { + RenderBoundGeoms.Add(geom); + } + public void Enqueue(RenderableInstanceBatchInst batch) + { + RenderInstBatches.Add(batch); + } + public void Enqueue(RenderableDistantLODLights lights) + { + RenderDistLODLights.Add(lights); + } + public void Enqueue(RenderablePathBatch paths) + { + RenderPathBatches.Add(paths); + } + public void Enqueue(RenderableWaterQuad waterquad) + { + RenderWaterQuads.Add(waterquad); + } + + + public ShaderRenderBucket EnsureRenderBucket(int index) + { + ShaderRenderBucket bucket = null; + while (index >= RenderBuckets.Count) + { + RenderBuckets.Add(new ShaderRenderBucket(RenderBuckets.Count)); + } + if (index < RenderBuckets.Count) + { + bucket = RenderBuckets[index]; + } + return bucket; + } + + + private void SetShaderRenderModeParams() + { + Basic.RenderMode = RenderMode; + Basic.RenderVertexColourIndex = RenderVertexColourIndex; + Basic.RenderTextureCoordIndex = RenderTextureCoordIndex; + Basic.RenderTextureSamplerCoord = RenderTextureSamplerCoord; + Basic.RenderTextureSampler = RenderTextureSampler; + Basic.AnisotropicFilter = AnisotropicFiltering; + Clouds.AnisotropicFilter = AnisotropicFiltering; + Water.RenderMode = RenderMode; + Water.RenderVertexColourIndex = RenderVertexColourIndex; + Water.RenderTextureCoordIndex = RenderTextureCoordIndex; + Water.RenderTextureSamplerCoord = RenderTextureSamplerCoord; + Water.RenderTextureSampler = RenderTextureSampler; + Water.AnisotropicFilter = AnisotropicFiltering; + Terrain.RenderMode = RenderMode; + Terrain.RenderVertexColourIndex = RenderVertexColourIndex; + Terrain.RenderTextureCoordIndex = RenderTextureCoordIndex; + Terrain.RenderTextureSamplerCoord = RenderTextureSamplerCoord; + Terrain.RenderTextureSampler = RenderTextureSampler; + Terrain.AnisotropicFilter = AnisotropicFiltering; + } + + + + public void ClearDepth(DeviceContext context, bool firstpass = true) + { + if ((HDR != null) && firstpass) + { + HDR.ClearDepth(context); + } + else + { + DXMan.ClearDepth(context); + } + } + public void SetRasterizerMode(DeviceContext context, RasterizerMode mode) + { + switch (mode) + { + default: + case RasterizerMode.Solid: + context.Rasterizer.State = rsSolid; + break; + case RasterizerMode.Wireframe: + context.Rasterizer.State = rsWireframe; + break; + case RasterizerMode.SolidDblSided: + context.Rasterizer.State = rsSolidDblSided; + break; + case RasterizerMode.WireframeDblSided: + context.Rasterizer.State = rsWireframeDblSided; + break; + } + } + public void SetDepthStencilMode(DeviceContext context, DepthStencilMode mode) + { + switch (mode) + { + default: + case DepthStencilMode.Enabled: + context.OutputMerger.DepthStencilState = dsEnabled; + break; + case DepthStencilMode.DisableWrite: + context.OutputMerger.DepthStencilState = dsDisableWrite; + break; + case DepthStencilMode.DisableComp: + context.OutputMerger.DepthStencilState = dsDisableComp; + break; + case DepthStencilMode.DisableAll: + context.OutputMerger.DepthStencilState = dsDisableAll; + break; + } + } + public void SetDefaultBlendState(DeviceContext context) + { + context.OutputMerger.BlendState = bsDefault; + } + public void SetAlphaBlendState(DeviceContext context) + { + context.OutputMerger.BlendState = bsAlpha; + } + + public void OnWindowResize(int w, int h) + { + Width = w; + Height = h; + if (HDR != null) + { + HDR.OnWindowResize(DXMan); + } + } + } + + public enum RasterizerMode + { + Solid = 1, + Wireframe = 2, + SolidDblSided = 3, + WireframeDblSided = 4, + } + public enum DepthStencilMode + { + Enabled = 1, + DisableWrite = 2, + DisableComp = 3, + DisableAll = 4, + } + + + public struct ShaderKey + { + public MetaHash ShaderName; + public MetaHash ShaderFile; + + public override string ToString() + { + return ShaderFile.ToString() + ": " + ShaderName.ToString(); + } + } + public class ShaderRenderBucket + { + public int Index; + public Dictionary Batches = new Dictionary(); + + public List BasicBatches = new List(); + public List DecalBatches = new List(); + public List WaterBatches = new List(); + public List Water2Batches = new List(); + public List AlphaBatches = new List(); + public List GlassBatches = new List(); + public List CutoutBatches = new List(); + public List TerrainBatches = new List(); + public List TreesLodBatches = new List(); + public List CableBatches = new List(); + public List ClothBatches = new List(); + public List VehicleBatches = new List(); + + + public ShaderRenderBucket(int index) + { + Index = index; + } + public void Clear() + { + foreach (var batch in Batches.Values) + { + batch.Clear(); + } + } + + public void GroupBatches() + { + BasicBatches.Clear(); + DecalBatches.Clear(); + WaterBatches.Clear(); + Water2Batches.Clear(); + AlphaBatches.Clear(); + GlassBatches.Clear(); + CutoutBatches.Clear(); + TerrainBatches.Clear(); + TreesLodBatches.Clear(); + CableBatches.Clear(); + ClothBatches.Clear(); + VehicleBatches.Clear(); + + foreach (var kvp in Batches) + { + if (kvp.Value.Geometries.Count == 0) continue; + + List b = null; + switch (kvp.Key.ShaderFile.Hash) + { + #region default batches + case 0://default + case 413996436://{default.sps} + case 1581835696://{default_um.sps} + case 200682448://{default_tnt.sps} + case 1891750326://{default_spec.sps} + case 3080824371://{default_detail.sps} + case 3939256279://{default_terrain_wet.sps} + case 2948410525://{normal.sps} + case 3326705511://{normal_um.sps} + case 1891558834://{normal_pxm.sps} + case 3348158737://{normal_pxm_tnt.sps} + case 346521853://{normal_spec.sps} + case 1092618307://{normal_spec_dpm.sps} + case 505619005://{normal_spec_detail.sps} + case 10880875://{normal_spec_detail_tnt.sps} + case 3376941572://{normal_spec_detail_dpm_tnt.sps} + case 1315370658://{normal_spec_detail_dpm.sps} + case 4246136089://{normal_spec_detail_dpm_vertdecal_tnt.sps} + case 810202407://{normal_spec_tnt.sps} + case 2121232575://{normal_spec_tnt_pxm.sps} + case 1489449972://{normal_spec_pxm.sps} + case 1117835835://{normal_spec_pxm_tnt.sps} + case 3085209681://{normal_spec_um.sps} + case 1332909972://{normal_spec_emissive.sps} + case 3424303599://{normal_spec_reflect.sps} + case 2072061694://{normal_spec_reflect_emissivenight.sps} + case 3564197994://{normal_spec_cubemap_reflect.sps} + case 1808536605://{normal_detail.sps} + case 557170358://{normal_detail_dpm.sps} + case 3420295952://{normal_diffspec.sps} + case 559317884://{normal_diffspec_detail_dpm_tnt.sps} + case 2735427639://{normal_diffspec_detail_dpm.sps} + case 1845339284://{normal_diffspec_detail.sps} + case 601788410://{normal_diffspec_detail_tnt.sps} + case 3756536307://{normal_diffspec_tnt.sps} + case 2988770526://{normal_tnt.sps} + case 1728634142://{normal_tnt_pxm.sps} + case 3362038760://{normal_terrain_wet.sps} + case 1685791092://{normal_reflect.sps} + case 2626821864://{normal_cubemap_reflect.sps} + case 2635608835://{emissive.sps} + case 443538781://{emissive_clip.sps} + case 2049580179://{emissive_speclum.sps} + case 1193295596://{emissive_tnt.sps} + case 1434302180://{emissivenight.sps} + case 1897917258://{emissivenight_geomnightonly.sps} + case 140448747://{emissivestrong.sps} + case 2247429097://{spec.sps} + case 1396339721://{spec_const.sps} + case 689627308://{spec_tnt.sps} + case 873285799://{spec_reflect.sps} + case 3634763545://{reflect.sps} + case 1658580369://{mirror_default.sps} + case 129155404://{mirror_crack.sps} + case 2067933913://{parallax.sps} + case 1084945164://{parallax_specmap.sps} + case 3052800384://{blend_2lyr.sps} + case 154074948://{spec_twiddle_tnt.sps} + case 14185869://{weapon_normal_spec_tnt.sps} + b = BasicBatches; + break; + #endregion + #region cloth batches + case 1106229739://{cloth_default.sps} + case 1800418130://{cloth_normal_spec.sps} + case 476099326://{cloth_spec_cutout.sps} + case 170694389://{cloth_normal_spec_cutout.sps} + case 38543133://{cloth_normal_spec_tnt.sps} + b = ClothBatches; + break; + #endregion + #region cutout batches + case 1530399584://{cutout.sps} + case 3190732435://{cutout_um.sps} + case 3959636627://{cutout_tnt.sps} + case 2219447268://{cutout_fence.sps} + case 3091995132://{cutout_fence_normal.sps} + case 3187789425://{cutout_hard.sps} + case 3339370144://{cutout_spec_tnt.sps} + case 1264076685://{normal_cutout.sps} + case 46387092://{normal_cutout_tnt.sps} + case 748520668://{normal_cutout_um.sps} + case 807996366://{normal_spec_cutout.sps} + case 3300978494://{normal_spec_cutout_tnt.sps} + case 582493193://{trees_lod.sps} //not billboarded.. + case 2322653400://{trees.sps} + case 3334613197://{trees_tnt.sps} + case 3192134330://{trees_normal.sps} + case 1224713457://{trees_normal_spec.sps} + case 1229591973://{trees_normal_spec_tnt.sps} + case 4265705004://{trees_normal_diffspec.sps} + case 2245870123://{trees_normal_diffspec_tnt.sps} + b = CutoutBatches; + break; + #endregion + #region alpha batches + case 2021887493://{normal_spec_alpha.sps} + case 1086592620://{normal_spec_reflect_alpha.sps} + case 1436689415://{normal_spec_reflect_emissivenight_alpha.sps} + case 4237650253://{normal_spec_screendooralpha.sps} + case 1564459451://{normal_alpha.sps} + case 763839200://{normal_reflect_alpha.sps} + case 179247185://{emissive_alpha.sps} + case 1314864030://{emissive_alpha_tnt.sps} + case 1478174766://{emissive_additive_alpha.sps} + case 3733846327://{emissivenight_alpha.sps} + case 3174327089://{emissivestrong_alpha.sps} + case 257450439://{spec_alpha.sps} + case 2116642565://{spec_reflect_alpha.sps} + case 298255408://{alpha.sps} + case 181295180://{reflect_alpha.sps} + case 1896243360://{normal_screendooralpha.sps} + case 3724703640://{spec_screendooralpha.sps} + case 2161953435://{cloth_spec_alpha.sps} //alpha cloth is ok in alpha batch for now... + case 3203310712://{cloth_normal_spec_alpha.sps} + b = AlphaBatches; + break; + #endregion + #region water batches + case 1529202445://{water_river.sps} + case 4064804434://{water_riverlod.sps} + case 2871265627://{water_riverocean.sps} + case 1507348828://{water_rivershallow.sps} + case 3945561843://{water_fountain.sps} + case 4234404348://{water_shallow.sps} + b = WaterBatches; + break; + case 1077877097://{water_poolenv.sps} + case 3053856997://{water_riverfoam.sps} + case 3066724854://{water_terrainfoam.sps} + case 1471966282://{water_decal.sps} (should this be in decal batch?) + b = Water2Batches; + break; + #endregion + #region glass batches + case 3928756789://{glass.sps} + case 4018753208://{glass_pv.sps} + case 2800545026://{glass_pv_env.sps} + case 1263059426://{glass_env.sps} + case 3398951093://{glass_spec.sps} + case 1520288031://{glass_reflect.sps} + case 3924045432://{glass_emissive.sps} + case 837003310://{glass_emissivenight.sps} + case 485710087://{glass_emissivenight_alpha.sps} + case 1359281054://{glass_breakable.sps} + case 4237090538://{glass_breakable_screendooralpha.sps} + case 430314084://{glass_displacement.sps} + case 2866652360://{glass_normal_spec_reflect.sps} + case 2055615352://{glass_emissive_alpha.sps} + b = GlassBatches; + break; + #endregion + #region decal batches + case 3140040342://{decal.sps} + case 1093522222://{decal_tnt.sps} + case 3948167519://{decal_glue.sps} + case 3880384844://{decal_spec_only.sps} + case 341123999://{decal_normal_only.sps} + case 2918136469://{decal_emissive_only.sps} + case 2698880237://{decal_emissivenight_only.sps} + case 600733812://{decal_amb_only.sps} + case 1145906525://{normal_decal.sps} + case 1342302630://{normal_decal_pxm.sps} + case 2269053854://{normal_decal_pxm_tnt.sps} + case 108580378://{normal_decal_tnt.sps} + case 2189252961://{normal_spec_decal.sps} + case 992110385://{normal_spec_decal_detail.sps} + case 941334042://{normal_spec_decal_nopuddle.sps} + case 2739041469://{normal_spec_decal_tnt.sps} + case 3606424483://{normal_spec_decal_pxm.sps} + case 2842248626://{spec_decal.sps} + case 3717415672://{spec_reflect_decal.sps} + case 2457676400://{reflect_decal.sps} + case 2655725442://{decal_dirt.sps} + case 2706821972://{mirror_decal.sps} + case 1851110504://{distance_map.sps} + b = DecalBatches; + break; + #endregion + #region trees batches + case 4113118754://{trees_lod2.sps} + b = TreesLodBatches; + break; + #endregion + #region terrain batches + case 2131453483://{terrain_cb_w_4lyr.sps} + case 404312839://{terrain_cb_w_4lyr_lod.sps} + case 1196319128://{terrain_cb_w_4lyr_spec.sps} + case 1539365454://{terrain_cb_w_4lyr_spec_pxm.sps} + case 2415127391://{terrain_cb_w_4lyr_pxm_spm.sps} + case 4024079163://{terrain_cb_w_4lyr_pxm.sps} + case 1437909171://{terrain_cb_w_4lyr_cm_pxm.sps} + case 1185891401://{terrain_cb_w_4lyr_cm_tnt.sps} //golf + case 3254053796://{terrain_cb_w_4lyr_cm_pxm_tnt.sps} //golf + case 1567099655://{terrain_cb_w_4lyr_cm.sps} + case 3908107877://{terrain_cb_w_4lyr_2tex.sps} + case 341330913://{terrain_cb_w_4lyr_2tex_blend.sps} + case 673057355://{terrain_cb_w_4lyr_2tex_blend_lod.sps} + case 1046220944://{terrain_cb_w_4lyr_2tex_blend_pxm.sps} + case 2344506399://{terrain_cb_w_4lyr_2tex_blend_pxm_spm.sps} + case 3444846649://{terrain_cb_w_4lyr_2tex_pxm.sps} + case 3369161623://{terrain_cb_4lyr.sps} + case 1003015712://{terrain_cb_w_4lyr_spec_int_pxm.sps} + case 1927591706://{terrain_cb_w_4lyr_spec_int.sps} + case 3550605441://{terrain_cb_4lyr_lod.sps} //TODO! (used in custom stuff...) + b = TerrainBatches; + break; + #endregion + #region cable batches + case 3854885487://{cable.sps} + b = CableBatches; + break; + #endregion + #region vehicle batches + case 753908000://{vehicle_basic.sps} + case 1107511867://{vehicle_generic.sps} + case 3274951810://{vehicle_paint1.sps} + case 1009159769://{vehicle_paint2.sps} + case 2045642561://{vehicle_paint3.sps} + case 1534086746://{vehicle_paint3_enveff.sps} + case 60950417://{vehicle_paint4_enveff.sps} + case 249472155://{vehicle_paint5_enveff.sps} + case 354168229://{vehicle_paint6_enveff.sps} + case 617726044://{vehicle_mesh.sps} + case 2162256878://{vehicle_tire.sps} + case 3106021319://{vehicle_interior.sps} + case 2837548125://{vehicle_interior2.sps} + case 2094873540://{vehicle_shuts.sps} + case 2405328911://{vehicle_licenseplate.sps} + case 2226589567://{vehicle_lights.sps} + case 364912658://{vehicle_lightsemissive.sps} + case 3030872505://{vehicle_emissive_opaque.sps} + case 146667297://{vehicle_badges.sps} + case 4162395624://{vehicle_dash_emissive.sps} + case 254152173://{vehicle_dash_emissive_opaque.sps} + case 3355845283://{vehicle_detail2.sps} + case 4097152976://{vehicle_track.sps} + case 3631243954://{vehicle_blurredrotor.sps} + case 457610770://{vehicle_nosplash.sps} + case 3621563260://{vehicle_nowater.sps} + b = BasicBatches; + break; + case 1041778472://{vehicle_decal.sps} + case 1462664157://{vehicle_decal2.sps} + b = DecalBatches; + break; + case 3096299666://{vehicle_vehglass.sps} + case 588619930://{vehicle_vehglass_inner.sps} + b = GlassBatches; + break; + case 3986926894://{vehicle_cloth.sps} + b = ClothBatches; + break; + #endregion + #region TODO/unused batches + case 3333227093://{grass_fur.sps} + case 4256676773://{grass_fur_mask.sps} + break;//todo: grass_fur + + case 83630553://{cpv_only.sps} + case 1238547107://{decal_shadow_only.sps} + case 1695474112://{trees_shadow_proxy.sps} + break; //should add this to a shadowproxies group.. but currently don't draw. + #endregion + #region TODO/clouds batches + case 4103916155://{clouds_animsoft.sps} + case 1097000161://{clouds_altitude.sps} + case 1481470665://{clouds_soft.sps} + case 2184108982://{clouds_fast.sps} + case 4192928948://{clouds_anim.sps} + b = BasicBatches; //todo: correct batched cloud rendering... + break; + #endregion + + default: + b = BasicBatches; + break; + } + + if (b != null) + { + b.Add(kvp.Value); + } + + } + } + } + public class ShaderBatch + { + public ShaderKey Key; + public List Geometries = new List(); + + public ShaderBatch(ShaderKey key) + { + Key = key; + } + + public void Clear() + { + Geometries.Clear(); + } + + } + + + public class ShaderGlobalLights + { + public Weather Weather; + public ShaderGlobalLightParams Params; + public Vector3 CurrentSunDir; + public Vector3 CurrentMoonDir; + public Vector3 MoonAxis; + public bool HdrEnabled; + public float HdrIntensity; + public bool SpecularEnabled; + } + public struct ShaderGlobalLightParams + { + public Vector3 LightDir; + public float LightHdr; //global intensity + public Color4 LightDirColour; + public Color4 LightDirAmbColour; + public Color4 LightNaturalAmbUp; + public Color4 LightNaturalAmbDown; + public Color4 LightArtificialAmbUp; + public Color4 LightArtificialAmbDown; + } + + +} diff --git a/Rendering/Shaders/BasicShader.cs b/Rendering/Shaders/BasicShader.cs new file mode 100644 index 0000000..e798c2d --- /dev/null +++ b/Rendering/Shaders/BasicShader.cs @@ -0,0 +1,885 @@ +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX; +using CodeWalker.GameFiles; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct BasicShaderVSSceneVars + { + public Matrix ViewProj; + public Vector4 WindVector; + } + public struct BasicShaderVSEntityVars + { + public Vector4 CamRel; + public Quaternion Orientation; + public uint HasSkeleton; + public uint HasTransforms; + public uint TintPaletteIndex; + public uint Pad1; + public Vector3 Scale; + public uint IsInstanced; + } + public struct BasicShaderVSModelVars + { + public Matrix Transform; + } + public struct BasicShaderVSGeomVars + { + public uint EnableTint; + public float TintYVal; + public uint IsDecal; + public uint EnableWind; + public Vector4 WindOverrideParams; + } + public struct BasicShaderPSSceneVars + { + public ShaderGlobalLightParams GlobalLights; + public uint EnableShadows; + public uint RenderMode;//0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct + public uint RenderModeIndex; //colour/texcoord index + public uint RenderSamplerCoord; //which texcoord to use in single texture mode + } + public struct BasicShaderPSGeomVars + { + public uint EnableTexture; + public uint EnableTint; + public uint EnableNormalMap; + public uint EnableSpecMap; + public uint EnableDetailMap; + public uint IsDecal; + public uint IsEmissive; + public uint IsDistMap; + public float bumpiness; + public float AlphaScale; + public float HardAlphaBlend; + public float useTessellation; + public Vector4 detailSettings; + public Vector3 specMapIntMask; + public float specularIntensityMult; + public float specularFalloffMult; + public float specularFresnel; + public float wetnessMultiplier; + public uint SpecOnly; + } + public struct BasicShaderInstGlobalMatrix + { + public Vector4 Row1; + public Vector4 Row2; + public Vector4 Row3; + } + public struct BasicShaderInstGlobals + { + public BasicShaderInstGlobalMatrix M0; + public BasicShaderInstGlobalMatrix M1; + public BasicShaderInstGlobalMatrix M2; + public BasicShaderInstGlobalMatrix M3; + public BasicShaderInstGlobalMatrix M4; + public BasicShaderInstGlobalMatrix M5; + public BasicShaderInstGlobalMatrix M6; + public BasicShaderInstGlobalMatrix M7; + } + public struct BasicShaderInstLocals + { + public Vector3 vecBatchAabbMin; + public float instPad0; + public Vector3 vecBatchAabbDelta; + public float instPad1; + public Vector4 vecPlayerPos; + public Vector2 _vecCollParams; + public Vector2 instPad2; + public Vector4 fadeAlphaDistUmTimer; + public Vector4 uMovementParams; + public Vector4 _fakedGrassNormal; + public Vector3 gScaleRange; + public float instPad3; + public Vector4 gWindBendingGlobals; + public Vector2 gWindBendScaleVar; + public float gAlphaTest; + public float gAlphaToCoverageScale; + public Vector3 gLodFadeInstRange; + public uint gUseComputeShaderOutputBuffer; + } + + public class BasicShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader basicvspnct; + VertexShader basicvspncct; + VertexShader basicvspncctt; + VertexShader basicvspnccttt; + VertexShader basicvspnctx; + VertexShader basicvspncctx; + VertexShader basicvspncttx; + VertexShader basicvspnccttx; + VertexShader basicvspnctttx; + VertexShader basicvspncctttx; + VertexShader basicvsbox; + VertexShader basicvssphere; + VertexShader basicvscapsule; + VertexShader basicvscylinder; + PixelShader basicps; + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSEntityVars; + GpuVarsBuffer VSModelVars; + GpuVarsBuffer VSGeomVars; + GpuVarsBuffer PSSceneVars; + GpuVarsBuffer PSGeomVars; + GpuVarsBuffer InstGlobalVars; + GpuVarsBuffer InstLocalVars; + SamplerState texsampler; + SamplerState texsampleranis; + SamplerState texsamplertnt; + SamplerState texsamplertntyft; + UnitCube cube; //for collision box render + UnitSphere sphere; //for collision sphere render + UnitCapsule capsule; //for collision capsule render + UnitCylinder cylinder; //for collision cylinder render + + public bool AnisotropicFilter = false; + public bool DecalMode = false; + public float AlphaScale = 1.0f; + public Vector4 WindVector = Vector4.Zero; + public WorldRenderMode RenderMode = WorldRenderMode.Default; + public int RenderVertexColourIndex = 1; + public int RenderTextureCoordIndex = 1; + public int RenderTextureSamplerCoord = 1; + public MetaName RenderTextureSampler = MetaName.DiffuseSampler; + public bool SpecularEnable = true; + + + + private Dictionary layouts = new Dictionary(); + + public BasicShader(Device device) + { + byte[] vspnctbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCT.cso"); + byte[] vspncctbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCT.cso"); + byte[] vspnccttbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTT.cso"); + byte[] vspncctttbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTT.cso"); + byte[] vspnctxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTX.cso"); + byte[] vspncctxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTX.cso"); + byte[] vspncttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTTX.cso"); + byte[] vspnccttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTX.cso"); + byte[] vspnctttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTTTX.cso"); + byte[] vspncctttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTTX.cso"); + byte[] vsboxbytes = File.ReadAllBytes("Shaders\\BasicVS_Box.cso"); + byte[] vsspherebytes = File.ReadAllBytes("Shaders\\BasicVS_Sphere.cso"); + byte[] vscapsulebytes = File.ReadAllBytes("Shaders\\BasicVS_Capsule.cso"); + byte[] vscylinderbytes = File.ReadAllBytes("Shaders\\BasicVS_Cylinder.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\BasicPS.cso"); + + basicvspnct = new VertexShader(device, vspnctbytes); + basicvspncct = new VertexShader(device, vspncctbytes); + basicvspncctt = new VertexShader(device, vspnccttbytes); + basicvspnccttt = new VertexShader(device, vspncctttbytes); + basicvspnctx = new VertexShader(device, vspnctxbytes); + basicvspncctx = new VertexShader(device, vspncctxbytes); + basicvspncttx = new VertexShader(device, vspncttxbytes); + basicvspnccttx = new VertexShader(device, vspnccttxbytes); + basicvspnctttx = new VertexShader(device, vspnctttxbytes); + basicvspncctttx = new VertexShader(device, vspncctttxbytes); + basicvsbox = new VertexShader(device, vsboxbytes); + basicvssphere = new VertexShader(device, vsspherebytes); + basicvscapsule = new VertexShader(device, vscapsulebytes); + basicvscylinder = new VertexShader(device, vscylinderbytes); + basicps = new PixelShader(device, psbytes); + + VSSceneVars = new GpuVarsBuffer(device); + VSEntityVars = new GpuVarsBuffer(device); + VSModelVars = new GpuVarsBuffer(device); + VSGeomVars = new GpuVarsBuffer(device); + PSSceneVars = new GpuVarsBuffer(device); + PSGeomVars = new GpuVarsBuffer(device); + InstGlobalVars = new GpuVarsBuffer(device); + InstLocalVars = new GpuVarsBuffer(device); + + InitInstGlobalVars(); + + + //supported layouts - requires Position, Normal, Colour, Texcoord + layouts.Add(VertexType.Default, new InputLayout(device, vspnctbytes, VertexTypeDefault.GetLayout())); + layouts.Add(VertexType.PNCH2, new InputLayout(device, vspnctbytes, VertexTypePNCH2.GetLayout())); + + layouts.Add(VertexType.PCCNCT, new InputLayout(device, vspncctbytes, VertexTypePCCNCT.GetLayout())); + layouts.Add(VertexType.PCCNCCT, new InputLayout(device, vspncctbytes, VertexTypePCCNCCT.GetLayout())); + layouts.Add(VertexType.PNCCT, new InputLayout(device, vspncctbytes, VertexTypePNCCT.GetLayout())); + layouts.Add(VertexType.PNCCTT, new InputLayout(device, vspnccttbytes, VertexTypePNCCTT.GetLayout())); + layouts.Add(VertexType.PNCCTTTT, new InputLayout(device, vspncctttbytes, VertexTypePNCCTTTT.GetLayout())); + + + //normalmap layouts - requires Position, Normal, Colour, Texcoord, Tangent (X) + layouts.Add(VertexType.DefaultEx, new InputLayout(device, vspnctxbytes, VertexTypeDefaultEx.GetLayout())); + layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vspnctxbytes, VertexTypePCCH2H4.GetLayout())); + + layouts.Add(VertexType.PCCNCTX, new InputLayout(device, vspncctxbytes, VertexTypePCCNCTX.GetLayout())); + layouts.Add(VertexType.PCCNCCTX, new InputLayout(device, vspncctxbytes, VertexTypePCCNCCTX.GetLayout())); + layouts.Add(VertexType.PNCCTX, new InputLayout(device, vspncctxbytes, VertexTypePNCCTX.GetLayout())); + layouts.Add(VertexType.PNCTTX, new InputLayout(device, vspncttxbytes, VertexTypePNCTTX.GetLayout())); + layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vspnccttxbytes, VertexTypePNCCTTX.GetLayout())); + layouts.Add(VertexType.PNCCTTX_2, new InputLayout(device, vspnccttxbytes, VertexTypePNCCTTX_2.GetLayout())); + layouts.Add(VertexType.PCCNCCTTX, new InputLayout(device, vspnccttxbytes, VertexTypePCCNCCTTX.GetLayout())); + layouts.Add(VertexType.PNCTTTX, new InputLayout(device, vspnctttxbytes, VertexTypePNCTTTX.GetLayout())); + layouts.Add(VertexType.PNCTTTX_2, new InputLayout(device, vspnctttxbytes, VertexTypePNCTTTX_2.GetLayout())); + layouts.Add(VertexType.PNCTTTX_3, new InputLayout(device, vspnctttxbytes, VertexTypePNCTTTX_3.GetLayout())); + layouts.Add(VertexType.PNCTTTTX, new InputLayout(device, vspnctttxbytes, VertexTypePNCTTTTX.GetLayout())); + layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vspncctttxbytes, VertexTypePNCCTTTX.GetLayout())); + + + layouts.Add(VertexType.PCCNCTT, new InputLayout(device, vspnccttbytes, VertexTypePCCNCTT.GetLayout())); + layouts.Add(VertexType.PCCNCTTX, new InputLayout(device, vspnccttxbytes, VertexTypePCCNCTTX.GetLayout())); + layouts.Add(VertexType.PCCNCTTT, new InputLayout(device, vspncctttbytes, VertexTypePCCNCTTT.GetLayout())); + layouts.Add(VertexType.PNCTT, new InputLayout(device, vspnctbytes, VertexTypePNCTT.GetLayout())); + layouts.Add(VertexType.PNCTTT, new InputLayout(device, vspnctbytes, VertexTypePNCTTT.GetLayout())); + + + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsampleranis = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.Anisotropic, + MaximumAnisotropy = 8, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsamplertnt = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Clamp, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.White, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipPoint, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsamplertntyft = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.White, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipPoint, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + + + cube = new UnitCube(device, vsboxbytes, false, false, true); + sphere = new UnitSphere(device, vsspherebytes, 4); + capsule = new UnitCapsule(device, vscapsulebytes, 4); + cylinder = new UnitCylinder(device, vscylinderbytes, 8); + } + + private void InitInstGlobalVars() + { + var m0 = Matrix3x3.RotationZ(0.00f * (float)Math.PI); + var m1 = Matrix3x3.RotationZ(0.25f * (float)Math.PI); + var m2 = Matrix3x3.RotationZ(0.50f * (float)Math.PI); + var m3 = Matrix3x3.RotationZ(0.75f * (float)Math.PI); + var m4 = Matrix3x3.RotationZ(1.00f * (float)Math.PI); + var m5 = Matrix3x3.RotationZ(1.25f * (float)Math.PI); + var m6 = Matrix3x3.RotationZ(1.50f * (float)Math.PI); + var m7 = Matrix3x3.RotationZ(1.75f * (float)Math.PI); + + InstGlobalVars.Vars.M0.Row1 = new Vector4(m0.Row1, 1); + InstGlobalVars.Vars.M0.Row2 = new Vector4(m0.Row2, 1); + InstGlobalVars.Vars.M0.Row3 = new Vector4(m0.Row3, 1); + InstGlobalVars.Vars.M1.Row1 = new Vector4(m1.Row1, 1); + InstGlobalVars.Vars.M1.Row2 = new Vector4(m1.Row2, 1); + InstGlobalVars.Vars.M1.Row3 = new Vector4(m1.Row3, 1); + InstGlobalVars.Vars.M2.Row1 = new Vector4(m2.Row1, 1); + InstGlobalVars.Vars.M2.Row2 = new Vector4(m2.Row2, 1); + InstGlobalVars.Vars.M2.Row3 = new Vector4(m2.Row3, 1); + InstGlobalVars.Vars.M3.Row1 = new Vector4(m3.Row1, 1); + InstGlobalVars.Vars.M3.Row2 = new Vector4(m3.Row2, 1); + InstGlobalVars.Vars.M3.Row3 = new Vector4(m3.Row3, 1); + InstGlobalVars.Vars.M4.Row1 = new Vector4(m4.Row1, 1); + InstGlobalVars.Vars.M4.Row2 = new Vector4(m4.Row2, 1); + InstGlobalVars.Vars.M4.Row3 = new Vector4(m4.Row3, 1); + InstGlobalVars.Vars.M5.Row1 = new Vector4(m5.Row1, 1); + InstGlobalVars.Vars.M5.Row2 = new Vector4(m5.Row2, 1); + InstGlobalVars.Vars.M5.Row3 = new Vector4(m5.Row3, 1); + InstGlobalVars.Vars.M6.Row1 = new Vector4(m6.Row1, 1); + InstGlobalVars.Vars.M6.Row2 = new Vector4(m6.Row2, 1); + InstGlobalVars.Vars.M6.Row3 = new Vector4(m6.Row3, 1); + InstGlobalVars.Vars.M7.Row1 = new Vector4(m7.Row1, 1); + InstGlobalVars.Vars.M7.Row2 = new Vector4(m7.Row2, 1); + InstGlobalVars.Vars.M7.Row3 = new Vector4(m7.Row3, 1); + + } + + + private void SetVertexShader(DeviceContext context, VertexType type) + { + VertexShader vs = basicvspnct; + switch (type) + { + case VertexType.Default: + case VertexType.PNCH2: + case VertexType.PNCTT: + case VertexType.PNCTTT: + vs = basicvspnct; + break; + case VertexType.PCCNCT: + case VertexType.PCCNCCT: + case VertexType.PNCCT: + vs = basicvspncct; + break; + case VertexType.PNCCTT://not used? + case VertexType.PCCNCTT: + vs = basicvspncctt; + break; + case VertexType.PNCCTTTT://not used? + case VertexType.PCCNCTTT: + vs = basicvspnccttt; + break; + case VertexType.DefaultEx: + case VertexType.PCCH2H4: + vs = basicvspnctx; + break; + + case VertexType.PCCNCTX: + case VertexType.PCCNCCTX: + case VertexType.PNCCTX: + vs = basicvspncctx; + break; + + case VertexType.PNCTTX: + vs = basicvspncttx; + break; + + case VertexType.PNCCTTX://not used? + case VertexType.PNCCTTX_2://not used? + case VertexType.PCCNCCTTX://not used? + case VertexType.PCCNCTTX: + vs = basicvspnccttx; + break; + + case VertexType.PNCTTTX: + case VertexType.PNCTTTX_2: + case VertexType.PNCTTTX_3: + case VertexType.PNCTTTTX: //not using last texcoords! + vs = basicvspnctttx; + break; + + case VertexType.PNCCTTTX://not used? + vs = basicvspncctttx; + break; + + default: + break; + + } + context.VertexShader.Set(vs); + } + + + public override void SetShader(DeviceContext context) + { + context.PixelShader.Set(basicps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + InputLayout l; + if (layouts.TryGetValue(type, out l)) + { + SetVertexShader(context, type); + context.InputAssembler.InputLayout = l; + return true; + } + return false; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + uint rendermode = 0; + uint rendermodeind = 1; + + SpecularEnable = lights.SpecularEnabled; + + switch (RenderMode) + { + case WorldRenderMode.VertexNormals: + rendermode = 1; + break; + case WorldRenderMode.VertexTangents: + rendermode = 2; + break; + case WorldRenderMode.VertexColour: + rendermode = 3; + rendermodeind = (uint)RenderVertexColourIndex; + break; + case WorldRenderMode.TextureCoord: + rendermode = 4; + rendermodeind = (uint)RenderTextureCoordIndex; + break; + case WorldRenderMode.SingleTexture: + rendermode = 8;//direct mode + break; + } + + + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Vars.WindVector = WindVector; + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + + PSSceneVars.Vars.GlobalLights = lights.Params; + PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u; + PSSceneVars.Vars.RenderMode = rendermode; + PSSceneVars.Vars.RenderModeIndex = rendermodeind; + PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord; + PSSceneVars.Update(context); + PSSceneVars.SetPSCBuffer(context, 0); + + if (shadowmap != null) + { + shadowmap.SetFinalRenderResources(context); + } + + if (!InstGlobalVars.Flag) //on the first frame, update the instance globals + { + InstGlobalVars.Update(context); + InstGlobalVars.Flag = true; + } + + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = rend.Orientation; + VSEntityVars.Vars.Scale = rend.Scale; + VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0; + VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0; + VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex; + VSEntityVars.Vars.IsInstanced = 0; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + } + + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + if (!model.UseTransform) return; + VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform); + VSModelVars.Update(context); + VSModelVars.SetVSCBuffer(context, 3); + } + + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + RenderableTexture texture = null; + RenderableTexture tintpal = null; + RenderableTexture bumptex = null; + RenderableTexture spectex = null; + RenderableTexture detltex = null; + bool isdistmap = false; + + float tntpalind = 0.0f; + if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0)) + { + if (RenderMode == WorldRenderMode.Default) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + if (itex == null) continue; + switch (ihash) + { + case MetaName.DiffuseSampler: + texture = itex; + break; + case MetaName.BumpSampler: + bumptex = itex; + break; + case MetaName.SpecSampler: + spectex = itex; + break; + case MetaName.DetailSampler: + detltex = itex; + break; + case MetaName.TintPaletteSampler: + tintpal = itex; + if (tintpal.Key != null) + { + //this is slightly dodgy but VSEntityVars should have the correct value in it... + tntpalind = (VSEntityVars.Vars.TintPaletteIndex + 0.5f) / tintpal.Key.Height; + } + break; + case MetaName.distanceMapSampler: + texture = itex; + isdistmap = true; + break; + case MetaName.heightSampler: + case MetaName.EnvironmentSampler: + break; + case MetaName.FlowSampler: + case MetaName.FogSampler: + case MetaName.FoamSampler: + if (texture == null) texture = itex; + break; + default: + if (texture == null) texture = itex; + break; + } + } + } + else if (RenderMode == WorldRenderMode.SingleTexture) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + if (ihash == RenderTextureSampler) + { + texture = itex; + break; + } + } + } + } + + + bool usediff = ((texture != null) && (texture.ShaderResourceView != null)); + bool usebump = ((bumptex != null) && (bumptex.ShaderResourceView != null)); + bool usespec = ((spectex != null) && (spectex.ShaderResourceView != null)); + bool usedetl = ((detltex != null) && (detltex.ShaderResourceView != null)); + bool usetint = ((tintpal != null) && (tintpal.ShaderResourceView != null)); + + uint tintflag = 0; + if (usetint) tintflag = 1; + + uint windflag = geom.EnableWind ? 1u : 0u; + uint emflag = geom.IsEmissive ? 1u : 0u; + var shaderName = geom.DrawableGeom.Shader.Name; + var shaderFile = geom.DrawableGeom.Shader.FileName; + switch (shaderFile.Hash) + { + case 2245870123: //trees_normal_diffspec_tnt.sps + case 3334613197: //trees_tnt.sps + case 1229591973://{trees_normal_spec_tnt.sps} + if (usetint) tintflag = 2; //use 2nd vertex colour channel for tint... + break; + case 3880384844://{decal_spec_only.sps}w + case 600733812://{decal_amb_only.sps} + case 2842248626://{spec_decal.sps} + case 2457676400://{reflect_decal.sps} + case 2706821972://{mirror_decal.sps} + //if (RenderMode == WorldRenderMode.Default) usediff = false; + break; + } + + uint pstintflag = tintflag; + if (VSEntityVars.Vars.IsInstanced>0) + { + pstintflag = 1; + switch (shaderFile.Hash) + { + case 916743331: //{grass_batch.sps} + windflag = 1; + break; + case 3833671083://{normal_spec_batch.sps} + windflag = 0; + break; + default: + break; + } + } + + + PSGeomVars.Vars.EnableTexture = usediff ? 1u : 0u; + PSGeomVars.Vars.EnableTint = pstintflag; + PSGeomVars.Vars.EnableNormalMap = usebump ? 1u : 0u; + PSGeomVars.Vars.EnableSpecMap = usespec ? 1u : 0u; + PSGeomVars.Vars.EnableDetailMap = usedetl ? 1u : 0u; + PSGeomVars.Vars.IsDecal = DecalMode ? 1u : 0u; + PSGeomVars.Vars.IsEmissive = emflag; + PSGeomVars.Vars.IsDistMap = isdistmap ? 1u : 0u; + PSGeomVars.Vars.bumpiness = geom.bumpiness; + PSGeomVars.Vars.AlphaScale = isdistmap ? 1.0f : AlphaScale; + PSGeomVars.Vars.HardAlphaBlend = 0.0f; //todo: cutouts flag! + PSGeomVars.Vars.useTessellation = 0.0f; + PSGeomVars.Vars.detailSettings = geom.detailSettings; + PSGeomVars.Vars.specMapIntMask = geom.specMapIntMask; + PSGeomVars.Vars.specularIntensityMult = SpecularEnable ? geom.specularIntensityMult : 0.0f; + PSGeomVars.Vars.specularFalloffMult = geom.specularFalloffMult; + PSGeomVars.Vars.specularFresnel = geom.specularFresnel; + PSGeomVars.Vars.wetnessMultiplier = geom.wetnessMultiplier; + PSGeomVars.Vars.SpecOnly = geom.SpecOnly ? 1u : 0u; + PSGeomVars.Update(context); + PSGeomVars.SetPSCBuffer(context, 2); + + VSGeomVars.Vars.EnableTint = tintflag; + VSGeomVars.Vars.TintYVal = tntpalind; + VSGeomVars.Vars.IsDecal = DecalMode ? 1u : 0u; + VSGeomVars.Vars.EnableWind = windflag; + VSGeomVars.Vars.WindOverrideParams = geom.WindOverrideParams; + VSGeomVars.Update(context); + VSGeomVars.SetVSCBuffer(context, 4); + + context.VertexShader.SetSampler(0, geom.IsFragment ? texsamplertntyft : texsamplertnt); + context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler); + if (usediff) + { + texture.SetPSResource(context, 0); + } + if (usebump) + { + bumptex.SetPSResource(context, 2); + } + if (usespec) + { + spectex.SetPSResource(context, 3); + } + if (usedetl) + { + detltex.SetPSResource(context, 4); + } + if (usetint) + { + tintpal.SetVSResource(context, 0); + } + } + + + public void SetInstanceVars(DeviceContext context, RenderableInstanceBatch batch) + { + var gb = batch.Key; + + VSEntityVars.Vars.CamRel = new Vector4(gb.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = Quaternion.Identity; + VSEntityVars.Vars.Scale = Vector3.One; + VSEntityVars.Vars.HasSkeleton = 0; + VSEntityVars.Vars.HasTransforms = 0; + VSEntityVars.Vars.TintPaletteIndex = 0; + VSEntityVars.Vars.IsInstanced = 1; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + + InstGlobalVars.SetVSCBuffer(context, 5); + + InstLocalVars.Vars.vecBatchAabbMin = gb.AABBMin; + InstLocalVars.Vars.vecBatchAabbDelta = gb.AABBMax - gb.AABBMin; + InstLocalVars.Vars.vecPlayerPos = new Vector4(gb.Position - gb.CamRel, 1.0f); + InstLocalVars.Vars._vecCollParams = new Vector2(2.0f, -3.0f);//range, offset + InstLocalVars.Vars.fadeAlphaDistUmTimer = new Vector4(0.0f); + InstLocalVars.Vars.uMovementParams = new Vector4(0.0f); + InstLocalVars.Vars._fakedGrassNormal = new Vector4(Vector3.Normalize(-gb.CamRel), 0.0f); + InstLocalVars.Vars.gScaleRange = gb.Batch.ScaleRange; + InstLocalVars.Vars.gWindBendingGlobals = new Vector4(WindVector.X, WindVector.Y, 1.0f, 1.0f); + InstLocalVars.Vars.gWindBendScaleVar = new Vector2(WindVector.Z, WindVector.W); + InstLocalVars.Vars.gAlphaTest = 0.0f; + InstLocalVars.Vars.gAlphaToCoverageScale = 1.0f; + InstLocalVars.Vars.gLodFadeInstRange = new Vector3(gb.Batch.LodInstFadeRange, gb.Batch.LodFadeStartDist, gb.Batch.lodDist); + InstLocalVars.Vars.gUseComputeShaderOutputBuffer = 0; + InstLocalVars.Update(context); + InstLocalVars.SetVSCBuffer(context, 6); + + + context.VertexShader.SetShaderResource(2, batch.GrassInstanceBuffer.SRV); + } + + + public void RenderBoundGeom(DeviceContext context, RenderableBoundGeometryInst inst) + { + + + VSEntityVars.Vars.CamRel = new Vector4(inst.Inst.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = inst.Inst.Orientation; + VSEntityVars.Vars.Scale = inst.Inst.Scale; + VSEntityVars.Vars.HasSkeleton = 0; + VSEntityVars.Vars.HasTransforms = 0; //todo! bounds transforms..? + VSEntityVars.Vars.TintPaletteIndex = 0; + VSEntityVars.Vars.IsInstanced = 0; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + + PSGeomVars.Vars.EnableTexture = 0; + PSGeomVars.Vars.EnableTint = 0; + PSGeomVars.Vars.EnableNormalMap = 0; + PSGeomVars.Vars.EnableSpecMap = 0; + PSGeomVars.Vars.EnableDetailMap = 0; + PSGeomVars.Vars.IsDecal = 0; + PSGeomVars.Vars.IsEmissive = 0; + PSGeomVars.Vars.IsDistMap = 0; + PSGeomVars.Vars.bumpiness = 0; + PSGeomVars.Vars.AlphaScale = 1; + PSGeomVars.Vars.HardAlphaBlend = 0; + PSGeomVars.Vars.useTessellation = 0; + PSGeomVars.Vars.detailSettings = Vector4.Zero; + PSGeomVars.Vars.specMapIntMask = Vector3.Zero; + PSGeomVars.Vars.specularIntensityMult = 1.0f; + PSGeomVars.Vars.specularFalloffMult = 1.0f; + PSGeomVars.Vars.specularFresnel = 1.0f; + PSGeomVars.Vars.wetnessMultiplier = 0.0f; + PSGeomVars.Vars.SpecOnly = 0; + PSGeomVars.Update(context); + PSGeomVars.SetPSCBuffer(context, 2); + + VSGeomVars.Vars.EnableTint = 0; + VSGeomVars.Vars.TintYVal = 0.0f; + VSGeomVars.Vars.IsDecal = 0; + VSGeomVars.Vars.EnableWind = 0; + VSGeomVars.Vars.WindOverrideParams = Vector4.Zero; + VSGeomVars.Update(context); + VSGeomVars.SetVSCBuffer(context, 4); + + + if (inst.Geom.VertexBuffer != null) //render the triangles + { + SetVertexShader(context, VertexType.Default); + SetInputLayout(context, VertexType.Default); + inst.Geom.RenderTriangles(context); + } + + //render the boxes + if (inst.Geom.BoxBuffer != null) + { + context.VertexShader.Set(basicvsbox); + context.VertexShader.SetShaderResource(1, inst.Geom.BoxBuffer.SRV); + cube.DrawInstanced(context, inst.Geom.BoxBuffer.StructCount); + } + + //render the spheres + if (inst.Geom.SphereBuffer != null) + { + context.VertexShader.Set(basicvssphere); + context.VertexShader.SetShaderResource(1, inst.Geom.SphereBuffer.SRV); + sphere.DrawInstanced(context, inst.Geom.SphereBuffer.StructCount); + } + + //render the capsules + if (inst.Geom.CapsuleBuffer != null) + { + context.VertexShader.Set(basicvscapsule); + context.VertexShader.SetShaderResource(1, inst.Geom.CapsuleBuffer.SRV); + capsule.DrawInstanced(context, inst.Geom.CapsuleBuffer.StructCount); + } + + //render the cylinders + if (inst.Geom.CylinderBuffer != null) + { + context.VertexShader.Set(basicvscylinder); + context.VertexShader.SetShaderResource(1, inst.Geom.CylinderBuffer.SRV); + cylinder.DrawInstanced(context, inst.Geom.CylinderBuffer.StructCount); + } + + + } + + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); //shadowmap + context.PixelShader.SetConstantBuffer(1, null); //shadowmap + context.PixelShader.SetShaderResource(1, null);//shadowmap + context.PixelShader.SetSampler(1, null); //shadowmap + context.VertexShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(3, null); + context.PixelShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(4, null); + context.VertexShader.SetConstantBuffer(5, null); + context.VertexShader.SetConstantBuffer(6, null); + context.VertexShader.SetSampler(0, null); + context.PixelShader.SetSampler(0, null); + context.PixelShader.SetShaderResource(0, null); + context.PixelShader.SetShaderResource(2, null); + context.PixelShader.SetShaderResource(3, null); + context.PixelShader.SetShaderResource(4, null); + context.VertexShader.SetShaderResource(0, null); + context.VertexShader.SetShaderResource(1, null); + context.VertexShader.SetShaderResource(2, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + public void Dispose() + { + if (disposed) return; + + cube.Dispose(); + sphere.Dispose(); + capsule.Dispose(); + cylinder.Dispose(); + + texsampler.Dispose(); + texsampleranis.Dispose(); + texsamplertnt.Dispose(); + + foreach (InputLayout layout in layouts.Values) + { + layout.Dispose(); + } + layouts.Clear(); + + VSSceneVars.Dispose(); + VSEntityVars.Dispose(); + VSModelVars.Dispose(); + VSGeomVars.Dispose(); + PSSceneVars.Dispose(); + PSGeomVars.Dispose(); + InstGlobalVars.Dispose(); + InstLocalVars.Dispose(); + + basicps.Dispose(); + basicvspnct.Dispose(); + basicvspncct.Dispose(); + basicvspncctt.Dispose(); + basicvspnccttt.Dispose(); + basicvspnctx.Dispose(); + basicvspncctx.Dispose(); + basicvspncttx.Dispose(); + basicvspnccttx.Dispose(); + basicvspnctttx.Dispose(); + basicvspncctttx.Dispose(); + basicvsbox.Dispose(); + basicvssphere.Dispose(); + basicvscapsule.Dispose(); + basicvscylinder.Dispose(); + + disposed = true; + } + } +} diff --git a/Rendering/Shaders/BoundsShader.cs b/Rendering/Shaders/BoundsShader.cs new file mode 100644 index 0000000..33656c4 --- /dev/null +++ b/Rendering/Shaders/BoundsShader.cs @@ -0,0 +1,239 @@ +using SharpDX; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using CodeWalker.GameFiles; +using System.IO; +using SharpDX.DXGI; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct BoundingSphereVSSceneVars + { + public Matrix ViewProj; + public Matrix ViewInv; + public float SegmentCount; + public float VertexCount; + public float Pad1; + public float Pad2; + } + public struct BoundingSphereVSSphereVars + { + public Vector3 Center; + public float Radius; + } + public struct BoundingBoxVSSceneVars + { + public Matrix ViewProj; + } + public struct BoundingBoxVSBoxVars + { + public Quaternion Orientation; + public Vector4 BBMin; + public Vector4 BBRng; //max-min + public Vector3 CamRel; + public float Pad1; + public Vector3 Scale; + public float Pad2; + } + public struct BoundsPSColourVars + { + public Vector4 Colour; + } + + + public class BoundsShader : Shader, IDisposable + { + bool disposed = false; + + BoundsShaderMode mode = BoundsShaderMode.Sphere; + VertexShader spherevs; + VertexShader boxvs; + PixelShader boundsps; + + GpuVarsBuffer VSSphereSceneVars; + GpuVarsBuffer VSSphereVars; + GpuVarsBuffer VSBoxSceneVars; + GpuVarsBuffer VSBoxVars; + GpuVarsBuffer PSColourVars; + + int SegmentCount = 64; + int VertexCount = 65; + UnitCube cube; + + public BoundsShader(Device device) + { + byte[] spherevsbytes = File.ReadAllBytes("Shaders\\BoundingSphereVS.cso"); + byte[] boxvsbytes = File.ReadAllBytes("Shaders\\BoundingBoxVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\BoundsPS.cso"); + + spherevs = new VertexShader(device, spherevsbytes); + boxvs = new VertexShader(device, boxvsbytes); + boundsps = new PixelShader(device, psbytes); + + VSSphereSceneVars = new GpuVarsBuffer(device); + VSSphereVars = new GpuVarsBuffer(device); + VSBoxSceneVars = new GpuVarsBuffer(device); + VSBoxVars = new GpuVarsBuffer(device); + PSColourVars = new GpuVarsBuffer(device); + + cube = new UnitCube(device, boxvsbytes, false, true, false); + } + + + public void SetMode(BoundsShaderMode m) + { + mode = m; + } + + public override void SetShader(DeviceContext context) + { + switch (mode) + { + default: + case BoundsShaderMode.Sphere: + context.VertexShader.Set(spherevs); + break; + case BoundsShaderMode.Box: + context.VertexShader.Set(boxvs); + break; + } + context.PixelShader.Set(boundsps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + //switch (mode) + //{ + // default: + // case BoundsShaderMode.Sphere: + // context.InputAssembler.InputLayout = null; + // break; + // case BoundsShaderMode.Box: + // context.InputAssembler.InputLayout = cube.InputLayout; + // break; + //} + return true; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + switch (mode) + { + default: + case BoundsShaderMode.Sphere: + VSSphereSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSphereSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix); + VSSphereSceneVars.Vars.SegmentCount = (float)SegmentCount; + VSSphereSceneVars.Vars.VertexCount = (float)VertexCount; + VSSphereSceneVars.Update(context); + VSSphereSceneVars.SetVSCBuffer(context, 0); + break; + case BoundsShaderMode.Box: + VSBoxSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSBoxSceneVars.Update(context); + VSBoxSceneVars.SetVSCBuffer(context, 0); + break; + } + } + + public void SetSphereVars(DeviceContext context, Vector3 center, float radius) + { + VSSphereVars.Vars.Center = center; + VSSphereVars.Vars.Radius = radius; + VSSphereVars.Update(context); + VSSphereVars.SetVSCBuffer(context, 1); + } + + public void SetBoxVars(DeviceContext context, Vector3 camrel, Vector3 bbmin, Vector3 bbmax, Quaternion orientation, Vector3 scale) + { + VSBoxVars.Vars.Orientation = orientation; + VSBoxVars.Vars.BBMin = new Vector4(bbmin, 0.0f); + VSBoxVars.Vars.BBRng = new Vector4(bbmax - bbmin, 0.0f); + VSBoxVars.Vars.CamRel = camrel; + VSBoxVars.Vars.Scale = scale; + VSBoxVars.Update(context); + VSBoxVars.SetVSCBuffer(context, 1); + } + + public void SetColourVars(DeviceContext context, Vector4 colour) + { + PSColourVars.Vars.Colour = colour; + PSColourVars.Update(context); + PSColourVars.SetPSCBuffer(context, 0); + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + //don't use this one + } + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + //don't use this + } + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + //don't use this + } + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + public void DrawSphere(DeviceContext context) + { + context.InputAssembler.InputLayout = null; + context.InputAssembler.SetIndexBuffer(null, Format.Unknown, 0); + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineStrip; + context.Draw(VertexCount, 0); + } + + public void DrawBox(DeviceContext context) + { + cube.Draw(context); + } + + + public void Dispose() + { + if (disposed) return; + + VSSphereSceneVars.Dispose(); + VSSphereVars.Dispose(); + VSBoxSceneVars.Dispose(); + VSBoxVars.Dispose(); + PSColourVars.Dispose(); + + cube.Dispose(); + + boundsps.Dispose(); + boxvs.Dispose(); + spherevs.Dispose(); + + disposed = true; + } + + } + + public enum BoundsShaderMode + { + None = 0, + Sphere = 1, + Box = 2, + } + +} diff --git a/Rendering/Shaders/CableShader.cs b/Rendering/Shaders/CableShader.cs new file mode 100644 index 0000000..74aefb8 --- /dev/null +++ b/Rendering/Shaders/CableShader.cs @@ -0,0 +1,345 @@ +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX; +using CodeWalker.GameFiles; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct CableShaderVSSceneVars + { + public Matrix ViewProj; + } + public struct CableShaderVSEntityVars + { + public Vector4 CamRel; + public Quaternion Orientation; + public uint HasSkeleton; + public uint HasTransforms; + public uint TintPaletteIndex; + public uint Pad1; + public Vector3 Scale; + public uint IsInstanced; + } + public struct CableShaderVSModelVars + { + public Matrix Transform; + } + public struct CableShaderVSGeomVars + { + public uint EnableTint; + public float TintYVal; + public uint IsDecal; + public uint Pad5; + } + public struct CableShaderPSSceneVars + { + public ShaderGlobalLightParams GlobalLights; + public uint EnableShadows; + public uint RenderMode;//0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct + public uint RenderModeIndex; //colour/texcoord index + public uint RenderSamplerCoord; //which texcoord to use in single texture mode + } + public struct CableShaderPSGeomVars + { + public uint EnableTexture; + public uint EnableTint; + public uint Pad100; + public uint Pad101; + } + + public class CableShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader vs; + PixelShader ps; + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSEntityVars; + GpuVarsBuffer VSModelVars; + GpuVarsBuffer VSGeomVars; + GpuVarsBuffer PSSceneVars; + GpuVarsBuffer PSGeomVars; + SamplerState texsampler; + + public WorldRenderMode RenderMode = WorldRenderMode.Default; + public int RenderVertexColourIndex = 1; + public int RenderTextureCoordIndex = 1; + public int RenderTextureSamplerCoord = 1; + public MetaName RenderTextureSampler = MetaName.DiffuseSampler; + + + private Dictionary layouts = new Dictionary(); + + public CableShader(Device device) + { + byte[] vsbytes = File.ReadAllBytes("Shaders\\CableVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\CablePS.cso"); + + vs = new VertexShader(device, vsbytes); + ps = new PixelShader(device, psbytes); + + + VSSceneVars = new GpuVarsBuffer(device); + VSEntityVars = new GpuVarsBuffer(device); + VSModelVars = new GpuVarsBuffer(device); + VSGeomVars = new GpuVarsBuffer(device); + PSSceneVars = new GpuVarsBuffer(device); + PSGeomVars = new GpuVarsBuffer(device); + + + //supported layout - requires Position, Normal, Colour, Texcoord + layouts.Add(VertexType.Default, new InputLayout(device, vsbytes, VertexTypeDefault.GetLayout())); + + + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + } + + + private void SetVertexShader(DeviceContext context, VertexType type) + { + switch (type) + { + case VertexType.Default: + break; + default: + break; + } + context.VertexShader.Set(vs); + } + + + public override void SetShader(DeviceContext context) + { + context.PixelShader.Set(ps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + InputLayout l; + if (layouts.TryGetValue(type, out l)) + { + SetVertexShader(context, type); + context.InputAssembler.InputLayout = l; + return true; + } + return false; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + uint rendermode = 0; + uint rendermodeind = 1; + + switch (RenderMode) + { + case WorldRenderMode.VertexNormals: + rendermode = 1; + break; + case WorldRenderMode.VertexTangents: + rendermode = 2; + break; + case WorldRenderMode.VertexColour: + rendermode = 3; + rendermodeind = (uint)RenderVertexColourIndex; + break; + case WorldRenderMode.TextureCoord: + rendermode = 4; + rendermodeind = (uint)RenderTextureCoordIndex; + break; + case WorldRenderMode.SingleTexture: + rendermode = 8;//direct mode + break; + } + + + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + + PSSceneVars.Vars.GlobalLights = lights.Params; + PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u; + PSSceneVars.Vars.RenderMode = rendermode; + PSSceneVars.Vars.RenderModeIndex = rendermodeind; + PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord; + PSSceneVars.Update(context); + PSSceneVars.SetPSCBuffer(context, 0); + + if (shadowmap != null) + { + shadowmap.SetFinalRenderResources(context); + } + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = rend.Orientation; + VSEntityVars.Vars.Scale = rend.Scale; + VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0; + VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0; + VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex; + VSEntityVars.Vars.IsInstanced = 0; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + } + + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + if (!model.UseTransform) return; + VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform); + VSModelVars.Update(context); + VSModelVars.SetVSCBuffer(context, 3); + } + + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + RenderableTexture texture = null; // ((geom.Textures != null) && (geom.Textures.Length > 0)) ? geom.Textures[0] : null; + + if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0)) + { + + if (RenderMode == WorldRenderMode.Default) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + switch (ihash) + { + case MetaName.DiffuseSampler: + texture = itex; + break; + } + } + + + ////fallback try get first texture... eventaully remove this! (helps with water for now) + //int index = 0; + //while (((texture == null) || (texture.Texture2D == null)) && (index < geom.Textures.Length)) + //{ + // texture = geom.Textures[index]; + // index++; + //} + } + else if (RenderMode == WorldRenderMode.SingleTexture) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + if (ihash == RenderTextureSampler) + { + texture = itex; + break; + } + + } + } + + } + + + bool usediff = ((texture != null) && (texture.Texture2D != null) && (texture.ShaderResourceView != null)); + + PSGeomVars.Vars.EnableTexture = usediff ? 1u : 0u; + PSGeomVars.Vars.EnableTint = 0u; + PSGeomVars.Update(context); + PSGeomVars.SetPSCBuffer(context, 2); + + VSGeomVars.Vars.EnableTint = 0u; + VSGeomVars.Vars.TintYVal = 0u; + VSGeomVars.Vars.IsDecal = 0u; + VSGeomVars.Update(context); + VSGeomVars.SetVSCBuffer(context, 4); + + + //context.VertexShader.SetSampler(0, texsampler); + context.PixelShader.SetSampler(0, texsampler); + //context.PixelShader.SetSampler(1, texsamplerc); + if (usediff) + { + texture.SetPSResource(context, 0); + //context.PixelShader.SetShaderResource(0, difftex.ShaderResourceView); + } + } + + + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); //shadowmap + context.PixelShader.SetConstantBuffer(1, null); //shadowmap + context.PixelShader.SetShaderResource(1, null);//shadowmap + context.PixelShader.SetSampler(1, null); //shadowmap + context.VertexShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(3, null); + context.PixelShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(4, null); + context.VertexShader.SetSampler(0, null); + context.PixelShader.SetSampler(0, null); + context.PixelShader.SetShaderResource(0, null); + context.VertexShader.SetShaderResource(0, null); + context.VertexShader.SetShaderResource(1, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + public void Dispose() + { + if (disposed) return; + + + if (texsampler != null) + { + texsampler.Dispose(); + texsampler = null; + } + + foreach (InputLayout layout in layouts.Values) + { + layout.Dispose(); + } + layouts.Clear(); + + VSSceneVars.Dispose(); + VSEntityVars.Dispose(); + VSModelVars.Dispose(); + VSGeomVars.Dispose(); + PSSceneVars.Dispose(); + PSGeomVars.Dispose(); + + + ps.Dispose(); + vs.Dispose(); + + disposed = true; + } + } +} diff --git a/Rendering/Shaders/CloudsShader.cs b/Rendering/Shaders/CloudsShader.cs new file mode 100644 index 0000000..6ab0404 --- /dev/null +++ b/Rendering/Shaders/CloudsShader.cs @@ -0,0 +1,356 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CodeWalker.GameFiles; +using CodeWalker.World; +using SharpDX.Direct3D11; +using System.IO; +using SharpDX; + +namespace CodeWalker.Rendering +{ + public struct CloudsShaderVSSceneVars + { + public Matrix ViewProj; + public Matrix ViewInv; + } + public struct CloudsShaderVSEntityVars + { + public Vector4 CamRel; + public Quaternion Orientation; + public Vector4 Scale; + } + public struct CloudsShaderVSModelVars + { + public Matrix Transform; + } + public struct CloudsShaderPSSceneVars + { + public Vector4 LightDirection; + public uint EnableHDR; + public uint Pad0; + public uint Pad1; + public uint Pad2; + } + public struct CloudsShaderCloudsLocals + { + public Vector3 gSkyColor; // Offset: 0 Size: 12 [unused] + public float gPad00; + public Vector3 gEastMinusWestColor; // Offset: 16 Size: 12 [unused] + public float gPad01; + public Vector3 gWestColor; // Offset: 32 Size: 12 [unused] + public float gPad02; + public Vector3 gSunDirection; // Offset: 48 Size: 12 + public float gPad03; + public Vector3 gSunColor; // Offset: 64 Size: 12 + public float gPad04; + public Vector3 gCloudColor; // Offset: 80 Size: 12 [unused] + public float gPad05; + public Vector3 gAmbientColor; // Offset: 96 Size: 12 [unused] + public float gPad06; + public Vector3 gBounceColor; // Offset: 112 Size: 12 [unused] + public float gPad07; + public Vector4 gDensityShiftScale; // Offset: 128 Size: 16 [unused] + public Vector4 gScatterG_GSquared_PhaseMult_Scale;// Offset: 144 Size: 16 + public Vector4 gPiercingLightPower_Strength_NormalStrength_Thickness;// Offset: 160 Size: 16 + public Vector3 gScaleDiffuseFillAmbient; // Offset: 176 Size: 12 [unused] + public float gPad08; + public Vector3 gWrapLighting_MSAARef; // Offset: 192 Size: 12 [unused] + public float gPad09; + public Vector4 gNearFarQMult; // Offset: 208 Size: 16 [unused] + public Vector3 gAnimCombine; // Offset: 224 Size: 12 [unused] + public float gPad10; + public Vector3 gAnimSculpt; // Offset: 240 Size: 12 [unused] + public float gPad11; + public Vector3 gAnimBlendWeights; // Offset: 256 Size: 12 [unused] + public float gPad12; + public Vector4 gUVOffsetArr0; // Offset: 272 Size: 32 + public Vector4 gUVOffsetArr1; // Offset: 272 Size: 32 + public Matrix gCloudViewProj; // Offset: 304 Size: 64 + public Vector4 gCameraPos; // Offset: 368 Size: 16 + public Vector2 gUVOffset1; // Offset: 384 Size: 8 + public Vector2 gUVOffset2; // Offset: 392 Size: 8 + public Vector2 gUVOffset3; // Offset: 400 Size: 8 + public Vector2 gRescaleUV1; // Offset: 408 Size: 8 + public Vector2 gRescaleUV2; // Offset: 416 Size: 8 + public Vector2 gRescaleUV3; // Offset: 424 Size: 8 + public float gSoftParticleRange; // Offset: 432 Size: 4 [unused] + public float gEnvMapAlphaScale; // Offset: 436 Size: 4 [unused] + public Vector2 cloudLayerAnimScale1; // Offset: 440 Size: 8 + public Vector2 cloudLayerAnimScale2; // Offset: 448 Size: 8 + public Vector2 cloudLayerAnimScale3; // Offset: 456 Size: 8 + }; + + + public class CloudsShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader vs; + PixelShader ps; + + GpuVarsBuffer CloudsLocalVars; + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSEntityVars; + GpuVarsBuffer VSModelVars; + GpuVarsBuffer PSSceneVars; + + SamplerState texsampler; + SamplerState texsampleranis; + InputLayout layout; + + public bool EnableHDR { get; set; } + public bool AnisotropicFilter = false; + + public CloudsShader(Device device) + { + byte[] vsbytes = File.ReadAllBytes("Shaders\\CloudsVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\CloudsPS.cso"); + + vs = new VertexShader(device, vsbytes); + ps = new PixelShader(device, psbytes); + + CloudsLocalVars = new GpuVarsBuffer(device); + VSSceneVars = new GpuVarsBuffer(device); + VSEntityVars = new GpuVarsBuffer(device); + VSModelVars = new GpuVarsBuffer(device); + PSSceneVars = new GpuVarsBuffer(device); + + layout = new InputLayout(device, vsbytes, VertexTypeDefaultEx.GetLayout()); + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsampleranis = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.Anisotropic, + MaximumAnisotropy = 8, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + } + + public void UpdateCloudsLocals(Clouds clouds, ShaderGlobalLights lights) + { + + CloudsLocalVars.Vars.gSunDirection = lights.CurrentSunDir; + CloudsLocalVars.Vars.gSunColor = ((Vector4)lights.Params.LightDirColour).XYZ(); + CloudsLocalVars.Vars.gUVOffset1 = clouds.AnimOverrides.UVOffset1; + CloudsLocalVars.Vars.gUVOffset2 = clouds.AnimOverrides.UVOffset2; + CloudsLocalVars.Vars.gUVOffset3 = clouds.AnimOverrides.UVOffset3; + CloudsLocalVars.Vars.gRescaleUV1 = clouds.AnimOverrides.RescaleUV1; + CloudsLocalVars.Vars.gRescaleUV2 = clouds.AnimOverrides.RescaleUV2; + CloudsLocalVars.Vars.gRescaleUV3 = clouds.AnimOverrides.RescaleUV3; + CloudsLocalVars.Vars.cloudLayerAnimScale1 = clouds.AnimOverrides.cloudLayerAnimScale1; + CloudsLocalVars.Vars.cloudLayerAnimScale2 = clouds.AnimOverrides.cloudLayerAnimScale2; + CloudsLocalVars.Vars.cloudLayerAnimScale3 = clouds.AnimOverrides.cloudLayerAnimScale3; + CloudsLocalVars.Vars.gUVOffsetArr0 = Vector4.Zero; + CloudsLocalVars.Vars.gUVOffsetArr1 = Vector4.Zero; + + + } + + public override void SetShader(DeviceContext context) + { + context.VertexShader.Set(vs); + context.PixelShader.Set(ps); + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + CloudsLocalVars.Update(context); + CloudsLocalVars.SetVSCBuffer(context, 0); + CloudsLocalVars.SetPSCBuffer(context, 0); + + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix); + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 1); + + PSSceneVars.Vars.LightDirection = new Vector4(lights.Params.LightDir, 0.0f); + PSSceneVars.Vars.EnableHDR = EnableHDR ? 1u : 0u; + PSSceneVars.Update(context); + PSSceneVars.SetPSCBuffer(context, 1); + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = rend.Orientation; + VSEntityVars.Vars.Scale = new Vector4(rend.Scale, 1.0f); + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + } + + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + //currently not used.. + //if (!model.UseTransform) return; + //VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform); + //VSModelVars.Update(context); + //VSModelVars.SetVSCBuffer(context, 3); + } + + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + + switch (geom.DrawableGeom.Shader.FileName.Hash) + { + case 4103916155://{clouds_animsoft.sps} + case 1097000161://{clouds_altitude.sps} + case 1481470665://{clouds_soft.sps} + case 2184108982://{clouds_fast.sps} + case 4192928948://{clouds_anim.sps} + break; + default: + break; + } + + RenderableTexture DensitySampler = null; + RenderableTexture NormalSampler = null; + RenderableTexture DetailDensitySampler = null; + RenderableTexture DetailNormalSampler = null; + RenderableTexture DetailDensity2Sampler = null; + RenderableTexture DetailNormal2Sampler = null; + RenderableTexture DepthMapTexSampler = null; + + + if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0)) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + switch (ihash) + { + case MetaName.DensitySampler: + DensitySampler = itex; + break; + case MetaName.normalSampler: + NormalSampler = itex; + break; + case MetaName.DetailDensitySampler: + DetailDensitySampler = itex; + break; + case MetaName.DetailNormalSampler: + DetailNormalSampler = itex; + break; + case MetaName.DetailDensity2Sampler: + DetailDensity2Sampler = itex; + break; + case MetaName.DetailNormal2Sampler: + DetailNormal2Sampler = itex; + break; + case MetaName.DepthMapTexSampler: + DepthMapTexSampler = itex; + break; + default: + break; + } + } + } + + bool usedens = ((DensitySampler != null) && (DensitySampler.ShaderResourceView != null)); + bool usenorm = ((NormalSampler != null) && (NormalSampler.ShaderResourceView != null)); + bool usedden = ((DetailDensitySampler != null) && (DetailDensitySampler.ShaderResourceView != null)); + bool usednrm = ((DetailNormalSampler != null) && (DetailNormalSampler.ShaderResourceView != null)); + bool useddn2 = ((DetailDensity2Sampler != null) && (DetailDensity2Sampler.ShaderResourceView != null)); + bool usednm2 = ((DetailNormal2Sampler != null) && (DetailNormal2Sampler.ShaderResourceView != null)); + bool usedept = ((DepthMapTexSampler != null) && (DepthMapTexSampler.ShaderResourceView != null)); + + if (usedens) + { + DensitySampler.SetPSResource(context, 0); + } + if (usenorm) + { + NormalSampler.SetPSResource(context, 1); + } + if (usedden) + { + DetailDensitySampler.SetPSResource(context, 2); + } + if (usednrm) + { + DetailNormalSampler.SetPSResource(context, 3); + } + if (useddn2) + { + DetailDensity2Sampler.SetPSResource(context, 4); + } + if (usednm2) + { + DetailNormal2Sampler.SetPSResource(context, 5); + } + if (usedept) + { + DepthMapTexSampler.SetPSResource(context, 6); + } + + context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler); + + + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + if (type != VertexType.DefaultEx) + { + return false; + } + context.InputAssembler.InputLayout = layout; + return true; + } + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); + context.PixelShader.SetConstantBuffer(1, null); + context.VertexShader.SetConstantBuffer(2, null); + context.PixelShader.SetSampler(0, null); + context.PixelShader.SetShaderResource(0, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + public void Dispose() + { + if (disposed) return; + disposed = true; + + + texsampler.Dispose(); + + layout.Dispose(); + + CloudsLocalVars.Dispose(); + VSSceneVars.Dispose(); + VSEntityVars.Dispose(); + VSModelVars.Dispose(); + PSSceneVars.Dispose(); + + ps.Dispose(); + vs.Dispose(); + } + } +} diff --git a/Rendering/Shaders/DistantLightsShader.cs b/Rendering/Shaders/DistantLightsShader.cs new file mode 100644 index 0000000..ffc66e8 --- /dev/null +++ b/Rendering/Shaders/DistantLightsShader.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CodeWalker.GameFiles; +using SharpDX; +using SharpDX.Direct3D11; +using System.IO; +using SharpDX.DXGI; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + public struct DistantLightsShaderVSSceneVars + { + public Matrix ViewProj; + public Matrix ViewInv; + public Vector3 CamPos; + public float Pad0; + } + + public class DistantLightsShader : Shader + { + bool disposed = false; + + VertexShader lightsvs; + PixelShader lightsps; + + InputLayout layout; + + SamplerState texsampler; + + UnitQuad quad; + + GpuVarsBuffer VSSceneVars; + + + public DistantLightsShader(Device device) + { + byte[] vsbytes = File.ReadAllBytes("Shaders\\DistantLightsVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\DistantLightsPS.cso"); + + lightsvs = new VertexShader(device, vsbytes); + lightsps = new PixelShader(device, psbytes); + + layout = new InputLayout(device, vsbytes, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0), + }); + + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Clamp, + AddressV = TextureAddressMode.Clamp, + AddressW = TextureAddressMode.Clamp, + BorderColor = Color.Transparent, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + + + quad = new UnitQuad(device); + + VSSceneVars = new GpuVarsBuffer(device); + + } + + public override void SetShader(DeviceContext context) + { + context.VertexShader.Set(lightsvs); + context.PixelShader.Set(lightsps); + SetInputLayout(context, VertexType.PT); + } + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + context.InputAssembler.InputLayout = layout; + return true; + } + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix); + VSSceneVars.Vars.CamPos = camera.Position; + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + } + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + } + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + } + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + } + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.VertexShader.SetShaderResource(0, null); + context.PixelShader.SetShaderResource(0, null); + context.PixelShader.SetSampler(0, null); + } + + + public void RenderBatch(DeviceContext context, RenderableDistantLODLights lights) + { + context.VertexShader.SetShaderResource(0, lights.InstanceBuffer.SRV); + context.PixelShader.SetShaderResource(0, lights.Texture.ShaderResourceView); + context.PixelShader.SetSampler(0, texsampler); + + quad.DrawInstanced(context, lights.InstanceCount); + } + + + public void Dispose() + { + if (disposed) return; + + VSSceneVars.Dispose(); + + quad.Dispose(); + + texsampler.Dispose(); + + layout.Dispose(); + + //VSSceneVars.Dispose(); + + lightsps.Dispose(); + lightsvs.Dispose(); + + disposed = true; + } + + } +} diff --git a/Rendering/Shaders/MarkerShader.cs b/Rendering/Shaders/MarkerShader.cs new file mode 100644 index 0000000..6f3df64 --- /dev/null +++ b/Rendering/Shaders/MarkerShader.cs @@ -0,0 +1,166 @@ +using SharpDX; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using CodeWalker.GameFiles; +using System.IO; +using SharpDX.DXGI; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct MarkerShaderVSSceneVars + { + public Matrix ViewProj; + public Matrix ViewInv; + public Vector4 ScreenScale; //xy = 1/wh + } + public struct MarkerShaderVSMarkerVars + { + public Vector4 CamRel; + public Vector2 Size; + public Vector2 Offset; + } + + public class MarkerShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader markervs; + PixelShader markerps; + + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSMarkerVars; + + SamplerState texsampler; + + InputLayout layout; + + + public MarkerShader(Device device) + { + byte[] vsbytes = File.ReadAllBytes("Shaders\\MarkerVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\MarkerPS.cso"); + + markervs = new VertexShader(device, vsbytes); + markerps = new PixelShader(device, psbytes); + + VSSceneVars = new GpuVarsBuffer(device); + VSMarkerVars = new GpuVarsBuffer(device); + + layout = new InputLayout(device, vsbytes, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0), + }); + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Clamp, + AddressV = TextureAddressMode.Clamp, + AddressW = TextureAddressMode.Clamp, + BorderColor = Color.Transparent, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + + } + + + + + public override void SetShader(DeviceContext context) + { + context.VertexShader.Set(markervs); + context.PixelShader.Set(markerps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + context.InputAssembler.InputLayout = layout; + return true; + } + + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix); + VSSceneVars.Vars.ScreenScale = new Vector4(0.5f / camera.Width, 0.5f / camera.Height, camera.Width, camera.Height); + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + } + + public void SetMarkerVars(DeviceContext context, Vector3 camrel, Vector2 size, Vector2 offset) + { + VSMarkerVars.Vars.CamRel = new Vector4(camrel, 0.0f); + VSMarkerVars.Vars.Size = size; + VSMarkerVars.Vars.Offset = offset; + VSMarkerVars.Update(context); + VSMarkerVars.SetVSCBuffer(context, 1); + } + + public void SetTexture(DeviceContext context, ShaderResourceView srv) + { + context.PixelShader.SetSampler(0, texsampler); + context.PixelShader.SetShaderResource(0, srv); + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + //don't use this one + } + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + //don't use this + } + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + //don't use this + } + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); + context.PixelShader.SetSampler(0, null); + context.PixelShader.SetShaderResource(0, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + public void Dispose() + { + if (disposed) return; + + if (texsampler != null) + { + texsampler.Dispose(); + texsampler = null; + } + + layout.Dispose(); + + VSSceneVars.Dispose(); + VSMarkerVars.Dispose(); + + markerps.Dispose(); + markervs.Dispose(); + + disposed = true; + } + + } +} diff --git a/Rendering/Shaders/PathShader.cs b/Rendering/Shaders/PathShader.cs new file mode 100644 index 0000000..72d1e65 --- /dev/null +++ b/Rendering/Shaders/PathShader.cs @@ -0,0 +1,246 @@ +using SharpDX; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using CodeWalker.GameFiles; +using System.IO; +using SharpDX.DXGI; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct PathShaderVSSceneVars + { + public Matrix ViewProj; + public Vector4 CameraPos; + public Vector4 LightColour; + } + + + public class PathShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader boxvs; + PixelShader boxps; + VertexShader dynvs; + VertexShader vs; + PixelShader ps; + + GpuVarsBuffer VSSceneVars; + + InputLayout layout; + + UnitCube cube; + + bool UseDynamicVerts = false; + GpuCBuffer vertices; //for selection polys/lines use + + + public PathShader(Device device) + { + byte[] boxvsbytes = File.ReadAllBytes("Shaders\\PathBoxVS.cso"); + byte[] boxpsbytes = File.ReadAllBytes("Shaders\\PathBoxPS.cso"); + byte[] dynvsbytes = File.ReadAllBytes("Shaders\\PathDynVS.cso"); + byte[] vsbytes = File.ReadAllBytes("Shaders\\PathVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\PathPS.cso"); + + + boxvs = new VertexShader(device, boxvsbytes); + boxps = new PixelShader(device, boxpsbytes); + dynvs = new VertexShader(device, dynvsbytes); + vs = new VertexShader(device, vsbytes); + ps = new PixelShader(device, psbytes); + + VSSceneVars = new GpuVarsBuffer(device); + + layout = new InputLayout(device, vsbytes, VertexTypePC.GetLayout()); + + cube = new UnitCube(device, boxvsbytes, true, false, true); + + vertices = new GpuCBuffer(device, 1000); //should be more than needed.... + } + + + public override void SetShader(DeviceContext context) + { + if (UseDynamicVerts) + { + context.VertexShader.Set(dynvs); + //context.InputAssembler.SetVertexBuffers(0, null); + context.InputAssembler.SetIndexBuffer(null, Format.Unknown, 0); + } + else + { + context.VertexShader.Set(vs); + } + context.PixelShader.Set(ps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + if (UseDynamicVerts) + { + context.InputAssembler.InputLayout = null; + } + else + { + context.InputAssembler.InputLayout = layout; + } + return true; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f); + VSSceneVars.Vars.LightColour = new Vector4(1.0f, 1.0f, 1.0f, lights.HdrIntensity * 2.0f); + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + //don't use this one + } + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + //don't use this + } + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + //don't use this + } + + + public void RenderBatches(DeviceContext context, List batches, Camera camera, ShaderGlobalLights lights) + { + UseDynamicVerts = false; + SetShader(context); + SetInputLayout(context, VertexType.PC); + SetSceneVars(context, camera, null, lights); + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList; + context.InputAssembler.SetIndexBuffer(null, Format.R16_UInt, 0); + for (int i = 0; i < batches.Count; i++) + { + var pbatch = batches[i]; + + if (pbatch.TriangleVertexBuffer == null) continue; + if (pbatch.TriangleVertexCount == 0) continue; + + context.InputAssembler.SetVertexBuffers(0, pbatch.TriangleVBBinding); + context.Draw(pbatch.TriangleVertexCount, 0); + } + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList; + context.InputAssembler.SetIndexBuffer(null, Format.R16_UInt, 0); + for (int i = 0; i < batches.Count; i++) + { + var pbatch = batches[i]; + + if (pbatch.PathVertexBuffer == null) continue; + if (pbatch.PathVertexCount == 0) continue; + + context.InputAssembler.SetVertexBuffers(0, pbatch.PathVBBinding); + context.Draw(pbatch.PathVertexCount, 0); + } + + + context.VertexShader.Set(boxvs); + context.PixelShader.Set(boxps); + + VSSceneVars.SetVSCBuffer(context, 0); + + foreach (var batch in batches) + { + if (batch.NodeBuffer == null) continue; + + context.VertexShader.SetShaderResource(0, batch.NodeBuffer.SRV); + + cube.DrawInstanced(context, batch.Nodes.Length); + } + + UnbindResources(context); + } + + public void RenderTriangles(DeviceContext context, List verts, Camera camera, ShaderGlobalLights lights) + { + UseDynamicVerts = true; + SetShader(context); + SetInputLayout(context, VertexType.PC); + SetSceneVars(context, camera, null, lights); + + vertices.Clear(); + foreach (var vert in verts) + { + vertices.Add(vert); + } + vertices.Update(context); + vertices.SetVSResource(context, 0); + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList; + context.Draw(vertices.CurrentCount, 0); + } + + public void RenderLines(DeviceContext context, List verts, Camera camera, ShaderGlobalLights lights) + { + UseDynamicVerts = true; + SetShader(context); + SetInputLayout(context, VertexType.PC); + SetSceneVars(context, camera, null, lights); + + vertices.Clear(); + foreach (var vert in verts) + { + vertices.Add(vert); + } + vertices.Update(context); + vertices.SetVSResource(context, 0); + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList; + context.Draw(vertices.CurrentCount, 0); + } + + + + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.VertexShader.SetShaderResource(0, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + + public void Dispose() + { + if (disposed) return; + disposed = true; + + VSSceneVars.Dispose(); + + vertices.Dispose(); + + layout.Dispose(); + cube.Dispose(); + + ps.Dispose(); + vs.Dispose(); + dynvs.Dispose(); + boxvs.Dispose(); + boxps.Dispose(); + } + + } + +} diff --git a/Rendering/Shaders/PostProcessor.cs b/Rendering/Shaders/PostProcessor.cs new file mode 100644 index 0000000..7e0f439 --- /dev/null +++ b/Rendering/Shaders/PostProcessor.cs @@ -0,0 +1,688 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX.Direct3D11; +using System.IO; +using CodeWalker.GameFiles; +using CodeWalker.World; +using SharpDX; +using SharpDX.DXGI; +using SharpDX.Mathematics.Interop; + +namespace CodeWalker.Rendering +{ + + public struct PostProcessorReduceCSVars + { + public uint dimx; + public uint dimy; + public uint Width; + public uint Height; + } + public struct PostProcessorLumBlendCSVars + { + public Vector4 blend; + } + public struct PostProcessorFilterSampleWeights + { + public Vector4 avSampleWeights00; //[15]; + public Vector4 avSampleWeights01; + public Vector4 avSampleWeights02; + public Vector4 avSampleWeights03; + public Vector4 avSampleWeights04; + public Vector4 avSampleWeights05; + public Vector4 avSampleWeights06; + public Vector4 avSampleWeights07; + public Vector4 avSampleWeights08; + public Vector4 avSampleWeights09; + public Vector4 avSampleWeights10; + public Vector4 avSampleWeights11; + public Vector4 avSampleWeights12; + public Vector4 avSampleWeights13; + public Vector4 avSampleWeights14; + + public Vector4 Get(int i) + { + switch (i) + { + default: + case 0: return avSampleWeights00; + case 1: return avSampleWeights01; + case 2: return avSampleWeights02; + case 3: return avSampleWeights03; + case 4: return avSampleWeights04; + case 5: return avSampleWeights05; + case 6: return avSampleWeights06; + case 7: return avSampleWeights07; + case 8: return avSampleWeights08; + case 9: return avSampleWeights09; + case 10: return avSampleWeights10; + case 11: return avSampleWeights11; + case 12: return avSampleWeights12; + case 13: return avSampleWeights13; + case 14: return avSampleWeights14; + } + } + public void Set(int i, Vector4 v) + { + switch (i) + { + case 0: avSampleWeights00 = v; break; + case 1: avSampleWeights01 = v; break; + case 2: avSampleWeights02 = v; break; + case 3: avSampleWeights03 = v; break; + case 4: avSampleWeights04 = v; break; + case 5: avSampleWeights05 = v; break; + case 6: avSampleWeights06 = v; break; + case 7: avSampleWeights07 = v; break; + case 8: avSampleWeights08 = v; break; + case 9: avSampleWeights09 = v; break; + case 10: avSampleWeights10 = v; break; + case 11: avSampleWeights11 = v; break; + case 12: avSampleWeights12 = v; break; + case 13: avSampleWeights13 = v; break; + case 14: avSampleWeights14 = v; break; + } + } + } + public struct PostProcessorFilterBPHCSVars + { + public PostProcessorFilterSampleWeights avSampleWeights; + public uint outputwidth; + public float finverse; + public int inputsize0; + public int inputsize1; + } + public struct PostProcessorFilterVCSVars + { + public PostProcessorFilterSampleWeights avSampleWeights; + public int outputsize0; + public int outputsize1; + public int inputsize0; + public int inputsize1; + } + public struct PostProcessorFinalPSVars + { + public Vector4 invPixelCount; + } + + + public class PostProcessor + { + ComputeShader ReduceTo1DCS; + ComputeShader ReduceTo0DCS; + ComputeShader LumBlendCS; + ComputeShader BloomFilterBPHCS; + ComputeShader BloomFilterVCS; + PixelShader CopyPixelsPS; + VertexShader FinalPassVS; + PixelShader FinalPassPS; + UnitQuad FinalPassQuad; + InputLayout FinalPassLayout; + GpuVarsBuffer ReduceCSVars; + GpuVarsBuffer LumBlendCSVars; + GpuVarsBuffer FilterBPHCSVars; + GpuVarsBuffer FilterVCSVars; + GpuVarsBuffer FinalPSVars; + + GpuTexture Primary; + + GpuBuffer Reduction0; + GpuBuffer Reduction1; + + GpuBuffer LumBlendResult; + + GpuBuffer Bloom0; + GpuBuffer Bloom1; + GpuTexture Bloom; + + SamplerState SampleStatePoint; + SamplerState SampleStateLinear; + BlendState BlendState; + long WindowSizeVramUsage = 0; + int Width = 0; + int Height = 0; + ViewportF Viewport; + bool Multisampled = false; + bool EnableBloom = true; + float ElapsedTime = 0.0f; + public float LumBlendSpeed = 1.0f; + + bool CS_FULL_PIXEL_REDUCTION = false; + + public long VramUsage + { + get + { + return WindowSizeVramUsage; + } + } + + RawViewportF[] vpOld = new RawViewportF[15]; + + public PostProcessor(DXManager dxman) + { + var device = dxman.device; + + byte[] bReduceTo1DCS = File.ReadAllBytes("Shaders\\PPReduceTo1DCS.cso"); + byte[] bReduceTo0DCS = File.ReadAllBytes("Shaders\\PPReduceTo0DCS.cso"); + byte[] bLumBlendCS = File.ReadAllBytes("Shaders\\PPLumBlendCS.cso"); + byte[] bBloomFilterBPHCS = File.ReadAllBytes("Shaders\\PPBloomFilterBPHCS.cso"); + byte[] bBloomFilterVCS = File.ReadAllBytes("Shaders\\PPBloomFilterVCS.cso"); + byte[] bCopyPixelsPS = File.ReadAllBytes("Shaders\\PPCopyPixelsPS.cso"); + byte[] bFinalPassVS = File.ReadAllBytes("Shaders\\PPFinalPassVS.cso"); + byte[] bFinalPassPS = File.ReadAllBytes("Shaders\\PPFinalPassPS.cso"); + + ReduceTo1DCS = new ComputeShader(device, bReduceTo1DCS); + ReduceTo0DCS = new ComputeShader(device, bReduceTo0DCS); + LumBlendCS = new ComputeShader(device, bLumBlendCS); + BloomFilterBPHCS = new ComputeShader(device, bBloomFilterBPHCS); + BloomFilterVCS = new ComputeShader(device, bBloomFilterVCS); + CopyPixelsPS = new PixelShader(device, bCopyPixelsPS); + FinalPassVS = new VertexShader(device, bFinalPassVS); + FinalPassPS = new PixelShader(device, bFinalPassPS); + FinalPassQuad = new UnitQuad(device, true); + FinalPassLayout = new InputLayout(device, bFinalPassVS, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0), + }); + + + ReduceCSVars = new GpuVarsBuffer(device); + LumBlendCSVars = new GpuVarsBuffer(device); + FilterBPHCSVars = new GpuVarsBuffer(device); + FilterVCSVars = new GpuVarsBuffer(device); + FinalPSVars = new GpuVarsBuffer(device); + + TextureAddressMode a = TextureAddressMode.Clamp; + Color4 b = new Color4(0.0f, 0.0f, 0.0f, 0.0f); + Comparison c = Comparison.Always; + SampleStatePoint = DXUtility.CreateSamplerState(device, a, b, c, Filter.MinMagMipPoint, 0, 1.0f, 1.0f, 0.0f); + SampleStateLinear = DXUtility.CreateSamplerState(device, a, b, c, Filter.MinMagMipLinear, 0, 1.0f, 1.0f, 0.0f); + + BlendState = DXUtility.CreateBlendState(device, false, BlendOperation.Add, BlendOption.One, BlendOption.Zero, BlendOperation.Add, BlendOption.One, BlendOption.Zero, ColorWriteMaskFlags.All); + + GetSampleWeights(ref FilterVCSVars.Vars.avSampleWeights, 3.0f, 1.25f); //init sample weights + FilterBPHCSVars.Vars.avSampleWeights = FilterVCSVars.Vars.avSampleWeights; + } + public void Dispose() + { + DisposeBuffers(); + + if (BlendState != null) + { + BlendState.Dispose(); + BlendState = null; + } + if (SampleStateLinear != null) + { + SampleStateLinear.Dispose(); + SampleStateLinear = null; + } + if (SampleStatePoint != null) + { + SampleStatePoint.Dispose(); + SampleStatePoint = null; + } + if (FinalPSVars != null) + { + FinalPSVars.Dispose(); + FinalPSVars = null; + } + if (FilterVCSVars != null) + { + FilterVCSVars.Dispose(); + FilterVCSVars = null; + } + if (FilterBPHCSVars != null) + { + FilterBPHCSVars.Dispose(); + FilterBPHCSVars = null; + } + if (LumBlendCSVars != null) + { + LumBlendCSVars.Dispose(); + LumBlendCSVars = null; + } + if (ReduceCSVars != null) + { + ReduceCSVars.Dispose(); + ReduceCSVars = null; + } + if (FinalPassLayout != null) + { + FinalPassLayout.Dispose(); + FinalPassLayout = null; + } + if (FinalPassQuad != null) + { + FinalPassQuad.Dispose(); + FinalPassQuad = null; + } + if (FinalPassPS != null) + { + FinalPassPS.Dispose(); + FinalPassPS = null; + } + if (FinalPassVS != null) + { + FinalPassVS.Dispose(); + FinalPassVS = null; + } + if (CopyPixelsPS != null) + { + CopyPixelsPS.Dispose(); + CopyPixelsPS = null; + } + if (BloomFilterVCS != null) + { + BloomFilterVCS.Dispose(); + BloomFilterVCS = null; + } + if (BloomFilterBPHCS != null) + { + BloomFilterBPHCS.Dispose(); + BloomFilterBPHCS = null; + } + if (LumBlendCS != null) + { + LumBlendCS.Dispose(); + LumBlendCS = null; + } + if (ReduceTo0DCS != null) + { + ReduceTo0DCS.Dispose(); + ReduceTo0DCS = null; + } + if (ReduceTo1DCS != null) + { + ReduceTo1DCS.Dispose(); + ReduceTo1DCS = null; + } + } + + public void OnWindowResize(DXManager dxman) + { + DisposeBuffers(); + + var device = dxman.device; + + + int sc = dxman.multisamplecount; + int sq = dxman.multisamplequality; + Multisampled = (sc > 1); + + int uw = Width = dxman.backbuffer.Description.Width; + int uh = Height = dxman.backbuffer.Description.Height; + Viewport = new ViewportF(); + Viewport.Width = (float)uw; + Viewport.Height = (float)uh; + Viewport.MinDepth = 0.0f; + Viewport.MaxDepth = 1.0f; + Viewport.X = 0.0f; + Viewport.Y = 0.0f; + + + Format f = Format.R32G32B32A32_Float; + Format df = Format.D32_Float; + + + Primary = new GpuTexture(device, uw, uh, f, sc, sq, true, df); + WindowSizeVramUsage += Primary.VramUsage; + + + int rc = (int)(Math.Ceiling(uw / 8.0f) * Math.Ceiling(uh / 8.0f)); + + Reduction0 = new GpuBuffer(device, 1, rc); + Reduction1 = new GpuBuffer(device, 1, rc); + WindowSizeVramUsage += sizeof(float) * rc * 2; + + LumBlendResult = new GpuBuffer(device, 1, 1); + WindowSizeVramUsage += sizeof(float); //because 4 bytes matter + + int tw = uw / 8; + int th = uh / 8; + rc = tw * th; + f = Format.R8G8B8A8_UNorm; + + Bloom0 = new GpuBuffer(device, 1, rc); + Bloom1 = new GpuBuffer(device, 1, rc); + WindowSizeVramUsage += /*sizeof(V4F)*/ 16 * rc * 2; + + Bloom = new GpuTexture(device, tw, th, f, 1, 0, false, df); + WindowSizeVramUsage += Bloom.VramUsage; + + + } + public void DisposeBuffers() + { + if (Bloom != null) + { + Bloom.Dispose(); + Bloom = null; + } + if (Bloom0 != null) + { + Bloom0.Dispose(); + Bloom0 = null; + } + if (Bloom1 != null) + { + Bloom1.Dispose(); + Bloom1 = null; + } + if (LumBlendResult != null) + { + LumBlendResult.Dispose(); + LumBlendResult = null; + } + if (Reduction0 != null) + { + Reduction0.Dispose(); + Reduction0 = null; + } + if (Reduction1 != null) + { + Reduction1.Dispose(); + Reduction1 = null; + } + if (Primary != null) + { + Primary.Dispose(); + Primary = null; + } + WindowSizeVramUsage = 0; + } + + public void Clear(DeviceContext context) + { + Color4 clearColour = new Color4(0.2f, 0.4f, 0.6f, 0.0f); + //Color4 clearColour = new Color4(0.0f, 0.0f, 0.0f, 0.0f); + + Primary.Clear(context, clearColour); + } + public void ClearDepth(DeviceContext context) + { + Primary.ClearDepth(context); + } + public void SetPrimary(DeviceContext context) + { + Primary.SetRenderTarget(context); + context.Rasterizer.SetViewport(Viewport); + } + + public void Render(DXManager dxman, float elapsed) + { + ElapsedTime = elapsed; + + var context = dxman.context; + + if (Multisampled) + { + int sr = 0;// D3D11CalcSubresource(0, 0, 1); + context.ResolveSubresource(Primary.TextureMS, sr, Primary.Texture, sr, Format.R32G32B32A32_Float); + } + + context.OutputMerger.SetRenderTargets((RenderTargetView)null); + + ProcessLuminance(context); + ProcessBloom(context); + + dxman.SetDefaultRenderTarget(context); + context.OutputMerger.SetBlendState(BlendState, null, 0xFFFFFFFF); + FinalPass(context); + } + + + private void ProcessLuminance(DeviceContext context) + { + uint dimx, dimy; + if (CS_FULL_PIXEL_REDUCTION) + { + dimx = (uint)(Math.Ceiling(Width / 8.0f)); + dimx = (uint)(Math.Ceiling(dimx / 2.0f)); + dimy = (uint)(Math.Ceiling(Height / 8.0f)); + dimy = (uint)(Math.Ceiling(dimy / 2.0f)); + } + else + { + dimx = (uint)(Math.Ceiling(81.0f / 8.0f)); //ToneMappingTexSize = (int)pow(3.0f, NUM_TONEMAP_TEXTURES-1); + dimy = dimx; + } + + ReduceCSVars.Vars.dimx = dimx; + ReduceCSVars.Vars.dimy = dimy; + ReduceCSVars.Vars.Width = (uint)Width; + ReduceCSVars.Vars.Height = (uint)Height; + ReduceCSVars.Update(context); + + Compute(context, ReduceTo1DCS, ReduceCSVars.Buffer, Reduction0.UAV, (int)dimx, (int)dimy, 1, Primary.SRV); + + uint dim = dimx * dimy; + uint nNumToReduce = dim; + dim = (uint)(Math.Ceiling(dim / 128.0f)); + if (nNumToReduce > 1) + { + for (;;) + { + ReduceCSVars.Vars.dimx = nNumToReduce; + ReduceCSVars.Vars.dimy = dim; + ReduceCSVars.Vars.Width = 0; + ReduceCSVars.Vars.Height = 0; + ReduceCSVars.Update(context); + + Compute(context, ReduceTo0DCS, ReduceCSVars.Buffer, Reduction1.UAV, (int)dim, 1, 1, Reduction0.SRV); + + nNumToReduce = dim; + dim = (uint)(Math.Ceiling(dim / 128.0f)); + + if (nNumToReduce == 1) break; + + var r0 = Reduction0; + Reduction0 = Reduction1; + Reduction1 = r0; + } + } + else + { + var r0 = Reduction0; + Reduction0 = Reduction1; + Reduction1 = r0; + } + + LumBlendCSVars.Vars.blend = new Vector4(Math.Min(ElapsedTime * LumBlendSpeed, 1.0f)); + LumBlendCSVars.Update(context); + + Compute(context, LumBlendCS, LumBlendCSVars.Buffer, LumBlendResult.UAV, 1, 1, 1, Reduction1.SRV); + + } + private void ProcessBloom(DeviceContext context) + { + if (EnableBloom) + { + + // Bright pass and horizontal blur + + ShaderResourceView view = Primary.SRV; + + ShaderResourceView[] aRViews = { view, LumBlendResult.SRV }; + //BloomFilterShaderVars cbFilter; + //GetSampleWeights(cbFilter.avSampleWeights, 3.0f, 1.25f); + FilterBPHCSVars.Vars.outputwidth = (uint)(Width / 8); + if (CS_FULL_PIXEL_REDUCTION) + { + FilterBPHCSVars.Vars.finverse = 1.0f / (Width * Height); + } + else + { + FilterBPHCSVars.Vars.finverse = 1.0f / (81 * 81); //(ToneMappingTexSize*ToneMappingTexSize); + } + FilterBPHCSVars.Vars.inputsize0 = (int)Width; + FilterBPHCSVars.Vars.inputsize1 = (int)Height; + FilterBPHCSVars.Update(context); + + int x = (int)(Math.Ceiling((float)FilterBPHCSVars.Vars.outputwidth / (128 - 7 * 2))); + int y = (Height / 8); + Compute(context, BloomFilterBPHCS, FilterBPHCSVars.Buffer, Bloom1.UAV, x, y, 1, view, LumBlendResult.SRV); + + // Vertical blur + FilterVCSVars.Vars.outputsize0 = (int)(Width / 8); + FilterVCSVars.Vars.outputsize1 = (int)(Height / 8); + FilterVCSVars.Vars.inputsize0 = (int)(Width / 8); + FilterVCSVars.Vars.inputsize1 = (int)(Height / 8); + FilterVCSVars.Update(context); + x = Width / 8; + y = (int)(Math.Ceiling((float)FilterVCSVars.Vars.outputsize1 / (128 - 7 * 2))); + + Compute(context, BloomFilterVCS, FilterVCSVars.Buffer, Bloom0.UAV, x, y, 1, Bloom1.SRV, LumBlendResult.SRV); + } + + CopyPixels(context, Width / 8, Height / 8, Bloom0.SRV, Bloom.RTV); + + } + private void FinalPass(DeviceContext context) + { + context.Rasterizer.SetViewport(Viewport); + context.VertexShader.Set(FinalPassVS); + context.PixelShader.Set(FinalPassPS); + + context.PixelShader.SetShaderResources(0, Primary.SRV, LumBlendResult.SRV, EnableBloom ? Bloom.SRV : null); + + if (CS_FULL_PIXEL_REDUCTION) + { + //pcbCS[0] = 1.0f / (Width * Height); + FinalPSVars.Vars.invPixelCount = new Vector4(1.0f / (Width * Height)); + } + else + { + //pcbCS[0] = 1.0f / (81 * 81); //ToneMappingTexSize*ToneMappingTexSize + FinalPSVars.Vars.invPixelCount = new Vector4(1.0f / (81 * 81)); + } + FinalPSVars.Update(context); + FinalPSVars.SetPSCBuffer(context, 0); + + context.PixelShader.SetSamplers(0, SampleStatePoint, SampleStateLinear); + + context.InputAssembler.InputLayout = FinalPassLayout; + FinalPassQuad.Draw(context); + + context.VertexShader.Set(null); + context.PixelShader.Set(null); + context.PixelShader.SetShaderResources(0, null, null, null); + context.PixelShader.SetSamplers(0, null, null); + } + + + + + private float GaussianDistribution(float x, float y, float rho) + { + float g = 1.0f / (float)Math.Sqrt(2.0f * 3.14159265f * rho * rho); + g *= (float)Math.Exp(-(x * x + y * y) / (2 * rho * rho)); + return g; + } + private void GetSampleWeights(ref PostProcessorFilterSampleWeights w, float fDeviation, float fMultiplier) + { + // Fill the center texel + float weight = 1.0f * GaussianDistribution(0, 0, fDeviation); + w.Set(7, new Vector4(weight, weight, weight, 1.0f)); + + // Fill the right side + for (int i = 1; i < 8; i++) + { + weight = fMultiplier * GaussianDistribution((float)i, 0, fDeviation); + w.Set(7 - i, new Vector4(weight, weight, weight, 1.0f)); + } + + // Copy to the left side + for (int i = 8; i < 15; i++) + { + w.Set(i, w.Get(14 - i)); + } + + // Debug convolution kernel which doesn't transform input data + /*ZeroMemory( avColorWeight, sizeof(D3DXVECTOR4)*15 ); + w.Set(7, new Vector4( 1, 1, 1, 1 ));*/ + } + + + private void Compute(DeviceContext context, ComputeShader cs, Buffer constantBuffer, UnorderedAccessView unorderedAccessView, int X, int Y, int Z, params ShaderResourceView[] resourceViews) + { + context.ComputeShader.Set(cs); + context.ComputeShader.SetShaderResources(0, resourceViews); + context.ComputeShader.SetUnorderedAccessView(0, unorderedAccessView); + + if (constantBuffer != null) + { + //make sure buffer is updated first... + //D3D11_MAPPED_SUBRESOURCE mappedResource; + //dc->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + //memcpy(mappedResource.pData, constantData, constantDataSize); + //dc->Unmap(constantBuffer, 0); + context.ComputeShader.SetConstantBuffer(0, constantBuffer); //dc->CSSetConstantBuffers(0, 1, &constantBuffer); + } + + context.Dispatch(X, Y, Z); + + ShaderResourceView[] ppSRVNULL = { null, null, null }; + context.ComputeShader.SetUnorderedAccessView(0, null); + context.ComputeShader.SetShaderResources(0, 3, ppSRVNULL); + context.ComputeShader.SetConstantBuffer(0, null); + } + + private void CopyPixels(DeviceContext context, int w, int h, ShaderResourceView fromSRV, RenderTargetView toRTV) + { + context.VertexShader.Set(FinalPassVS); + context.PixelShader.Set(CopyPixelsPS); + + ShaderResourceView[] aRViews = { fromSRV }; + context.PixelShader.SetShaderResource(0, fromSRV); + + RenderTargetView[] aRTViews = { toRTV }; + context.OutputMerger.SetRenderTargets(toRTV); + + //D3D11_MAPPED_SUBRESOURCE mappedResource; + //dc->Map(ReduceCSVars.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + //UINT* p = (UINT*)mappedResource.pData; + //p[0] = w; + //p[1] = h; + //dc->Unmap(ReduceCSVars.Get(), 0); + //ID3D11Buffer* ppCB[1] = { ReduceCSVars.Get() }; + //dc->PSSetConstantBuffers(0, 1, ppCB); + ReduceCSVars.Vars.dimx = (uint)w; + ReduceCSVars.Vars.dimy = (uint)h; + ReduceCSVars.Update(context); + ReduceCSVars.SetPSCBuffer(context, 0); + + //DrawFullScreenQuad11( pd3dImmediateContext, g_pDumpBufferPS, dwWidth, dwHeight ); + //ViewportF[] vpOld = new ViewportF[15];// [D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX]; + //UINT nViewPorts = 1; + //dc->RSGetViewports(&nViewPorts, vpOld); + context.Rasterizer.GetViewports(vpOld); + + // Setup the viewport to match the backbuffer + ViewportF vp; + vp.Width = (float)Width; + vp.Height = (float)Height; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.X = 0; + vp.Y = 0; + context.Rasterizer.SetViewport(vp); + + context.InputAssembler.InputLayout = FinalPassLayout; + FinalPassQuad.Draw(context); + + + context.Rasterizer.SetViewports(vpOld); //reverting viewports maybe not necessary... + } + + + } +} diff --git a/Rendering/Shaders/Shader.cs b/Rendering/Shaders/Shader.cs new file mode 100644 index 0000000..b5a9a60 --- /dev/null +++ b/Rendering/Shaders/Shader.cs @@ -0,0 +1,30 @@ +using CodeWalker.GameFiles; +using SharpDX; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + public abstract class Shader + { + + public abstract void SetShader(DeviceContext context); + public abstract bool SetInputLayout(DeviceContext context, VertexType type); + public abstract void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights); + public abstract void SetEntityVars(DeviceContext context, ref RenderableInst rend); + public abstract void SetModelVars(DeviceContext context, RenderableModel model); + public abstract void SetGeomVars(DeviceContext context, RenderableGeometry geom); + public abstract void UnbindResources(DeviceContext context); + + //public abstract void Dispose(); + + } +} diff --git a/Rendering/Shaders/ShadowShader.cs b/Rendering/Shaders/ShadowShader.cs new file mode 100644 index 0000000..17aa68b --- /dev/null +++ b/Rendering/Shaders/ShadowShader.cs @@ -0,0 +1,351 @@ +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX; +using CodeWalker.GameFiles; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct ShadowShaderVSSceneVars + { + public Matrix ViewProj; + public Vector4 WindVector; + } + public struct ShadowShaderVSEntityVars + { + public Vector4 CamRel; + public Quaternion Orientation; + public uint HasSkeleton; + public uint HasTransforms; + public uint TintPaletteIndex; + public uint Pad1; + public Vector3 Scale; + public uint Pad2; + } + public struct ShadowShaderVSModelVars + { + public Matrix Transform; + } + //public struct ShadowShaderVSGeomVars + //{ + // public uint EnableTint; + // public float TintYVal; + // public uint IsDecal; + // public uint Pad5; + //} + public struct ShadowShaderGeomVars + { + public uint EnableTexture; + public uint EnableTint; + public uint IsDecal; + public uint EnableWind; + public Vector4 WindOverrideParams; + } + + public class ShadowShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader shadowvs; + PixelShader shadowps; + + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSEntityVars; + GpuVarsBuffer VSModelVars; + GpuVarsBuffer GeomVars; + + SamplerState texsampler; + SamplerState texsamplerc; + //public bool DecalMode = false; + + public Vector4 WindVector { get; set; } + + + private Dictionary layouts = new Dictionary(); + + public ShadowShader(Device device) + { + byte[] vsbytes = File.ReadAllBytes("Shaders\\ShadowVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\ShadowPS.cso"); + + shadowvs = new VertexShader(device, vsbytes); + shadowps = new PixelShader(device, psbytes); + + + VSSceneVars = new GpuVarsBuffer(device); + VSEntityVars = new GpuVarsBuffer(device); + VSModelVars = new GpuVarsBuffer(device); + GeomVars = new GpuVarsBuffer(device); + + + //supported layouts - requires Position, Normal, Colour, Texcoord + layouts.Add(VertexType.Default, new InputLayout(device, vsbytes, VertexTypeDefault.GetLayout())); + layouts.Add(VertexType.DefaultEx, new InputLayout(device, vsbytes, VertexTypeDefaultEx.GetLayout())); + layouts.Add(VertexType.PNCCT, new InputLayout(device, vsbytes, VertexTypePNCCT.GetLayout())); + layouts.Add(VertexType.PNCCTTTT, new InputLayout(device, vsbytes, VertexTypePNCCTTTT.GetLayout())); + layouts.Add(VertexType.PCCNCCTTX, new InputLayout(device, vsbytes, VertexTypePCCNCCTTX.GetLayout())); + layouts.Add(VertexType.PCCNCCT, new InputLayout(device, vsbytes, VertexTypePCCNCCT.GetLayout())); + layouts.Add(VertexType.PNCTTTX, new InputLayout(device, vsbytes, VertexTypePNCTTTX.GetLayout())); + layouts.Add(VertexType.PNCTTTX_2, new InputLayout(device, vsbytes, VertexTypePNCTTTX_2.GetLayout())); + layouts.Add(VertexType.PNCTTTX_3, new InputLayout(device, vsbytes, VertexTypePNCTTTX_3.GetLayout())); + layouts.Add(VertexType.PNCTTTTX, new InputLayout(device, vsbytes, VertexTypePNCTTTTX.GetLayout())); + layouts.Add(VertexType.PNCTTX, new InputLayout(device, vsbytes, VertexTypePNCTTX.GetLayout())); + layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vsbytes, VertexTypePNCCTTX.GetLayout())); + layouts.Add(VertexType.PNCCTTX_2, new InputLayout(device, vsbytes, VertexTypePNCCTTX_2.GetLayout())); + layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vsbytes, VertexTypePNCCTTTX.GetLayout())); + layouts.Add(VertexType.PCCNCCTX, new InputLayout(device, vsbytes, VertexTypePCCNCCTX.GetLayout())); + layouts.Add(VertexType.PCCNCTX, new InputLayout(device, vsbytes, VertexTypePCCNCTX.GetLayout())); + layouts.Add(VertexType.PCCNCT, new InputLayout(device, vsbytes, VertexTypePCCNCT.GetLayout())); + layouts.Add(VertexType.PNCCTT, new InputLayout(device, vsbytes, VertexTypePNCCTT.GetLayout())); + layouts.Add(VertexType.PNCCTX, new InputLayout(device, vsbytes, VertexTypePNCCTX.GetLayout())); + layouts.Add(VertexType.PNCH2, new InputLayout(device, vsbytes, VertexTypePNCH2.GetLayout())); + layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vsbytes, VertexTypePCCH2H4.GetLayout())); + layouts.Add(VertexType.PCCNCTT, new InputLayout(device, vsbytes, VertexTypePCCNCTT.GetLayout())); + layouts.Add(VertexType.PCCNCTTX, new InputLayout(device, vsbytes, VertexTypePCCNCTTX.GetLayout())); + layouts.Add(VertexType.PCCNCTTT, new InputLayout(device, vsbytes, VertexTypePCCNCTTT.GetLayout())); + layouts.Add(VertexType.PNCTT, new InputLayout(device, vsbytes, VertexTypePNCTT.GetLayout())); + layouts.Add(VertexType.PNCTTT, new InputLayout(device, vsbytes, VertexTypePNCTTT.GetLayout())); + + + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsamplerc = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Clamp, + AddressV = TextureAddressMode.Clamp, + AddressW = TextureAddressMode.Clamp, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipPoint, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + + } + + + + public override void SetShader(DeviceContext context) + { + context.VertexShader.Set(shadowvs); + context.PixelShader.Set(shadowps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + InputLayout l; + if (layouts.TryGetValue(type, out l)) + { + context.InputAssembler.InputLayout = l; + return true; + } + return false; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + } + public void SetSceneVars(DeviceContext context, Matrix shadowviewproj) + { + VSSceneVars.Vars.ViewProj = Matrix.Transpose(shadowviewproj); + VSSceneVars.Vars.WindVector = WindVector; + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = rend.Orientation; + VSEntityVars.Vars.Scale = rend.Scale; + VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0; + VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0; + VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 1); + } + + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + if (!model.UseTransform) return; + VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform); + VSModelVars.Update(context); + VSModelVars.SetVSCBuffer(context, 2); + } + + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + RenderableTexture texture = null; // ((geom.Textures != null) && (geom.Textures.Length > 0)) ? geom.Textures[0] : null; + //RenderableTexture tintpal = null; + + //float tntpalind = 0.0f; + + if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0)) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + switch (ihash) + { + case MetaName.DiffuseSampler: + case MetaName.TextureSampler_layer0: + case MetaName.TextureSampler_layer1: + case MetaName.TextureSampler_layer2: + case MetaName.TextureSampler_layer3: + texture = itex; + break; + } + if (texture != null) break; + } + + ////try get default diffuse texture + //if ((geom.DiffuseSampler >= 0) && (geom.DiffuseSampler < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.DiffuseSampler]; + //} + //if ((texture == null) && (geom.TextureSampler_layer0 >= 0) && (geom.TextureSampler_layer0 < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.TextureSampler_layer0]; + //} + //if ((texture == null) && (geom.TextureSampler_layer1 >= 0) && (geom.TextureSampler_layer1 < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.TextureSampler_layer1]; + //} + //if ((texture == null) && (geom.TextureSampler_layer2 >= 0) && (geom.TextureSampler_layer2 < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.TextureSampler_layer2]; + //} + //if ((texture == null) && (geom.TextureSampler_layer3 >= 0) && (geom.TextureSampler_layer3 < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.TextureSampler_layer3]; + //} + + //fallback try get first texture... eventaully remove this! (helps with water for now) + int index = 0; + while (((texture == null)) && (index < geom.RenderableTextures.Length)) + { + texture = geom.RenderableTextures[index]; + index++; + } + + + //if ((geom.PaletteTexture >= 0) && (geom.PaletteTexture < geom.Textures.Length)) + //{ + // tintpal = geom.Textures[geom.PaletteTexture]; + // if (tintpal.Texture != null) + // { + // //this is slightly dodgy but vsentvarsdata should have the correct value in it... + // tntpalind = (vsentvarsdata.TintPaletteIndex + 0.5f) / tintpal.Texture.Height; + // } + //} + } + + + bool usediff = ((texture != null) && (texture.ShaderResourceView != null)); + + + uint windflag = 0; + var shaderFile = geom.DrawableGeom.Shader.FileName; + switch (shaderFile.Hash) + { + case 2245870123: //trees_normal_diffspec_tnt.sps + case 3334613197: //trees_tnt.sps + case 1229591973://{trees_normal_spec_tnt.sps} + case 2322653400://{trees.sps} + case 3192134330://{trees_normal.sps} + case 1224713457://{trees_normal_spec.sps} + case 4265705004://{trees_normal_diffspec.sps} + windflag = 1; + break; + } + + + + + GeomVars.Vars.EnableTexture = usediff ? 1u : 0u; + GeomVars.Vars.EnableTint = 0u;// usetint ? 1u : 0u; + GeomVars.Vars.IsDecal = 0u;// DecalMode ? 1u : 0u; + GeomVars.Vars.EnableWind = windflag; + GeomVars.Vars.WindOverrideParams = geom.WindOverrideParams; + GeomVars.Update(context); + GeomVars.SetPSCBuffer(context, 0); + GeomVars.SetVSCBuffer(context, 3); + + context.VertexShader.SetSampler(0, texsamplerc); + context.PixelShader.SetSampler(0, texsampler); + //context.PixelShader.SetSampler(1, texsamplerc); + if (usediff) + { + texture.SetPSResource(context, 0); + } + } + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); + context.VertexShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(3, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.SetSampler(0, null); + context.PixelShader.SetSampler(0, null); + context.PixelShader.SetShaderResource(0, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + public void Dispose() + { + if (disposed) return; + + if (texsampler != null) + { + texsampler.Dispose(); + texsampler = null; + } + + foreach (InputLayout layout in layouts.Values) + { + layout.Dispose(); + } + layouts.Clear(); + + VSSceneVars.Dispose(); + VSEntityVars.Dispose(); + VSModelVars.Dispose(); + GeomVars.Dispose(); + + + shadowps.Dispose(); + shadowvs.Dispose(); + + disposed = true; + } + } +} diff --git a/Rendering/Shaders/SkydomeShader.cs b/Rendering/Shaders/SkydomeShader.cs new file mode 100644 index 0000000..24de659 --- /dev/null +++ b/Rendering/Shaders/SkydomeShader.cs @@ -0,0 +1,410 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX.Direct3D11; +using System.IO; +using CodeWalker.GameFiles; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct SkydomeShaderVSSceneVars + { + public Matrix ViewProj; + public Matrix ViewInv; + } + public struct SkydomeShaderVSEntityVars + { + public Vector4 CamRel; + public Quaternion Orientation; + } + public struct SkydomeShaderVSModelVars + { + public Matrix Transform; + } + public struct SkydomeShaderPSSceneVars + { + public Vector4 LightDirection; + public uint EnableHDR; + public uint Pad0; + public uint Pad1; + public uint Pad2; + } + + public struct SkydomeShaderVSSunMoonVars + { + public Matrix ViewProj; + public Matrix ViewInv; + public Vector4 CamRel; + public Vector2 Size; + public Vector2 Offset; + } + public struct SkydomeShaderPSSunMoonVars + { + public Vector4 Colour; + } + + + public struct SkydomeShaderSkySystemLocals + { + public Vector4 azimuthEastColor; // Offset: 0 Size: 12 + public Vector4 azimuthWestColor; // Offset: 16 Size: 12 + public Vector3 azimuthTransitionColor; // Offset: 32 Size: 12 + public float azimuthTransitionPosition; // Offset: 44 Size: 4 + public Vector4 zenithColor; // Offset: 48 Size: 12 + public Vector4 zenithTransitionColor; // Offset: 64 Size: 12 + public Vector4 zenithConstants; // Offset: 80 Size: 16 + public Vector4 skyPlaneColor; // Offset: 96 Size: 16 [unused] + public Vector4 skyPlaneParams; // Offset: 112 Size: 16 [unused] + public float hdrIntensity; // Offset: 128 Size: 4 + public Vector3 sunColor; // Offset: 132 Size: 12 + public Vector4 sunColorHdr; // Offset: 144 Size: 12 + public Vector4 sunDiscColorHdr; // Offset: 160 Size: 12 [unused] + public Vector4 sunConstants; // Offset: 176 Size: 16 + public Vector4 sunDirection; // Offset: 192 Size: 12 + public Vector4 sunPosition; // Offset: 208 Size: 12 [unused] + public Vector4 cloudBaseMinusMidColour; // Offset: 224 Size: 12 + public Vector4 cloudMidColour; // Offset: 240 Size: 12 + public Vector4 cloudShadowMinusBaseColourTimesShadowStrength;// Offset: 256 Size: 12 + public Vector4 cloudDetailConstants; // Offset: 272 Size: 16 + public Vector4 cloudConstants1; // Offset: 288 Size: 16 + public Vector4 cloudConstants2; // Offset: 304 Size: 16 + public Vector4 smallCloudConstants; // Offset: 320 Size: 16 + public Vector4 smallCloudColorHdr; // Offset: 336 Size: 12 + public Vector4 effectsConstants; // Offset: 352 Size: 16 + public float horizonLevel; // Offset: 368 Size: 4 + public Vector3 speedConstants; // Offset: 372 Size: 12 + public float starfieldIntensity; // Offset: 384 Size: 4 + public Vector3 moonDirection; // Offset: 388 Size: 12 + public Vector3 moonPosition; // Offset: 400 Size: 12 [unused] + public float moonIntensity; // Offset: 412 Size: 4 [unused] + public Vector4 lunarCycle; // Offset: 416 Size: 12 + public Vector3 moonColor; // Offset: 432 Size: 12 + public float noiseFrequency; // Offset: 444 Size: 4 [unused] + public float noiseScale; // Offset: 448 Size: 4 [unused] + public float noiseThreshold; // Offset: 452 Size: 4 [unused] + public float noiseSoftness; // Offset: 456 Size: 4 [unused] + public float noiseDensityOffset; // Offset: 460 Size: 4 [unused] + public Vector4 noisePhase; // Offset: 464 Size: 8 [unused] + } + + + public class SkydomeShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader skyvs; + PixelShader skyps; + VertexShader sunvs; + PixelShader sunps; + VertexShader moonvs; + PixelShader moonps; + + GpuVarsBuffer SkyLocalVars; + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSEntityVars; + GpuVarsBuffer VSModelVars; + GpuVarsBuffer PSSceneVars; + + GpuVarsBuffer VSSunMoonVars; + GpuVarsBuffer PSSunMoonVars; + + + SamplerState texsampler; + + InputLayout skylayout; + InputLayout sunlayout; + InputLayout moonlayout; + + UnitDisc sundisc; + UnitQuad moonquad; + + public bool EnableHDR { get; set; } + + + public SkydomeShader(Device device) + { + byte[] skyvsbytes = File.ReadAllBytes("Shaders\\SkydomeVS.cso"); + byte[] skypsbytes = File.ReadAllBytes("Shaders\\SkydomePS.cso"); + byte[] sunvsbytes = File.ReadAllBytes("Shaders\\SkySunVS.cso"); + byte[] sunpsbytes = File.ReadAllBytes("Shaders\\SkySunPS.cso"); + byte[] moonvsbytes = File.ReadAllBytes("Shaders\\SkyMoonVS.cso"); + byte[] moonpsbytes = File.ReadAllBytes("Shaders\\SkyMoonPS.cso"); + + skyvs = new VertexShader(device, skyvsbytes); + skyps = new PixelShader(device, skypsbytes); + sunvs = new VertexShader(device, sunvsbytes); + sunps = new PixelShader(device, sunpsbytes); + moonvs = new VertexShader(device, moonvsbytes); + moonps = new PixelShader(device, moonpsbytes); + + SkyLocalVars = new GpuVarsBuffer(device); + VSSceneVars = new GpuVarsBuffer(device); + VSEntityVars = new GpuVarsBuffer(device); + VSModelVars = new GpuVarsBuffer(device); + PSSceneVars = new GpuVarsBuffer(device); + + VSSunMoonVars = new GpuVarsBuffer(device); + PSSunMoonVars = new GpuVarsBuffer(device); + + sundisc = new UnitDisc(device, 30, true); + sunlayout = new InputLayout(device, sunvsbytes, sundisc.GetLayout()); + skylayout = new InputLayout(device, skyvsbytes, VertexTypePTT.GetLayout()); + + moonquad = new UnitQuad(device, true); + moonlayout = new InputLayout(device, moonvsbytes, moonquad.GetLayout()); + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + + } + + + + public override void SetShader(DeviceContext context) + { + context.VertexShader.Set(skyvs); + context.PixelShader.Set(skyps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + if (type != VertexType.PTT) + { + return false; + } + context.InputAssembler.InputLayout = skylayout; + return true; + } + + public void UpdateSkyLocals(Weather weather, ShaderGlobalLights lights) + { + var wv = weather.CurrentValues; + + float skyhdr = EnableHDR ? wv.skyHdr : Math.Min(wv.skyHdr, 1.8f); + float sunhdr = EnableHDR ? wv.skySunHdr : Math.Min(wv.skySunHdr, 4.8f); //NO HDR - turn it down!!! + float scathdr = EnableHDR ? wv.skySunScatterInten : Math.Min(wv.skySunScatterInten, 1.8f); + Vector3 suncolhdr = wv.skySunCol * sunhdr; + Vector4 azecol = wv.skyAzimuthEastCol; + Vector4 azwcol = wv.skyAzimuthWestCol; + Vector4 aztcol = wv.skyAzimuthTransitionCol; + Vector4 zencol = wv.skyZenithCol; + Vector4 zetcol = wv.skyZenithTransitionCol; + Vector4 plncol = wv.skyPlane; + + SkyLocalVars.Vars.azimuthEastColor = azecol; + SkyLocalVars.Vars.azimuthWestColor = azwcol; + SkyLocalVars.Vars.azimuthTransitionColor = aztcol.XYZ(); + SkyLocalVars.Vars.azimuthTransitionPosition = wv.skyAzimuthTransition; + SkyLocalVars.Vars.zenithColor = zencol; + SkyLocalVars.Vars.zenithTransitionColor = zetcol; + SkyLocalVars.Vars.zenithConstants = wv.skyZenithTransition; + SkyLocalVars.Vars.skyPlaneColor = plncol; + SkyLocalVars.Vars.skyPlaneParams = Vector4.Zero; + SkyLocalVars.Vars.hdrIntensity = skyhdr; + SkyLocalVars.Vars.sunColor = wv.skySunCol; + SkyLocalVars.Vars.sunColorHdr = new Vector4(suncolhdr, sunhdr); + SkyLocalVars.Vars.sunDiscColorHdr = new Vector4(wv.skySunDiscCol, wv.skySunDiscSize); + //SkyLocalVars.Vars.sunConstants = new Vector4(wv.skySunMie, scathdr); + //SkyLocalVars.Vars.sunConstants.X = wv.skySunMie.X; //mie phase + //SkyLocalVars.Vars.sunConstants.Y = wv.skySunMie.Y; //mie scatter + //SkyLocalVars.Vars.sunConstants.Z = 0.5f / wv.skySunInfluenceRadius;// * 0.01f; // 0.0025f; //mie size/"range" + //SkyLocalVars.Vars.sunConstants.W = wv.skySunMie.Z;// * scathdr; //mie hdr intensity + SkyLocalVars.Vars.sunConstants.X = wv.skySunMie.X * wv.skySunMie.Y; //mie phase + SkyLocalVars.Vars.sunConstants.Y = wv.skySunMie.Y;// 1.0f /wv.skySunMie.Y;// 1.7f;// wv.skySunMie.Y; //mie scatter + SkyLocalVars.Vars.sunConstants.Z = 0.00003f * wv.skySunInfluenceRadius;// * wv.skySunMie.X;// wv.skySunMie.Z;///720.0f;// * 0.01f; // 0.0025f; //mie size/"range" + SkyLocalVars.Vars.sunConstants.W = wv.skySunMie.Z;// * scathdr; //mie intensity multiplier + SkyLocalVars.Vars.sunDirection = new Vector4(-lights.CurrentSunDir, 0);// wv.sunDirection, 0); + SkyLocalVars.Vars.sunPosition = new Vector4(-lights.CurrentSunDir, 0); //not used + SkyLocalVars.Vars.cloudBaseMinusMidColour = Vector4.Zero; + SkyLocalVars.Vars.cloudMidColour = Vector4.Zero; + SkyLocalVars.Vars.cloudShadowMinusBaseColourTimesShadowStrength = Vector4.Zero; + SkyLocalVars.Vars.cloudDetailConstants = Vector4.Zero; + SkyLocalVars.Vars.cloudConstants1 = Vector4.Zero; + SkyLocalVars.Vars.cloudConstants2 = Vector4.Zero; + SkyLocalVars.Vars.smallCloudConstants = Vector4.Zero; + SkyLocalVars.Vars.smallCloudColorHdr = Vector4.Zero; + SkyLocalVars.Vars.effectsConstants = Vector4.Zero; + SkyLocalVars.Vars.horizonLevel = 0; + SkyLocalVars.Vars.speedConstants = Vector3.Zero; + SkyLocalVars.Vars.starfieldIntensity = wv.skyStarsIten * 5.0f; //makes stars brighter.... + SkyLocalVars.Vars.moonDirection = wv.moonDirection; + SkyLocalVars.Vars.moonPosition = Vector3.Zero;//need to update this? + SkyLocalVars.Vars.moonIntensity = wv.skyMoonIten; + SkyLocalVars.Vars.lunarCycle = Vector4.Zero; + SkyLocalVars.Vars.moonColor = wv.skyMoonCol; + SkyLocalVars.Vars.noiseFrequency = 0; + SkyLocalVars.Vars.noiseScale = 0; + SkyLocalVars.Vars.noiseThreshold = 0; + SkyLocalVars.Vars.noiseSoftness = 0; + SkyLocalVars.Vars.noiseDensityOffset = 0; + SkyLocalVars.Vars.noisePhase = Vector4.Zero; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + SkyLocalVars.Update(context); + SkyLocalVars.SetVSCBuffer(context, 0); + SkyLocalVars.SetPSCBuffer(context, 0); + + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix); + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 1); + + PSSceneVars.Vars.LightDirection = new Vector4(lights.Params.LightDir, 0.0f); + PSSceneVars.Vars.EnableHDR = EnableHDR ? 1u : 0u; + PSSceneVars.Update(context); + PSSceneVars.SetPSCBuffer(context, 1); + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = rend.Orientation; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + } + + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + if (!model.UseTransform) return; + VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform); + VSModelVars.Update(context); + VSModelVars.SetVSCBuffer(context, 3); + } + + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + //don't use this version + } + + public void SetTextures(DeviceContext context, RenderableTexture starfield) + { + if (starfield != null) + { + context.PixelShader.SetSampler(0, texsampler); + starfield.SetPSResource(context, 0); + } + } + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); + context.PixelShader.SetConstantBuffer(1, null); + context.VertexShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(3, null); + context.PixelShader.SetSampler(0, null); + context.PixelShader.SetShaderResource(0, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + + public void RenderSun(DeviceContext context, Camera camera, Weather weather, ShaderGlobalLights lights) + { + + context.VertexShader.Set(sunvs); + context.PixelShader.Set(sunps); + + VSSunMoonVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSunMoonVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix); + VSSunMoonVars.Vars.CamRel = new Vector4(lights.CurrentSunDir, 0); + VSSunMoonVars.Vars.Size = new Vector2(weather.CurrentValues.skySunDiscSize * 0.008f); + VSSunMoonVars.Vars.Offset = Vector2.Zero; + VSSunMoonVars.Update(context); + VSSunMoonVars.SetVSCBuffer(context, 0); + + PSSunMoonVars.Vars.Colour = new Vector4(weather.CurrentValues.skySunDiscCol * weather.CurrentValues.skySunHdr, 1); + PSSunMoonVars.Update(context); + PSSunMoonVars.SetPSCBuffer(context, 0); + + context.InputAssembler.InputLayout = sunlayout; + sundisc.Draw(context); + } + + public void RenderMoon(DeviceContext context, Camera camera, Weather weather, ShaderGlobalLights lights, RenderableTexture moontex) + { + context.VertexShader.Set(moonvs); + context.PixelShader.Set(moonps); + + + Quaternion ori = Quaternion.Invert(Quaternion.LookAtRH(Vector3.Zero, lights.CurrentMoonDir, lights.MoonAxis)); + Matrix omat = ori.ToMatrix(); + + + VSSunMoonVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSunMoonVars.Vars.ViewInv = Matrix.Transpose(omat);// camera.ViewInvMatrix); + VSSunMoonVars.Vars.CamRel = new Vector4(lights.CurrentMoonDir, 0); + VSSunMoonVars.Vars.Size = new Vector2(weather.CurrentValues.skyMoonDiscSize * 0.008f); + VSSunMoonVars.Vars.Offset = Vector2.Zero; + VSSunMoonVars.Update(context); + VSSunMoonVars.SetVSCBuffer(context, 0); + + PSSunMoonVars.Vars.Colour = new Vector4(weather.CurrentValues.skyMoonCol * weather.CurrentValues.skyMoonIten, weather.CurrentValues.skyMoonIten); + PSSunMoonVars.Update(context); + PSSunMoonVars.SetPSCBuffer(context, 0); + + context.PixelShader.SetSampler(0, texsampler); + moontex.SetPSResource(context, 0); + + context.InputAssembler.InputLayout = moonlayout; + moonquad.Draw(context); + } + + + + + public void Dispose() + { + if (disposed) return; + disposed = true; + + texsampler.Dispose(); + + sundisc.Dispose(); + moonquad.Dispose(); + + skylayout.Dispose(); + sunlayout.Dispose(); + moonlayout.Dispose(); + + VSSunMoonVars.Dispose(); + PSSunMoonVars.Dispose(); + + SkyLocalVars.Dispose(); + VSSceneVars.Dispose(); + VSEntityVars.Dispose(); + VSModelVars.Dispose(); + PSSceneVars.Dispose(); + + skyps.Dispose(); + skyvs.Dispose(); + sunps.Dispose(); + sunvs.Dispose(); + moonps.Dispose(); + moonvs.Dispose(); + } + } +} diff --git a/Rendering/Shaders/TerrainShader.cs b/Rendering/Shaders/TerrainShader.cs new file mode 100644 index 0000000..446015b --- /dev/null +++ b/Rendering/Shaders/TerrainShader.cs @@ -0,0 +1,645 @@ +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX; +using CodeWalker.GameFiles; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct TerrainShaderVSSceneVars + { + public Matrix ViewProj; + } + public struct TerrainShaderVSEntityVars + { + public Vector4 CamRel; + public Quaternion Orientation; + public uint HasSkeleton; + public uint HasTransforms; + public uint TintPaletteIndex; + public uint Pad1; + public Vector3 Scale; + public uint Pad2; + } + public struct TerrainShaderVSModelVars + { + public Matrix Transform; + } + public struct TerrainShaderVSGeomVars + { + public uint EnableTint; + public float TintYVal; + public uint Pad4; + public uint Pad5; + } + public struct TerrainShaderPSSceneVars + { + public ShaderGlobalLightParams GlobalLights; + public uint EnableShadows; + public uint RenderMode; //0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct + public uint RenderModeIndex; //colour/texcoord index + public uint RenderSamplerCoord; //which texcoord to use in single texture mode + } + public struct TerrainShaderPSGeomVars + { + public uint EnableTexture0; + public uint EnableTexture1; + public uint EnableTexture2; + public uint EnableTexture3; + public uint EnableTexture4; + public uint EnableTextureMask; + public uint EnableNormalMap; + public uint ShaderName; + public uint EnableTint; + public uint EnableVertexColour; + public float bumpiness; + public uint Pad102; + } + + public class TerrainShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader pncctvs; + VertexShader pnccttvs; + VertexShader pnccttxvs; + VertexShader pncctttxvs; + VertexShader pncctxvs; + VertexShader pnctttxvs; + VertexShader pncttxvs; + PixelShader terrainps; + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSEntityVars; + GpuVarsBuffer VSModelVars; + GpuVarsBuffer VSGeomVars; + GpuVarsBuffer PSSceneVars; + GpuVarsBuffer PSGeomVars; + SamplerState texsampler; + SamplerState texsampleranis; + SamplerState texsamplertnt; + public bool AnisotropicFilter = false; + public WorldRenderMode RenderMode = WorldRenderMode.Default; + public int RenderVertexColourIndex = 1; + public int RenderTextureCoordIndex = 1; + public int RenderTextureSamplerCoord = 1; + public MetaName RenderTextureSampler = MetaName.DiffuseSampler; + + private Dictionary layouts = new Dictionary(); + + + public TerrainShader(Device device) + { + byte[] vspncct = File.ReadAllBytes("Shaders\\TerrainVS_PNCCT.cso"); + byte[] vspncctt = File.ReadAllBytes("Shaders\\TerrainVS_PNCCTT.cso"); + byte[] vspnccttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCCTTX.cso"); + byte[] vspncctttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCCTTTX.cso"); + byte[] vspncctx = File.ReadAllBytes("Shaders\\TerrainVS_PNCCTX.cso"); + byte[] vspnctttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCTTTX.cso"); + byte[] vspncttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCTTX.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\TerrainPS.cso"); + + pncctvs = new VertexShader(device, vspncct); + pnccttvs = new VertexShader(device, vspncctt); + pnccttxvs = new VertexShader(device, vspnccttx); + pncctttxvs = new VertexShader(device, vspncctttx); + pncctxvs = new VertexShader(device, vspncctx); + pnctttxvs = new VertexShader(device, vspnctttx); + pncttxvs = new VertexShader(device, vspncttx); + terrainps = new PixelShader(device, psbytes); + + VSSceneVars = new GpuVarsBuffer(device); + VSEntityVars = new GpuVarsBuffer(device); + VSModelVars = new GpuVarsBuffer(device); + VSGeomVars = new GpuVarsBuffer(device); + PSSceneVars = new GpuVarsBuffer(device); + PSGeomVars = new GpuVarsBuffer(device); + + //supported layouts - requires Position, Normal, Colour, Texcoord + layouts.Add(VertexType.PNCCT, new InputLayout(device, vspncct, VertexTypePNCCT.GetLayout())); + layouts.Add(VertexType.PNCCTT, new InputLayout(device, vspncctt, VertexTypePNCCTT.GetLayout())); + layouts.Add(VertexType.PNCTTX, new InputLayout(device, vspncttx, VertexTypePNCTTX.GetLayout())); + layouts.Add(VertexType.PNCTTTX_3, new InputLayout(device, vspnctttx, VertexTypePNCTTTX_3.GetLayout())); + layouts.Add(VertexType.PNCCTX, new InputLayout(device, vspncctx, VertexTypePNCCTX.GetLayout())); + layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vspnccttx, VertexTypePNCCTTX.GetLayout())); + layouts.Add(VertexType.PNCCTTX_2, new InputLayout(device, vspnccttx, VertexTypePNCCTTX_2.GetLayout())); + layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vspncctttx, VertexTypePNCCTTTX.GetLayout())); + + + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsampleranis = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.Anisotropic, + MaximumAnisotropy = 8, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsamplertnt = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.White, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipPoint, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + + } + + + private void SetVertexShader(DeviceContext context, uint shaderhash) + { + //no longer used. + + + //PNCCT terrain_cb_w_4lyr_lod (terrain_cb_w_4lyr_lod.sps) + //PNCCTT terrain_cb_w_4lyr_2tex_blend_lod (terrain_cb_w_4lyr_2tex_blend_lod.sps) + //PNCTTX terrain_cb_w_4lyr_cm (terrain_cb_w_4lyr_cm.sps) + //PNCTTX terrain_cb_w_4lyr_cm_tnt (terrain_cb_w_4lyr_cm_tnt.sps) + //PNCTTTX_3 terrain_cb_w_4lyr_cm_pxm (terrain_cb_w_4lyr_cm_pxm.sps) + //PNCTTTX_3 terrain_cb_w_4lyr_cm_pxm_tnt (terrain_cb_w_4lyr_cm_pxm_tnt.sps) + //PNCCTX terrain_cb_w_4lyr (terrain_cb_w_4lyr.sps) + //PNCCTX terrain_cb_w_4lyr_spec (terrain_cb_w_4lyr_spec.sps) + //PNCCTTX terrain_cb_w_4lyr_2tex (terrain_cb_w_4lyr_2tex.sps) + //PNCCTTX terrain_cb_w_4lyr_2tex_blend (terrain_cb_w_4lyr_2tex_blend.sps) + //PNCCTTX_2 terrain_cb_w_4lyr_pxm (terrain_cb_w_4lyr_pxm.sps) + //PNCCTTX_2 terrain_cb_w_4lyr_pxm_spm (terrain_cb_w_4lyr_pxm_spm.sps) + //PNCCTTX_2 terrain_cb_w_4lyr_spec_pxm (terrain_cb_w_4lyr_spec_pxm.sps) + //PNCCTTTX terrain_cb_w_4lyr_2tex_pxm (terrain_cb_w_4lyr_2tex_pxm.sps) + //PNCCTTTX terrain_cb_w_4lyr_2tex_blend_pxm (terrain_cb_w_4lyr_2tex_blend_pxm.sps) + //PNCCTTTX terrain_cb_w_4lyr_2tex_blend_pxm_spm (terrain_cb_w_4lyr_2tex_blend_pxm_spm.sps) + + + VertexType vt = VertexType.Default; + switch (shaderhash) + { + case 295525123: //terrain_cb_w_4lyr_cm (terrain_cb_w_4lyr_cm.sps) vt: PNCTTX + case 417637541: //terrain_cb_w_4lyr_cm_tnt (terrain_cb_w_4lyr_cm_tnt.sps) vt: PNCTTX + vt = VertexType.PNCTTX; + break; + case 3965214311: //terrain_cb_w_4lyr_cm_pxm_tnt (terrain_cb_w_4lyr_cm_pxm_tnt.sps) vt: PNCTTTX_3 + case 4186046662: //terrain_cb_w_4lyr_cm_pxm (terrain_cb_w_4lyr_cm_pxm.sps) vt: PNCTTTX_3 + vt = VertexType.PNCTTTX; //cs6_08_struct08 + break; + case 3051127652: //terrain_cb_w_4lyr (terrain_cb_w_4lyr.sps) vt: PNCCTX + case 646532852: //terrain_cb_w_4lyr_spec (terrain_cb_w_4lyr_spec.sps) vt: PNCCTX + vt = VertexType.PNCCTX; //hw1_07_grnd_c.. + break; + case 2535953532: //terrain_cb_w_4lyr_2tex_blend_lod (terrain_cb_w_4lyr_2tex_blend_lod.sps) vt: PNCCTT + vt = VertexType.PNCCTT; //cs1_12_riverbed1_lod.. + break; + case 137526804: //terrain_cb_w_4lyr_lod (terrain_cb_w_4lyr_lod.sps) vt: PNCCT + vt = VertexType.PNCCT; //brdgeplatform_01_lod.. + break; + case 2316006813: //terrain_cb_w_4lyr_2tex_blend (terrain_cb_w_4lyr_2tex_blend.sps) vt: PNCCTTX + case 3112820305: //terrain_cb_w_4lyr_2tex (terrain_cb_w_4lyr_2tex.sps) vt: PNCCTTX + case 2601000386: //terrain_cb_w_4lyr_spec_pxm (terrain_cb_w_4lyr_spec_pxm.sps) vt: PNCCTTX_2 + case 4105814572: //terrain_cb_w_4lyr_pxm (terrain_cb_w_4lyr_pxm.sps) vt: PNCCTTX_2 + case 3400824277: //terrain_cb_w_4lyr_pxm_spm (terrain_cb_w_4lyr_pxm_spm.sps) vt: PNCCTTX_2 + vt = VertexType.PNCCTTX; //ch2_04_land02b, ch2_06_terrain01a .. vb_35_beacha + break; + case 653544224: //terrain_cb_w_4lyr_2tex_blend_pxm_spm (terrain_cb_w_4lyr_2tex_blend_pxm_spm.sps) vt: PNCCTTTX + case 2486206885: //terrain_cb_w_4lyr_2tex_blend_pxm (terrain_cb_w_4lyr_2tex_blend_pxm.sps) vt: PNCCTTTX + case 1888432890: //terrain_cb_w_4lyr_2tex_pxm (terrain_cb_w_4lyr_2tex_pxm.sps) vt: PNCCTTTX + vt = VertexType.PNCCTTTX; //ch1_04b_vineland01.. + break; + default: + break; + } + SetVertexShader(context, vt); + } + private void SetVertexShader(DeviceContext context, VertexType type) + { + VertexShader vs = pnccttxvs; + switch (type) + { + case VertexType.PNCCT: vs = pncctvs; break; + case VertexType.PNCCTT: vs = pnccttvs; break; + case VertexType.PNCTTX: vs = pncttxvs; break; + case VertexType.PNCTTTX_3: vs = pnctttxvs; break; + case VertexType.PNCCTX: vs = pncctxvs; break; + case VertexType.PNCCTTX: vs = pnccttxvs; break; + case VertexType.PNCCTTX_2: vs = pnccttxvs; break; + case VertexType.PNCCTTTX: vs = pncctttxvs; break; + } + context.VertexShader.Set(vs); + } + + public override void SetShader(DeviceContext context) + { + context.PixelShader.Set(terrainps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + InputLayout l; + if (layouts.TryGetValue(type, out l)) + { + SetVertexShader(context, type); //need to use the correct VS. + context.InputAssembler.InputLayout = l; + return true; + } + return false; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + uint rendermode = 0; + uint rendermodeind = 1; + + switch (RenderMode) + { + case WorldRenderMode.VertexNormals: + rendermode = 1; + break; + case WorldRenderMode.VertexTangents: + rendermode = 2; + break; + case WorldRenderMode.VertexColour: + rendermode = 3; + rendermodeind = (uint)RenderVertexColourIndex; + break; + case WorldRenderMode.TextureCoord: + rendermode = 4; + rendermodeind = (uint)RenderTextureCoordIndex; + break; + case WorldRenderMode.SingleTexture: + switch (RenderTextureSampler) + { + case MetaName.DiffuseSampler: + rendermode = 5; + break; + case MetaName.BumpSampler: + rendermode = 6; + break; + case MetaName.SpecSampler: + rendermode = 7; + break; + default: + rendermode = 8; + break; + } + break; + } + + + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + + + PSSceneVars.Vars.GlobalLights = lights.Params; + PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u; + PSSceneVars.Vars.RenderMode = rendermode; + PSSceneVars.Vars.RenderModeIndex = rendermodeind; + PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord; + PSSceneVars.Update(context); + PSSceneVars.SetPSCBuffer(context, 0); + + if (shadowmap != null) + { + shadowmap.SetFinalRenderResources(context); + } + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = rend.Orientation; + VSEntityVars.Vars.Scale = rend.Scale; + VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0; + VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0; + VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + } + + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + if (!model.UseTransform) return; + VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform); + VSModelVars.Update(context); + VSModelVars.SetVSCBuffer(context, 3); + } + + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + RenderableTexture texture0 = null; + RenderableTexture texture1 = null; + RenderableTexture texture2 = null; + RenderableTexture texture3 = null; + RenderableTexture texture4 = null; + RenderableTexture texturemask = null; + RenderableTexture tintpal = null; + RenderableTexture normals0 = null; + RenderableTexture normals1 = null; + RenderableTexture normals2 = null; + RenderableTexture normals3 = null; + RenderableTexture normals4 = null; + float tntpalind = 0.0f; + bool usevc = true; + + if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0)) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + switch (ihash) + { + case MetaName.DiffuseSampler: + texture0 = itex; + break; + case MetaName.TextureSampler_layer0: + texture1 = itex; + break; + case MetaName.TextureSampler_layer1: + texture2 = itex; + break; + case MetaName.TextureSampler_layer2: + texture3 = itex; + break; + case MetaName.TextureSampler_layer3: + texture4 = itex; + break; + case MetaName.BumpSampler: + normals0 = itex; + break; + case MetaName.BumpSampler_layer0: + normals1 = itex; + break; + case MetaName.BumpSampler_layer1: + normals2 = itex; + break; + case MetaName.BumpSampler_layer2: + normals3 = itex; + break; + case MetaName.BumpSampler_layer3: + normals4 = itex; + break; + case MetaName.lookupSampler: + texturemask = itex; + break; + case MetaName.TintPaletteSampler: + tintpal = itex; + if (tintpal.Key != null) + { + //this is slightly dodgy but vsentvarsdata should have the correct value in it... + tntpalind = (VSEntityVars.Vars.TintPaletteIndex + 0.5f) / tintpal.Key.Height; + } + break; + } + } + + //if ((geom.DiffuseSampler >= 0) && (geom.DiffuseSampler < geom.Textures.Length)) + //{ + // texture0 = geom.Textures[geom.DiffuseSampler]; + //} + //if ((geom.TextureSampler_layer0 >= 0) && (geom.TextureSampler_layer0 < geom.Textures.Length)) + //{ + // texture1 = geom.Textures[geom.TextureSampler_layer0]; + //} + //if ((geom.TextureSampler_layer1 >= 0) && (geom.TextureSampler_layer1 < geom.Textures.Length)) + //{ + // texture2 = geom.Textures[geom.TextureSampler_layer1]; + //} + //if ((geom.TextureSampler_layer2 >= 0) && (geom.TextureSampler_layer2 < geom.Textures.Length)) + //{ + // texture3 = geom.Textures[geom.TextureSampler_layer2]; + //} + //if ((geom.TextureSampler_layer3 >= 0) && (geom.TextureSampler_layer3 < geom.Textures.Length)) + //{ + // texture4 = geom.Textures[geom.TextureSampler_layer3]; + //} + //if ((geom.BumpSampler >= 0) && (geom.BumpSampler < geom.Textures.Length)) + //{ + // normals0 = geom.Textures[geom.BumpSampler]; + //} + //if ((geom.BumpSampler_layer0 >= 0) && (geom.BumpSampler_layer0 < geom.Textures.Length)) + //{ + // normals1 = geom.Textures[geom.BumpSampler_layer0]; + //} + //if ((geom.BumpSampler_layer1 >= 0) && (geom.BumpSampler_layer1 < geom.Textures.Length)) + //{ + // normals2 = geom.Textures[geom.BumpSampler_layer1]; + //} + //if ((geom.BumpSampler_layer2 >= 0) && (geom.BumpSampler_layer2 < geom.Textures.Length)) + //{ + // normals3 = geom.Textures[geom.BumpSampler_layer2]; + //} + //if ((geom.BumpSampler_layer3 >= 0) && (geom.BumpSampler_layer3 < geom.Textures.Length)) + //{ + // normals4 = geom.Textures[geom.BumpSampler_layer3]; + //} + //if ((geom.lookupSampler >= 0) && (geom.lookupSampler < geom.Textures.Length)) + //{ + // texturemask = geom.Textures[geom.lookupSampler]; + //} + //if ((geom.TintPaletteSampler >= 0) && (geom.TintPaletteSampler < geom.Textures.Length)) + //{ + // tintpal = geom.Textures[geom.TintPaletteSampler]; + // if (tintpal.Texture != null) + // { + // //this is slightly dodgy but vsentvarsdata should have the correct value in it... + // tntpalind = (vsentvarsdata.TintPaletteIndex + 0.5f) / tintpal.Texture.Height; + // } + //} + + + + } + + if (RenderMode == WorldRenderMode.SingleTexture) + { + usevc = false; + switch (RenderTextureSampler) + { + case MetaName.DiffuseSampler: + case MetaName.BumpSampler: + case MetaName.SpecSampler: + break; + default: + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + if (ihash == RenderTextureSampler) + { + texture0 = itex; + break; + } + } + + //int directtexind = geom.GetTextureSamplerIndex(RenderTextureSampler); + //if ((directtexind >= 0) && (directtexind < geom.Textures.Length)) + //{ + // texture0 = geom.Textures[directtexind]; + //} + break; + } + } + + bool usediff0 = ((texture0 != null) && (texture0.ShaderResourceView != null)); + bool usediff1 = ((texture1 != null) && (texture1.ShaderResourceView != null)); + bool usediff2 = ((texture2 != null) && (texture2.ShaderResourceView != null)); + bool usediff3 = ((texture3 != null) && (texture3.ShaderResourceView != null)); + bool usediff4 = ((texture4 != null) && (texture4.ShaderResourceView != null)); + bool usemask = ((texturemask != null) && (texturemask.ShaderResourceView != null)); + bool usetint = ((tintpal != null) && (tintpal.ShaderResourceView != null)); + bool usenm = (((normals0 != null) && (normals0.ShaderResourceView != null)) || ((normals1 != null) && (normals1.ShaderResourceView != null))); + + + float bumpiness = 1.0f; + if (usenm) + { + bumpiness = geom.bumpiness; + } + + + PSGeomVars.Vars.EnableTexture0 = usediff0 ? 1u : 0u; + PSGeomVars.Vars.EnableTexture1 = usediff1 ? 1u : 0u; + PSGeomVars.Vars.EnableTexture2 = usediff2 ? 1u : 0u; + PSGeomVars.Vars.EnableTexture3 = usediff3 ? 1u : 0u; + PSGeomVars.Vars.EnableTexture4 = usediff4 ? 1u : 0u; + PSGeomVars.Vars.EnableTextureMask = usemask ? 1u : 0u; + PSGeomVars.Vars.EnableNormalMap = usenm ? 1u : 0u; + PSGeomVars.Vars.ShaderName = geom.DrawableGeom.Shader.Name.Hash; + PSGeomVars.Vars.EnableTint = usetint ? 1u : 0u; + PSGeomVars.Vars.EnableVertexColour = usevc ? 1u : 0u; + PSGeomVars.Vars.bumpiness = bumpiness;// + PSGeomVars.Update(context); + PSGeomVars.SetPSCBuffer(context, 2); + + VSGeomVars.Vars.EnableTint = usetint ? 1u : 0u; + VSGeomVars.Vars.TintYVal = tntpalind; + VSGeomVars.Update(context); + VSGeomVars.SetVSCBuffer(context, 4); + + + context.VertexShader.SetSampler(0, texsamplertnt); + context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler); + + if (usediff0) texture0.SetPSResource(context, 0); + if (usediff1) texture1.SetPSResource(context, 2); + if (usediff2) texture2.SetPSResource(context, 3); + if (usediff3) texture3.SetPSResource(context, 4); + if (usediff4) texture4.SetPSResource(context, 5); + if (usemask) texturemask.SetPSResource(context, 6); + if (usetint) tintpal.SetVSResource(context, 0); + if (normals0 != null) normals0.SetPSResource(context, 7); + if (normals1 != null) normals1.SetPSResource(context, 8); + if (normals2 != null) normals2.SetPSResource(context, 9); + if (normals3 != null) normals3.SetPSResource(context, 10); + if (normals4 != null) normals4.SetPSResource(context, 11); + + } + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); //shadowmap + context.PixelShader.SetConstantBuffer(1, null); //shadowmap + context.PixelShader.SetShaderResource(1, null);//shadowmap + context.PixelShader.SetSampler(1, null); //shadowmap + context.VertexShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(3, null); + context.PixelShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(4, null); + context.VertexShader.SetSampler(0, null); + context.PixelShader.SetSampler(0, null); + context.VertexShader.SetShaderResource(0, null); + context.PixelShader.SetShaderResource(0, null); + context.PixelShader.SetShaderResource(2, null); + context.PixelShader.SetShaderResource(3, null); + context.PixelShader.SetShaderResource(4, null); + context.PixelShader.SetShaderResource(5, null); + context.PixelShader.SetShaderResource(6, null); + context.PixelShader.SetShaderResource(7, null); + context.PixelShader.SetShaderResource(8, null); + context.PixelShader.SetShaderResource(9, null); + context.PixelShader.SetShaderResource(10, null); + context.PixelShader.SetShaderResource(11, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + public void Dispose() + { + if (disposed) return; + + if (texsampler != null) + { + texsampler.Dispose(); + texsampler = null; + } + if (texsampleranis != null) + { + texsampleranis.Dispose(); + texsampleranis = null; + } + if (texsamplertnt != null) + { + texsamplertnt.Dispose(); + texsamplertnt = null; + } + + foreach (InputLayout layout in layouts.Values) + { + layout.Dispose(); + } + layouts.Clear(); + + VSSceneVars.Dispose(); + VSEntityVars.Dispose(); + VSModelVars.Dispose(); + VSGeomVars.Dispose(); + PSSceneVars.Dispose(); + PSGeomVars.Dispose(); + + terrainps.Dispose(); + pncctvs.Dispose(); + pnccttvs.Dispose(); + pnccttxvs.Dispose(); + pncctttxvs.Dispose(); + pncctxvs.Dispose(); + pnctttxvs.Dispose(); + pncttxvs.Dispose(); + + disposed = true; + } + } +} diff --git a/Rendering/Shaders/TreesLodShader.cs b/Rendering/Shaders/TreesLodShader.cs new file mode 100644 index 0000000..c3b15be --- /dev/null +++ b/Rendering/Shaders/TreesLodShader.cs @@ -0,0 +1,320 @@ +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX; +using CodeWalker.GameFiles; +using CodeWalker.World; + +namespace CodeWalker.Rendering +{ + + public struct TreesLodShaderVSSceneVars + { + public Matrix ViewProj; + } + public struct TreesLodShaderVSEntityVars + { + public Vector4 CamRel; + public Quaternion Orientation; + public uint HasSkeleton; + public uint HasTransforms; + public uint Pad0; + public uint Pad1; + public Vector3 Scale; + public uint Pad2; + } + public struct TreesLodShaderVSModelVars + { + public Matrix Transform; + } + public struct TreesLodShaderVSGeometryVars + { + public Vector4 AlphaTest; + public Vector4 AlphaScale; + public Vector4 UseTreeNormals; + public Vector4 treeLod2Normal; + public Vector4 treeLod2Params; + } + public struct TreesLodShaderPSSceneVars + { + public ShaderGlobalLightParams GlobalLights; + } + public struct TreesLodShaderPSEntityVars + { + public uint EnableTexture; + public uint Pad1; + public uint Pad2; + public uint Pad3; + } + + public class TreesLodShader : Shader, IDisposable + { + bool disposed = false; + + VertexShader basicvs; + PixelShader basicps; + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSEntityVars; + GpuVarsBuffer VSModelVars; + GpuVarsBuffer VSGeomVars; + GpuVarsBuffer PSSceneVars; + GpuVarsBuffer PSEntityVars; + SamplerState texsampler; + + private Dictionary layouts = new Dictionary(); + + + public TreesLodShader(Device device) + { + byte[] vsbytes = File.ReadAllBytes("Shaders\\TreesLodVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\TreesLodPS.cso"); + + basicvs = new VertexShader(device, vsbytes); + basicps = new PixelShader(device, psbytes); + + VSSceneVars = new GpuVarsBuffer(device); + VSEntityVars = new GpuVarsBuffer(device); + VSModelVars = new GpuVarsBuffer(device); + VSGeomVars = new GpuVarsBuffer(device); + PSSceneVars = new GpuVarsBuffer(device); + PSEntityVars = new GpuVarsBuffer(device); + + //layouts.Add(VertexType.PNCCT, new InputLayout(device, vsbytes, VertexTypePNCCT.GetLayout())); + layouts.Add(VertexType.PNCCTTTT, new InputLayout(device, vsbytes, VertexTypePNCCTTTT.GetLayout())); + + + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + + } + + + + public override void SetShader(DeviceContext context) + { + context.VertexShader.Set(basicvs); + context.PixelShader.Set(basicps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + InputLayout l; + if (layouts.TryGetValue(type, out l)) + { + context.InputAssembler.InputLayout = l; + return true; + } + return false; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + + PSSceneVars.Vars.GlobalLights = lights.Params; + PSSceneVars.Update(context); + PSSceneVars.SetPSCBuffer(context, 0); + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = rend.Orientation; + VSEntityVars.Vars.Scale = rend.Scale; + VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0; + VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 1); + } + + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + if (!model.UseTransform) return; + VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform); + VSModelVars.Update(context); + VSModelVars.SetVSCBuffer(context, 2); + } + + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + RenderableTexture texture = null; // ((geom.Textures != null) && (geom.Textures.Length > 0)) ? geom.Textures[0] : null; + + //trees_lod2 + //PNCCTTTT: texcoord2 seems to be 0-1 for the billboard, vertex pos is billboard root. + //param for billboard dir... (treeLod2Normal) + + //trees_lod + //PNCCT: + + + if (geom.VertexType != VertexType.PNCCTTTT) + { } + + var shader = geom.DrawableGeom.Shader; + if (shader.Name.Hash == 1874959840) + { + + int nparams = 0; + MetaName[] hashes = null; + ShaderParameter[] sparams = null; + + if (shader.ParametersList != null) + { + nparams = shader.ParametersList.Hashes.Length; + hashes = shader.ParametersList.Hashes; + sparams = shader.ParametersList.Parameters; + } + + for (int i = 0; i < nparams; i++) + { + var h = shader.ParametersList.Hashes[i]; + switch (h) + { + case MetaName.AlphaTest: VSGeomVars.Vars.AlphaTest = (Vector4)sparams[i].Data; break; + case MetaName.AlphaScale: VSGeomVars.Vars.AlphaScale = (Vector4)sparams[i].Data; break; + case MetaName.UseTreeNormals: VSGeomVars.Vars.UseTreeNormals = (Vector4)sparams[i].Data; break; + case MetaName.treeLod2Normal: VSGeomVars.Vars.treeLod2Normal = (Vector4)sparams[i].Data; break; + case MetaName.treeLod2Params: VSGeomVars.Vars.treeLod2Params = (Vector4)sparams[i].Data; break; + } + } + + + } + else + { + VSGeomVars.Vars.AlphaTest = Vector4.Zero; + VSGeomVars.Vars.AlphaScale = Vector4.Zero; + VSGeomVars.Vars.UseTreeNormals = Vector4.Zero; + VSGeomVars.Vars.treeLod2Normal = Vector4.Zero; + VSGeomVars.Vars.treeLod2Params = Vector4.Zero; + } + + VSGeomVars.Update(context); + VSGeomVars.SetVSCBuffer(context, 3); + + if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0)) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + switch (ihash) + { + case MetaName.DiffuseSampler: + texture = itex; + break; + } + if (texture != null) break; + } + + ////try get default diffuse texture + //if ((geom.DiffuseSampler >= 0) && (geom.DiffuseSampler < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.DiffuseSampler]; + //} + //if ((texture == null) && (geom.TextureSampler_layer0 >= 0) && (geom.TextureSampler_layer0 < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.TextureSampler_layer0]; + //} + //if ((texture == null) && (geom.TextureSampler_layer1 >= 0) && (geom.TextureSampler_layer1 < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.TextureSampler_layer1]; + //} + //if ((texture == null) && (geom.TextureSampler_layer2 >= 0) && (geom.TextureSampler_layer2 < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.TextureSampler_layer2]; + //} + //if ((texture == null) && (geom.TextureSampler_layer3 >= 0) && (geom.TextureSampler_layer3 < geom.Textures.Length)) + //{ + // texture = geom.Textures[geom.TextureSampler_layer3]; + //} + + //fallback try get first texture... + int index = 0; + while (((texture == null) || (texture.Texture2D == null)) && (index < geom.RenderableTextures.Length)) + { + texture = geom.RenderableTextures[index]; + index++; + } + } + + + bool usediff = ((texture != null) && (texture.Texture2D != null) && (texture.ShaderResourceView != null)); + PSEntityVars.Vars.EnableTexture = usediff ? 1u : 0u; + PSEntityVars.Update(context); + PSEntityVars.SetPSCBuffer(context, 1); + + if (usediff) + { + context.PixelShader.SetSampler(0, texsampler); + //context.PixelShader.SetShaderResource(0, difftex.ShaderResourceView); + texture.SetPSResource(context, 0); + } + } + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); + context.VertexShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(3, null); + context.PixelShader.SetConstantBuffer(1, null); + context.PixelShader.SetSampler(0, null); + context.PixelShader.SetShaderResource(0, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + public void Dispose() + { + if (disposed) return; + + if (texsampler != null) + { + texsampler.Dispose(); + texsampler = null; + } + + foreach (InputLayout layout in layouts.Values) + { + layout.Dispose(); + } + layouts.Clear(); + + VSSceneVars.Dispose(); + VSEntityVars.Dispose(); + VSModelVars.Dispose(); + VSGeomVars.Dispose(); + PSSceneVars.Dispose(); + PSEntityVars.Dispose(); + + basicps.Dispose(); + basicvs.Dispose(); + + disposed = true; + } + } +} diff --git a/Rendering/Shaders/WaterShader.cs b/Rendering/Shaders/WaterShader.cs new file mode 100644 index 0000000..41017b6 --- /dev/null +++ b/Rendering/Shaders/WaterShader.cs @@ -0,0 +1,564 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CodeWalker.GameFiles; +using CodeWalker.World; +using SharpDX.Direct3D11; +using SharpDX; +using System.IO; + +namespace CodeWalker.Rendering +{ + public struct WaterShaderVSSceneVars + { + public Matrix ViewProj; + public Vector4 WaterVector; + public float ScaledTime; + public float ScnPad0; + public float ScnPad1; + public float ScnPad2; + } + public struct WaterShaderVSEntityVars + { + public Vector4 CamRel; + public Quaternion Orientation; + public Vector3 Scale; + public uint EntPad0; + } + public struct WaterShaderVSGeomVars + { + public Vector4 WaterParams; + public uint EnableFlow; + public uint ShaderMode; + public uint GeoPad1; + public uint GeoPad2; + public float RippleSpeed; + public float GeoPad3; + public float GeoPad4; + public float GeoPad5; + } + public struct WaterShaderPSSceneVars + { + public ShaderGlobalLightParams GlobalLights; + public uint EnableShadows; + public uint RenderMode;//0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct + public uint RenderModeIndex; //colour/texcoord index + public uint RenderSamplerCoord; //which texcoord to use in single texture mode + public uint EnableWaterbumps;//if the waterbump textures are ready.. + public uint EnableFogtex; //if the fog texture is ready + public uint ScnPad1; + public uint ScnPad2; + public Vector4 gFlowParams; + public Vector4 CameraPos; + public Vector4 WaterFogParams; //xy = base location, zw = inverse size + } + public struct WaterShaderPSGeomVars + { + public uint EnableTexture; + public uint EnableBumpMap; + public uint EnableFoamMap; + public uint ShaderMode; + public float SpecularIntensity; + public float SpecularFalloff; + public float GeoPad1; + public float GeoPad2; + public float WaveOffset; //for terrainfoam + public float WaterHeight; //for terrainfoam + public float WaveMovement; //for terrainfoam + public float HeightOpacity; //for terrainfoam + public float RippleSpeed; + public float RippleScale; + public float RippleBumpiness; + public float GeoPad3; + } + + + public class WaterShader : Shader + { + bool disposed = false; + + VertexShader vspt; + VertexShader vspct; + VertexShader vspnct; + VertexShader vspnctx; + PixelShader ps; + + GpuVarsBuffer VSSceneVars; + GpuVarsBuffer VSEntityVars; + GpuVarsBuffer VSGeomVars; + GpuVarsBuffer PSSceneVars; + GpuVarsBuffer PSGeomVars; + + SamplerState texsampler; + SamplerState texsampleranis; + SamplerState texsamplerflow; + + private Dictionary layouts = new Dictionary(); + + + public bool AnisotropicFilter = false; + public WorldRenderMode RenderMode = WorldRenderMode.Default; + public int RenderVertexColourIndex = 1; + public int RenderTextureCoordIndex = 1; + public int RenderTextureSamplerCoord = 1; + public MetaName RenderTextureSampler = MetaName.DiffuseSampler; + public double CurrentRealTime = 0; + public float CurrentElapsedTime = 0; + public bool SpecularEnable = true; + + + public RenderableTexture waterbump { get; set; } + public RenderableTexture waterbump2 { get; set; } + public RenderableTexture waterfog { get; set; } + + + //check dt1_21_reflproxy and dt1_05_reflproxy + + + public WaterShader(Device device) + { + byte[] vsptbytes = File.ReadAllBytes("Shaders\\WaterVS_PT.cso"); + byte[] vspctbytes = File.ReadAllBytes("Shaders\\WaterVS_PCT.cso"); + byte[] vspnctbytes = File.ReadAllBytes("Shaders\\WaterVS_PNCT.cso"); + byte[] vspnctxbytes = File.ReadAllBytes("Shaders\\WaterVS_PNCTX.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\WaterPS.cso"); + + + vspt = new VertexShader(device, vsptbytes); + vspct = new VertexShader(device, vspctbytes); + vspnct = new VertexShader(device, vspnctbytes); + vspnctx = new VertexShader(device, vspnctxbytes); + ps = new PixelShader(device, psbytes); + + VSSceneVars = new GpuVarsBuffer(device); + VSEntityVars = new GpuVarsBuffer(device); + VSGeomVars = new GpuVarsBuffer(device); + PSSceneVars = new GpuVarsBuffer(device); + PSGeomVars = new GpuVarsBuffer(device); + + layouts.Add(VertexType.PT, new InputLayout(device, vsptbytes, VertexTypePT.GetLayout())); + layouts.Add(VertexType.PCT, new InputLayout(device, vspctbytes, VertexTypePCT.GetLayout())); + layouts.Add(VertexType.Default, new InputLayout(device, vspnctbytes, VertexTypeDefault.GetLayout())); + layouts.Add(VertexType.DefaultEx, new InputLayout(device, vspnctxbytes, VertexTypeDefaultEx.GetLayout())); + + texsampler = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipLinear, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsampleranis = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Wrap, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.Black, + ComparisonFunction = Comparison.Always, + Filter = Filter.Anisotropic, + MaximumAnisotropy = 8, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + texsamplerflow = new SamplerState(device, new SamplerStateDescription() + { + AddressU = TextureAddressMode.Clamp, + AddressV = TextureAddressMode.Wrap, + AddressW = TextureAddressMode.Wrap, + BorderColor = Color.White, + ComparisonFunction = Comparison.Always, + Filter = Filter.MinMagMipPoint, + MaximumAnisotropy = 1, + MaximumLod = float.MaxValue, + MinimumLod = 0, + MipLodBias = 0, + }); + + } + + + private void SetVertexShader(DeviceContext context, VertexType type) + { + VertexShader vs = vspnct; + switch (type) + { + case VertexType.PT: + vs = vspt; + break; + case VertexType.PCT: + vs = vspct; + break; + case VertexType.Default: + vs = vspnct; + break; + case VertexType.DefaultEx: + vs = vspnctx; + break; + + default: + break; + + } + context.VertexShader.Set(vs); + } + + public override void SetShader(DeviceContext context) + { + context.PixelShader.Set(ps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + InputLayout l; + if (layouts.TryGetValue(type, out l)) + { + SetVertexShader(context, type); + context.InputAssembler.InputLayout = l; + return true; + } + return false; + } + + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + uint rendermode = 0; + uint rendermodeind = 1; + + SpecularEnable = lights.SpecularEnabled; + + switch (RenderMode) + { + case WorldRenderMode.VertexNormals: + rendermode = 1; + break; + case WorldRenderMode.VertexTangents: + rendermode = 2; + break; + case WorldRenderMode.VertexColour: + rendermode = 3; + rendermodeind = (uint)RenderVertexColourIndex; + break; + case WorldRenderMode.TextureCoord: + rendermode = 4; + rendermodeind = (uint)RenderTextureCoordIndex; + break; + case WorldRenderMode.SingleTexture: + rendermode = 8;//direct mode + break; + } + + + float phspd = 4.0f; + float phspdi = 1.0f / phspd; + float phspdh = phspd * 0.5f; + float t = (float)(CurrentRealTime - (Math.Floor(CurrentRealTime * 0.001) * 1000.0))*1.0f; + float ta = t * 2.0f; + float tb = ta + (phspdh); + float t1 = (ta * phspdi - (float)Math.Floor(ta * phspdi)) * phspd; + float t2 = (tb * phspdi - (float)Math.Floor(tb * phspdi)) * phspd; + float s1 = ((t1 < phspdh) ? t1 : phspd - t1) * phspdi * 1.0f; + float s2 = ((t2 < phspdh) ? t2 : phspd - t2) * phspdi * 1.0f; + //float s1 = ((float)Math.Cos(t1 * phspdi * Math.PI * 2) + 1.0f) * 0.5f; + //float s2 = ((float)Math.Cos(t2 * phspdi * Math.PI * 2) + 1.0f) * 0.5f; + + float gFlowX = t1*0.5f; + float gFlowY = t2*0.5f; + float gFlowZ = s1; + float gFlowW = s2; + + + Vector2 fogtexMin = new Vector2(-4000.0f, -4000.0f); //aka water quads min/max + Vector2 fogtexMax = new Vector2(4500.0f, 8000.0f); + Vector2 fogtexInv = 1.0f / (fogtexMax - fogtexMin); + + + bool usewaterbumps = (waterbump != null) && (waterbump.ShaderResourceView != null) && (waterbump2 != null) && (waterbump2.ShaderResourceView != null); + bool usefogtex = (waterfog != null) && (waterfog.ShaderResourceView != null); + + VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + VSSceneVars.Vars.WaterVector = Vector4.Zero; + VSSceneVars.Vars.ScaledTime = t * 0.1f; + VSSceneVars.Update(context); + VSSceneVars.SetVSCBuffer(context, 0); + + PSSceneVars.Vars.GlobalLights = lights.Params; + PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u; + PSSceneVars.Vars.RenderMode = rendermode; + PSSceneVars.Vars.RenderModeIndex = rendermodeind; + PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord; + PSSceneVars.Vars.EnableWaterbumps = usewaterbumps ? 1u : 0u; + PSSceneVars.Vars.EnableFogtex = usefogtex ? 1u : 0u; + PSSceneVars.Vars.gFlowParams = new Vector4(gFlowX, gFlowY, gFlowZ, gFlowW); + PSSceneVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f); + PSSceneVars.Vars.WaterFogParams = new Vector4(fogtexMin, fogtexInv.X, fogtexInv.Y); + PSSceneVars.Update(context); + PSSceneVars.SetPSCBuffer(context, 0); + + if (shadowmap != null) + { + shadowmap.SetFinalRenderResources(context); + } + if (usewaterbumps) + { + context.PixelShader.SetShaderResource(4, waterbump.ShaderResourceView); + context.PixelShader.SetShaderResource(5, waterbump2.ShaderResourceView); + } + if (usefogtex) + { + context.PixelShader.SetShaderResource(6, waterfog.ShaderResourceView); + } + + } + + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = rend.Orientation; + VSEntityVars.Vars.Scale = rend.Scale; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + } + + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + } + + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + RenderableTexture texture = null; + RenderableTexture bumptex = null; + RenderableTexture flowtex = null; + RenderableTexture foamtex = null; + RenderableTexture fogtex = null; + + if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0)) + { + if (RenderMode == WorldRenderMode.Default) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + if (itex == null) continue; + switch (ihash) + { + case MetaName.DiffuseSampler: + texture = itex; + break; + case MetaName.BumpSampler: + bumptex = itex; + break; + case MetaName.FlowSampler: + flowtex = itex; + break; + case MetaName.FoamSampler: + foamtex = itex; + break; + case MetaName.FogSampler: + fogtex = itex; + break; + default: + if (texture == null) texture = itex; + break; + } + } + } + else if (RenderMode == WorldRenderMode.SingleTexture) + { + for (int i = 0; i < geom.RenderableTextures.Length; i++) + { + var itex = geom.RenderableTextures[i]; + var ihash = geom.TextureParamHashes[i]; + if (ihash == RenderTextureSampler) + { + texture = itex; + break; + } + } + } + } + + + bool usediff = ((texture != null) && (texture.ShaderResourceView != null)); + bool usebump = ((bumptex != null) && (bumptex.ShaderResourceView != null)); + bool useflow = ((flowtex != null) && (flowtex.ShaderResourceView != null)); + bool usefoam = ((foamtex != null) && (foamtex.ShaderResourceView != null)); + bool usefog = ((fogtex != null) && (fogtex.ShaderResourceView != null)); + + uint shaderMode = 0; + var shaderFile = geom.DrawableGeom.Shader.FileName; + switch (shaderFile.Hash) + { + case 1529202445://{water_river.sps} + case 4064804434://{water_riverlod.sps} + case 2871265627://{water_riverocean.sps} + case 1507348828://{water_rivershallow.sps} + case 3945561843://{water_fountain.sps} + case 4234404348://{water_shallow.sps} + case 1077877097://{water_poolenv.sps} + break; + case 1471966282://{water_decal.sps} (should this be in decal batch?) + case 3053856997://{water_riverfoam.sps} + shaderMode = 1; + break; + case 3066724854://{water_terrainfoam.sps} + shaderMode = 2; + break; + default: + break; + } + + + PSGeomVars.Vars.EnableTexture = usediff ? 1u : 0u; + PSGeomVars.Vars.EnableBumpMap = usebump ? 1u : 0u; + PSGeomVars.Vars.EnableFoamMap = usefoam ? 1u : 0u; + PSGeomVars.Vars.ShaderMode = shaderMode; + PSGeomVars.Vars.SpecularIntensity = SpecularEnable ? 1.0f : 0.0f;// geom.specularIntensityMult; + PSGeomVars.Vars.SpecularFalloff = 1.0f;// geom.specularFalloffMult; + PSGeomVars.Vars.WaveOffset = geom.WaveOffset; //for terrainfoam + PSGeomVars.Vars.WaterHeight = geom.WaterHeight; //for terrainfoam + PSGeomVars.Vars.WaveMovement = geom.WaveMovement; //for terrainfoam + PSGeomVars.Vars.HeightOpacity = geom.HeightOpacity; //for terrainfoam + PSGeomVars.Vars.RippleSpeed = geom.RippleSpeed; + PSGeomVars.Vars.RippleScale = geom.RippleScale; + PSGeomVars.Vars.RippleBumpiness = geom.RippleBumpiness; + PSGeomVars.Update(context); + PSGeomVars.SetPSCBuffer(context, 2); + + VSGeomVars.Vars.EnableFlow = useflow ? 1u : 0u; + VSGeomVars.Vars.ShaderMode = shaderMode; + VSGeomVars.Vars.WaterParams = Vector4.Zero; + VSGeomVars.Vars.RippleSpeed = geom.RippleSpeed; + VSGeomVars.Update(context); + VSGeomVars.SetVSCBuffer(context, 3); + + context.VertexShader.SetSampler(0, texsamplerflow); + context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler); + if (usediff) + { + texture.SetPSResource(context, 0); + } + if (usebump) + { + bumptex.SetPSResource(context, 2); + } + if (usefoam) + { + foamtex.SetPSResource(context, 3); + } + if (useflow) + { + flowtex.SetVSResource(context, 0); + } + } + + + public void RenderWaterQuad(DeviceContext context, RenderableWaterQuad quad) + { + SetInputLayout(context, VertexType.PCT); + + VSEntityVars.Vars.CamRel = new Vector4(quad.CamRel, 0.0f); + VSEntityVars.Vars.Orientation = Quaternion.Identity; + VSEntityVars.Vars.Scale = Vector3.One; + VSEntityVars.Update(context); + VSEntityVars.SetVSCBuffer(context, 2); + + + PSGeomVars.Vars.EnableTexture = 0; + PSGeomVars.Vars.EnableBumpMap = 0; + PSGeomVars.Vars.EnableFoamMap = 0; + PSGeomVars.Vars.ShaderMode = 0; //normal water render + PSGeomVars.Vars.SpecularIntensity = SpecularEnable ? 4.2f : 0.0f;// geom.specularIntensityMult; + PSGeomVars.Vars.SpecularFalloff = 1600.0f;// geom.specularFalloffMult; + PSGeomVars.Vars.WaveOffset = 0.0f;// geom.WaveOffset; //for terrainfoam + PSGeomVars.Vars.WaterHeight = 0.0f;// geom.WaterHeight; //for terrainfoam + PSGeomVars.Vars.WaveMovement = 0.0f;// geom.WaveMovement; //for terrainfoam + PSGeomVars.Vars.HeightOpacity = 0.0f;// geom.HeightOpacity; //for terrainfoam + PSGeomVars.Vars.RippleSpeed = 2.1f;// geom.RippleSpeed; + PSGeomVars.Vars.RippleScale = 0.02f;// geom.RippleScale; + PSGeomVars.Vars.RippleBumpiness = 4.5f;// geom.RippleBumpiness; + PSGeomVars.Update(context); + PSGeomVars.SetPSCBuffer(context, 2); + + VSGeomVars.Vars.EnableFlow = 0; //no flow for water quads... + VSGeomVars.Vars.ShaderMode = 0; //normal water + VSGeomVars.Vars.WaterParams = Vector4.Zero; + VSGeomVars.Vars.RippleSpeed = 1.0f;// geom.RippleSpeed; + VSGeomVars.Update(context); + VSGeomVars.SetVSCBuffer(context, 3); + + context.VertexShader.SetSampler(0, texsamplerflow); + context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler); + + quad.Render(context); + } + + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.PixelShader.SetConstantBuffer(0, null); + context.VertexShader.SetConstantBuffer(1, null); //shadowmap + context.PixelShader.SetConstantBuffer(1, null); //shadowmap + context.PixelShader.SetShaderResource(1, null);//shadowmap + context.PixelShader.SetSampler(1, null); //shadowmap + context.VertexShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(3, null); + context.PixelShader.SetConstantBuffer(2, null); + context.VertexShader.SetConstantBuffer(4, null); + context.VertexShader.SetConstantBuffer(5, null); + context.VertexShader.SetConstantBuffer(6, null); + context.VertexShader.SetSampler(0, null); + context.PixelShader.SetSampler(0, null); + context.PixelShader.SetShaderResource(0, null); + context.PixelShader.SetShaderResource(2, null); + context.PixelShader.SetShaderResource(3, null); + context.PixelShader.SetShaderResource(4, null); + context.PixelShader.SetShaderResource(5, null); + context.VertexShader.SetShaderResource(0, null); + context.VertexShader.SetShaderResource(1, null); + context.VertexShader.SetShaderResource(2, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + public void Dispose() + { + if (disposed) return; + + texsampler.Dispose(); + texsampleranis.Dispose(); + texsamplerflow.Dispose(); + + foreach (InputLayout layout in layouts.Values) + { + layout.Dispose(); + } + layouts.Clear(); + + VSSceneVars.Dispose(); + VSEntityVars.Dispose(); + VSGeomVars.Dispose(); + PSSceneVars.Dispose(); + PSGeomVars.Dispose(); + + ps.Dispose(); + vspt.Dispose(); + vspct.Dispose(); + vspnct.Dispose(); + vspnctx.Dispose(); + + disposed = true; + + } + } +} diff --git a/Rendering/Shaders/WidgetShader.cs b/Rendering/Shaders/WidgetShader.cs new file mode 100644 index 0000000..00a5852 --- /dev/null +++ b/Rendering/Shaders/WidgetShader.cs @@ -0,0 +1,617 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CodeWalker.GameFiles; +using CodeWalker.World; +using SharpDX.Direct3D11; +using SharpDX; +using System.IO; + +namespace CodeWalker.Rendering +{ + public struct WidgetShaderSceneVars + { + public Matrix ViewProj; + public uint Mode; //0=Vertices, 1=Arc + public float Size; //world units + public float SegScale; //arc angle / number of segments + public float SegOffset; //angle offset of arc + public Vector3 CamRel; //center position + public uint CullBack; //culls pixels behind 0,0,0 + public Color4 Colour; //colour for arc + public Vector3 Axis1; //axis 1 of arc + public float WidgetPad2; + public Vector3 Axis2; //axis 2 of arc + public float WidgetPad3; + } + + + public class WidgetShader : Shader + { + VertexShader vs; + PixelShader ps; + + GpuVarsBuffer SceneVars; + GpuCBuffer Vertices; + + + public WidgetShader(Device device) + { + byte[] vsbytes = File.ReadAllBytes("Shaders\\WidgetVS.cso"); + byte[] psbytes = File.ReadAllBytes("Shaders\\WidgetPS.cso"); + + vs = new VertexShader(device, vsbytes); + ps = new PixelShader(device, psbytes); + + SceneVars = new GpuVarsBuffer(device); + + Vertices = new GpuCBuffer(device, 150); //should be more than needed.... + + } + public void Dispose() + { + Vertices.Dispose(); + SceneVars.Dispose(); + ps.Dispose(); + vs.Dispose(); + } + + public override void SetShader(DeviceContext context) + { + context.VertexShader.Set(vs); + context.PixelShader.Set(ps); + } + + public override bool SetInputLayout(DeviceContext context, VertexType type) + { + context.InputAssembler.InputLayout = null; + context.InputAssembler.SetIndexBuffer(null, SharpDX.DXGI.Format.Unknown, 0); + return true; + } + public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) + { + SceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); + SceneVars.Update(context); + SceneVars.SetVSCBuffer(context, 0); + + } + public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) + { + } + public override void SetModelVars(DeviceContext context, RenderableModel model) + { + } + public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) + { + } + + public override void UnbindResources(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(0, null); + context.VertexShader.SetShaderResource(0, null); + context.VertexShader.Set(null); + context.PixelShader.Set(null); + } + + + public void DrawDefaultWidget(DeviceContext context, Camera cam, Vector3 camrel, Quaternion ori, float size) + { + SetShader(context); + SetInputLayout(context, VertexType.Default); + + SceneVars.Vars.Mode = 0; //vertices mode + SceneVars.Vars.CamRel = camrel; + SetSceneVars(context, cam, null, null); + + Vector3 xdir = ori.Multiply(Vector3.UnitX); + Vector3 ydir = ori.Multiply(Vector3.UnitY); + Vector3 zdir = ori.Multiply(Vector3.UnitZ); + Color4 xcolour = new Color4(0.8f, 0.0f, 0.0f, 1.0f); + Color4 ycolour = new Color4(0.8f, 0.0f, 0.0f, 1.0f); + Color4 zcolour = new Color4(0.5f, 0.5f, 0.5f, 1.0f); + + Vector3[] axes = { xdir, ydir, zdir }; + Vector3[] sides = { ydir, xdir, xdir }; + Color4[] colours = { xcolour, ycolour, zcolour }; + + float linestart = 0.0f * size; + float lineend = 1.0f * size; + float arrowstart = 0.9f * size; + float arrowend = 1.0f * size; + float arrowrad = 0.05f * size; + + //draw lines... + Vertices.Clear(); + + for (int i = 0; i < 3; i++) + { + WidgetAxis sa = (WidgetAxis)(1 << i); + Color4 axcol = colours[i]; + + //main axis lines + Vertices.Add(new WidgetShaderVertex(axes[i] * linestart, axcol)); + Vertices.Add(new WidgetShaderVertex(axes[i] * lineend, axcol)); + + //arrow heads + Vector3 astart = axes[i] * arrowstart; + Vector3 aend = axes[i] * arrowend; + Vector3 aside = sides[i] * arrowrad; + Vertices.Add(new WidgetShaderVertex(aend, axcol)); + Vertices.Add(new WidgetShaderVertex(astart + aside, axcol)); + Vertices.Add(new WidgetShaderVertex(aend, axcol)); + Vertices.Add(new WidgetShaderVertex(astart - aside, axcol)); + } + + Vertices.Update(context); + Vertices.SetVSResource(context, 0); + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList; + context.Draw(Vertices.CurrentCount, 0); + + UnbindResources(context); + } + + public void DrawPositionWidget(DeviceContext context, Camera cam, Vector3 camrel, Quaternion ori, float size, WidgetAxis selax) + { + SetShader(context); + SetInputLayout(context, VertexType.Default); + + SceneVars.Vars.Mode = 0; //vertices mode + SceneVars.Vars.CamRel = camrel; + SetSceneVars(context, cam, null, null); + + Vector3 xdir = ori.Multiply(Vector3.UnitX); + Vector3 ydir = ori.Multiply(Vector3.UnitY); + Vector3 zdir = ori.Multiply(Vector3.UnitZ); + Color4 xcolour = new Color4(1.0f, 0.0f, 0.0f, 1.0f); + Color4 ycolour = new Color4(0.0f, 1.0f, 0.0f, 1.0f); + Color4 zcolour = new Color4(0.0f, 0.0f, 1.0f, 1.0f); + Color4 selaxcol = new Color4(1.0f, 1.0f, 0.0f, 1.0f); + Color4 selplcol = new Color4(1.0f, 1.0f, 0.0f, 0.5f); + + Vector3[] axes = { xdir, ydir, zdir }; + Vector3[] sides1 = { ydir, zdir, xdir }; + Vector3[] sides2 = { zdir, xdir, ydir }; + WidgetAxis[] sideax1 = { WidgetAxis.Y, WidgetAxis.Z, WidgetAxis.X }; + WidgetAxis[] sideax2 = { WidgetAxis.Z, WidgetAxis.X, WidgetAxis.Y }; + Color4[] colours = { xcolour, ycolour, zcolour }; + Color4[] coloursdark = { xcolour * 0.5f, ycolour * 0.5f, zcolour * 0.5f }; + for (int i = 0; i < 3; i++) coloursdark[i].Alpha = 1.0f; + + float linestart = 0.2f * size; + float lineend = 1.0f * size; + float sideval = 0.4f * size; + float arrowstart = 1.0f * size; + float arrowend = 1.33f * size; + float arrowrad = 0.06f * size; + + float hexx = 0.5f; + float hexy = 0.86602540378443864676372317075294f; //sqrt(0.75) + Vector2[] arrowv = + { + new Vector2(-1, 0) * arrowrad, + new Vector2(-hexx, hexy) * arrowrad, + new Vector2(hexx, hexy) * arrowrad, + new Vector2(1, 0) * arrowrad, + new Vector2(hexx, -hexy) * arrowrad, + new Vector2(-hexx, -hexy) * arrowrad, + new Vector2(-1, 0) * arrowrad + }; + + + + + //draw lines... + Vertices.Clear(); + + for (int i = 0; i < 3; i++) + { + WidgetAxis sa = (WidgetAxis)(1 << i); + bool axsel = ((selax & sa) > 0); + Color4 axcol = axsel ? selaxcol : colours[i]; + + //axis side square lines + Vector3 ax = axes[i] * sideval; + Vector3 s1 = sides1[i] * sideval; + Vector3 s2 = sides2[i] * sideval; + Color4 sc1 = (axsel && ((selax & sideax1[i]) > 0)) ? selaxcol : colours[i]; + Color4 sc2 = (axsel && ((selax & sideax2[i]) > 0)) ? selaxcol : colours[i]; + Vertices.Add(new WidgetShaderVertex(ax, sc1)); + Vertices.Add(new WidgetShaderVertex(ax + s1, sc1)); + Vertices.Add(new WidgetShaderVertex(ax, sc2)); + Vertices.Add(new WidgetShaderVertex(ax + s2, sc2)); + + //main axis lines - draw after side lines to be on top + Vertices.Add(new WidgetShaderVertex(axes[i] * linestart, axcol)); + Vertices.Add(new WidgetShaderVertex(axes[i] * lineend, axcol)); + } + + Vertices.Update(context); + Vertices.SetVSResource(context, 0); + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList; + context.Draw(Vertices.CurrentCount, 0); + + + + //draw triangles... + Vertices.Clear(); + + for (int i = 0; i < 3; i++) + { + //axis arrows - kind of inefficient, but meh + Vector3 aend = axes[i] * arrowend; + Vector3 astart = axes[i] * arrowstart; + for (int n = 0; n < 6; n++) + { + Vector2 a1 = arrowv[n]; + Vector2 a2 = arrowv[n + 1]; + Vector3 ap1 = astart + sides1[i] * a1.Y + sides2[i] * a1.X; + Vector3 ap2 = astart + sides1[i] * a2.Y + sides2[i] * a2.X; + Vertices.Add(new WidgetShaderVertex(aend, colours[i])); + Vertices.Add(new WidgetShaderVertex(ap1, colours[i])); + Vertices.Add(new WidgetShaderVertex(ap2, colours[i])); + Vertices.Add(new WidgetShaderVertex(astart, coloursdark[i])); + Vertices.Add(new WidgetShaderVertex(ap2, coloursdark[i])); + Vertices.Add(new WidgetShaderVertex(ap1, coloursdark[i])); + } + + //selection planes + WidgetAxis sa = (WidgetAxis)(1 << i); + if (((selax & sa) > 0)) + { + Vector3 ax = axes[i] * sideval; + for (int n = i + 1; n < 3; n++) + { + WidgetAxis tsa = (WidgetAxis)(1 << n); + if (((selax & tsa) > 0)) + { + Vector3 tax = axes[n] * sideval; + Vertices.Add(new WidgetShaderVertex(Vector3.Zero, selplcol)); + Vertices.Add(new WidgetShaderVertex(ax, selplcol)); + Vertices.Add(new WidgetShaderVertex(tax, selplcol)); + Vertices.Add(new WidgetShaderVertex(tax + ax, selplcol)); + Vertices.Add(new WidgetShaderVertex(tax, selplcol)); + Vertices.Add(new WidgetShaderVertex(ax, selplcol)); + } + } + } + } + + Vertices.Update(context); + Vertices.SetVSResource(context, 0); + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList; + context.Draw(Vertices.CurrentCount, 0); + + UnbindResources(context); + } + + public void DrawRotationWidget(DeviceContext context, Camera cam, Vector3 camrel, Quaternion ori, float size, WidgetAxis selax, WidgetAxis drawax) + { + SetShader(context); + SetInputLayout(context, VertexType.Default); + + + SceneVars.Vars.Mode = 0; //vertices mode + SceneVars.Vars.CamRel = camrel; + SetSceneVars(context, cam, null, null); + + Vector3 xdir = ori.Multiply(Vector3.UnitX); + Vector3 ydir = ori.Multiply(Vector3.UnitY); + Vector3 zdir = ori.Multiply(Vector3.UnitZ); + Color4 xcolour = new Color4(1.0f, 0.0f, 0.0f, 1.0f); + Color4 ycolour = new Color4(0.0f, 1.0f, 0.0f, 1.0f); + Color4 zcolour = new Color4(0.0f, 0.0f, 1.0f, 1.0f); + Color4 icolour = new Color4(0.5f, 0.5f, 0.5f, 1.0f); + Color4 ocolour = new Color4(0.7f, 0.7f, 0.7f, 1.0f); + Color4 scolour = new Color4(1.0f, 1.0f, 0.0f, 1.0f); + + Vector3[] axes = { xdir, ydir, zdir }; + Vector3[] sides = { ydir, xdir, xdir }; + Color4[] colours = { xcolour, ycolour, zcolour }; + + float linestart = 0.0f * size; + float lineend = 0.3f * size; + float ocircsize = 1.0f * size; + float icircsize = 0.75f * size; + + //draw lines... + Vertices.Clear(); + + for (int i = 0; i < 3; i++) + { + WidgetAxis sa = (WidgetAxis)(1 << i); + bool axsel = ((selax & sa) > 0); + Color4 axcol = axsel ? colours[i] : icolour; + + //main axis lines + Vertices.Add(new WidgetShaderVertex(axes[i] * linestart, axcol)); + Vertices.Add(new WidgetShaderVertex(axes[i] * lineend, axcol)); + } + + Vertices.Update(context); + Vertices.SetVSResource(context, 0); + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList; + context.Draw(Vertices.CurrentCount, 0); + + + + //linestrip for arcs and circles + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineStrip; + + Vector3 sdir = Vector3.Normalize(camrel); + //if (cam.IsMapView || cam.IsOrthographic) + //{ + // sdir = cam.ViewDirection; + //} + float ad1 = Math.Abs(Vector3.Dot(sdir, Vector3.UnitY)); + float ad2 = Math.Abs(Vector3.Dot(sdir, Vector3.UnitZ)); + Vector3 ax1 = Vector3.Normalize(Vector3.Cross(sdir, (ad1 > ad2) ? Vector3.UnitY : Vector3.UnitZ)); + Vector3 ax2 = Vector3.Normalize(Vector3.Cross(sdir, ax1)); + + //drawing circles + int segcount = 40; + int vertcount = segcount + 1; + SceneVars.Vars.Mode = 1; //arc mode + SceneVars.Vars.SegScale = ((float)Math.PI) * 2.0f / segcount; //arc angle / number of segments + SceneVars.Vars.SegOffset = 0.0f; //angle offset of arc + SceneVars.Vars.Axis1 = ax1; //axis 1 of arc + SceneVars.Vars.Axis2 = ax2; //axis 2 of arc + SceneVars.Vars.CullBack = 0; //culls pixels behind 0,0,0 + + //outer circle + if (drawax == WidgetAxis.XYZ) + { + SceneVars.Vars.Size = ocircsize; //world units + SceneVars.Vars.Colour = (selax == WidgetAxis.XYZ) ? scolour : ocolour; //colour for arc + SetSceneVars(context, cam, null, null); + context.Draw(vertcount, 0); + } + + //inner circle + SceneVars.Vars.Size = icircsize; //world units + SceneVars.Vars.Colour = icolour; //colour for arc + SetSceneVars(context, cam, null, null); + context.Draw(vertcount, 0); + + + //drawing arcs - culling done in PS + SceneVars.Vars.Size = icircsize; //world units + SceneVars.Vars.CullBack = 1; //culls pixels behind 0,0,0 + + if ((drawax & WidgetAxis.X) != 0) + { + SceneVars.Vars.SegOffset = 0.0f; //angle offset of arc + SceneVars.Vars.Axis1 = ydir; //axis 1 of arc + SceneVars.Vars.Axis2 = zdir; //axis 2 of arc + SceneVars.Vars.Colour = (selax == WidgetAxis.X) ? scolour : xcolour; //colour for arc + SetSceneVars(context, cam, null, null); + context.Draw(vertcount, 0); + } + + if ((drawax & WidgetAxis.Y) != 0) + { + SceneVars.Vars.SegOffset = 0.0f; //angle offset of arc + SceneVars.Vars.Axis1 = xdir; //axis 1 of arc + SceneVars.Vars.Axis2 = zdir; //axis 2 of arc + SceneVars.Vars.Colour = (selax == WidgetAxis.Y) ? scolour : ycolour; //colour for arc + SetSceneVars(context, cam, null, null); + context.Draw(vertcount, 0); + } + + if ((drawax & WidgetAxis.Z) != 0) + { + SceneVars.Vars.SegOffset = 0.0f; //angle offset of arc + SceneVars.Vars.Axis1 = xdir; //axis 1 of arc + SceneVars.Vars.Axis2 = ydir; //axis 2 of arc + SceneVars.Vars.Colour = (selax == WidgetAxis.Z) ? scolour : zcolour; //colour for arc + SetSceneVars(context, cam, null, null); + context.Draw(vertcount, 0); + } + + + + + UnbindResources(context); + } + + public void DrawScaleWidget(DeviceContext context, Camera cam, Vector3 camrel, Quaternion ori, float size, WidgetAxis selax) + { + SetShader(context); + SetInputLayout(context, VertexType.Default); + + SceneVars.Vars.Mode = 0; //vertices mode + SceneVars.Vars.CamRel = camrel; + SetSceneVars(context, cam, null, null); + + Vector3 xdir = ori.Multiply(Vector3.UnitX); + Vector3 ydir = ori.Multiply(Vector3.UnitY); + Vector3 zdir = ori.Multiply(Vector3.UnitZ); + Color4 xcolour = new Color4(1.0f, 0.0f, 0.0f, 1.0f); + Color4 ycolour = new Color4(0.0f, 1.0f, 0.0f, 1.0f); + Color4 zcolour = new Color4(0.0f, 0.0f, 1.0f, 1.0f); + Color4 selaxcol = new Color4(1.0f, 1.0f, 0.0f, 1.0f); + Color4 selplcol = new Color4(1.0f, 1.0f, 0.0f, 0.5f); + + Vector3[] axes = { xdir, ydir, zdir }; + Vector3[] sides1 = { ydir, zdir, xdir }; + Vector3[] sides2 = { zdir, xdir, ydir }; + WidgetAxis[] sideax1 = { WidgetAxis.Y, WidgetAxis.Z, WidgetAxis.X }; + WidgetAxis[] sideax2 = { WidgetAxis.Z, WidgetAxis.X, WidgetAxis.Y }; + Color4[] colours = { xcolour, ycolour, zcolour }; + Color4[] coloursn = { ycolour, zcolour, xcolour }; + Color4[] coloursdark = { xcolour * 0.5f, ycolour * 0.5f, zcolour * 0.5f }; + for (int i = 0; i < 3; i++) coloursdark[i].Alpha = 1.0f; + + float linestart = 0.0f * size; + float lineend = 1.33f * size; + float innertri = 0.7f * size; + float outertri = 1.0f * size; + float cubestart = 1.28f * size; + float cubeend = 1.33f * size; + float cubesize = 0.025f * size; + + //draw lines... + Vertices.Clear(); + + for (int i = 0; i < 3; i++) + { + WidgetAxis sa = (WidgetAxis)(1 << i); + bool axsel = ((selax & sa) > 0); + Color4 axcol = axsel ? selaxcol : colours[i]; + + WidgetAxis triaxn = sideax1[i]; + bool trisel = axsel && ((selax & triaxn) > 0); + Color4 tricol = trisel ? selaxcol : colours[i]; + Color4 trincol = trisel ? selaxcol : coloursn[i]; + + Vector3 inner1 = axes[i] * innertri; + Vector3 inner2 = sides1[i] * innertri; + Vector3 innera = (inner1 + inner2) * 0.5f; + Vector3 outer1 = axes[i] * outertri; + Vector3 outer2 = sides1[i] * outertri; + Vector3 outera = (outer1 + outer2) * 0.5f; + + //triangle axis lines + Vertices.Add(new WidgetShaderVertex(inner1, tricol)); + Vertices.Add(new WidgetShaderVertex(innera, tricol)); + Vertices.Add(new WidgetShaderVertex(innera, trincol)); + Vertices.Add(new WidgetShaderVertex(inner2, trincol)); + Vertices.Add(new WidgetShaderVertex(outer1, tricol)); + Vertices.Add(new WidgetShaderVertex(outera, tricol)); + Vertices.Add(new WidgetShaderVertex(outera, trincol)); + Vertices.Add(new WidgetShaderVertex(outer2, trincol)); + + //main axis lines - draw after side lines to be on top + Vertices.Add(new WidgetShaderVertex(axes[i] * linestart, axcol)); + Vertices.Add(new WidgetShaderVertex(axes[i] * lineend, axcol)); + } + + Vertices.Update(context); + Vertices.SetVSResource(context, 0); + + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList; + context.Draw(Vertices.CurrentCount, 0); + + + + + + //draw triangles... + Vertices.Clear(); + + for (int i = 0; i < 3; i++) + { + //axis end cubes - kind of inefficient, but meh + Vector3 cend = axes[i] * cubeend; + Vector3 cstart = axes[i] * cubestart; + Vector3 cside1 = sides1[i] * cubesize; + Vector3 cside2 = sides2[i] * cubesize; + Vector3 cv1 = cstart + cside1 - cside2; + Vector3 cv2 = cstart - cside1 - cside2; + Vector3 cv3 = cend + cside1 - cside2; + Vector3 cv4 = cend - cside1 - cside2; + Vector3 cv5 = cstart + cside1 + cside2; + Vector3 cv6 = cstart - cside1 + cside2; + Vector3 cv7 = cend + cside1 + cside2; + Vector3 cv8 = cend - cside1 + cside2; + Color4 col = colours[i]; + Color4 cold = coloursdark[i]; + Vertices.Add(new WidgetShaderVertex(cv1, cold)); + Vertices.Add(new WidgetShaderVertex(cv2, cold)); + Vertices.Add(new WidgetShaderVertex(cv5, cold)); + Vertices.Add(new WidgetShaderVertex(cv5, cold)); + Vertices.Add(new WidgetShaderVertex(cv2, cold)); + Vertices.Add(new WidgetShaderVertex(cv6, cold)); + Vertices.Add(new WidgetShaderVertex(cv3, col)); + Vertices.Add(new WidgetShaderVertex(cv4, col)); + Vertices.Add(new WidgetShaderVertex(cv7, col)); + Vertices.Add(new WidgetShaderVertex(cv7, col)); + Vertices.Add(new WidgetShaderVertex(cv4, col)); + Vertices.Add(new WidgetShaderVertex(cv8, col)); + Vertices.Add(new WidgetShaderVertex(cv1, col)); + Vertices.Add(new WidgetShaderVertex(cv2, col)); + Vertices.Add(new WidgetShaderVertex(cv3, col)); + Vertices.Add(new WidgetShaderVertex(cv3, col)); + Vertices.Add(new WidgetShaderVertex(cv2, col)); + Vertices.Add(new WidgetShaderVertex(cv4, col)); + Vertices.Add(new WidgetShaderVertex(cv5, col)); + Vertices.Add(new WidgetShaderVertex(cv6, col)); + Vertices.Add(new WidgetShaderVertex(cv7, col)); + Vertices.Add(new WidgetShaderVertex(cv7, col)); + Vertices.Add(new WidgetShaderVertex(cv6, col)); + Vertices.Add(new WidgetShaderVertex(cv8, col)); + Vertices.Add(new WidgetShaderVertex(cv1, col)); + Vertices.Add(new WidgetShaderVertex(cv5, col)); + Vertices.Add(new WidgetShaderVertex(cv3, col)); + Vertices.Add(new WidgetShaderVertex(cv3, col)); + Vertices.Add(new WidgetShaderVertex(cv5, col)); + Vertices.Add(new WidgetShaderVertex(cv7, col)); + Vertices.Add(new WidgetShaderVertex(cv2, col)); + Vertices.Add(new WidgetShaderVertex(cv6, col)); + Vertices.Add(new WidgetShaderVertex(cv4, col)); + Vertices.Add(new WidgetShaderVertex(cv4, col)); + Vertices.Add(new WidgetShaderVertex(cv6, col)); + Vertices.Add(new WidgetShaderVertex(cv8, col)); + + + //selection triangles + if (selax == WidgetAxis.XYZ) + { + //all axes - just draw inner triangle + Vertices.Add(new WidgetShaderVertex(Vector3.Zero, selplcol)); + Vertices.Add(new WidgetShaderVertex(axes[i] * innertri, selplcol)); + Vertices.Add(new WidgetShaderVertex(sides1[i] * innertri, selplcol)); + } + else + { + WidgetAxis sa = (WidgetAxis)(1 << i); + WidgetAxis na = sideax1[i]; + if (((selax & sa) > 0) && ((selax & na) > 0)) + { + Vertices.Add(new WidgetShaderVertex(axes[i] * innertri, selplcol)); + Vertices.Add(new WidgetShaderVertex(sides1[i] * innertri, selplcol)); + Vertices.Add(new WidgetShaderVertex(axes[i] * outertri, selplcol)); + Vertices.Add(new WidgetShaderVertex(axes[i] * outertri, selplcol)); + Vertices.Add(new WidgetShaderVertex(sides1[i] * innertri, selplcol)); + Vertices.Add(new WidgetShaderVertex(sides1[i] * outertri, selplcol)); + } + } + } + + Vertices.Update(context); + Vertices.SetVSResource(context, 0); + + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList; + context.Draw(Vertices.CurrentCount, 0); + + + + + + UnbindResources(context); + } + + } + + + public struct WidgetShaderVertex + { + public Vector4 Position; + public Color4 Colour; + + public WidgetShaderVertex(Vector3 p, Color4 c) + { + Position = new Vector4(p, 0.0f); + Colour = c; + } + } + + + +} diff --git a/Rendering/Utils/GpuBuffers.cs b/Rendering/Utils/GpuBuffers.cs new file mode 100644 index 0000000..a900145 --- /dev/null +++ b/Rendering/Utils/GpuBuffers.cs @@ -0,0 +1,372 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX.DXGI; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using SharpDX.Direct3D11; +using SharpDX; +using SharpDX.Direct3D; + +namespace CodeWalker.Rendering +{ + public class GpuVarsBuffer where T:struct //shader vars buffer helper! + { + public int Size; + public Buffer Buffer; + public T Vars; + public bool Flag;//for external use + public GpuVarsBuffer(Device device) + { + Size = System.Runtime.InteropServices.Marshal.SizeOf();// (sizeof(T)); + Buffer = new Buffer(device, Size, ResourceUsage.Dynamic, BindFlags.ConstantBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0);// //DXUtility::CreateShaderVarsBuffer(Size, name); + } + public void Dispose() + { + if (Buffer != null) + { + Buffer.Dispose(); + Buffer = null; + } + } + public void Update(DeviceContext context) + { + var dataBox = context.MapSubresource(Buffer, 0, MapMode.WriteDiscard, MapFlags.None); + Utilities.Write(dataBox.DataPointer, ref Vars); + context.UnmapSubresource(Buffer, 0); + } + public void SetVSCBuffer(DeviceContext context, int slot) + { + context.VertexShader.SetConstantBuffer(slot, Buffer); + } + public void SetPSCBuffer(DeviceContext context, int slot) + { + context.PixelShader.SetConstantBuffer(slot, Buffer); + } + } + + public class GpuSBuffer where T : struct //for static struct data as resource view + { + public int StructSize; + public int StructCount; + public int BufferSize; + public Buffer Buffer; + public ShaderResourceView SRV; + public GpuSBuffer(Device device, T[] data) + { + StructCount = data.Length; + StructSize = System.Runtime.InteropServices.Marshal.SizeOf();// (sizeof(T)); + BufferSize = StructCount * StructSize; + //var ds = new DataStream(new DataPointer() + Buffer = Buffer.Create(device, BindFlags.ShaderResource, data, BufferSize, ResourceUsage.Default, CpuAccessFlags.None, ResourceOptionFlags.BufferStructured, StructSize); + //Buffer = new Buffer(device, BufferSize, ResourceUsage.Default, BindFlags.ShaderResource, CpuAccessFlags.None, ResourceOptionFlags.BufferStructured, StructSize); + SRV = DXUtility.CreateShaderResourceView(device, Buffer, SharpDX.DXGI.Format.Unknown, SharpDX.Direct3D.ShaderResourceViewDimension.Buffer, 0, 0, StructCount, 0); + } + public void Dispose() + { + if (SRV != null) + { + SRV.Dispose(); + SRV = null; + } + if (Buffer != null) + { + Buffer.Dispose(); + Buffer = null; + } + } + } + + + public class GpuCBuffer where T : struct //Dynamic GPU buffer of items updated by CPU + { + public int StructSize; + public int StructCount; + public int BufferSize; + public int CurrentCount; + public Buffer Buffer; + public ShaderResourceView SRV; + public List Data; + public T[] DataArray; + + public GpuCBuffer(Device device, int count) + { + StructCount = count; + StructSize = System.Runtime.InteropServices.Marshal.SizeOf();// (sizeof(T)); + BufferSize = StructCount * StructSize; + //Buffer = Buffer.Create(device, BindFlags.ShaderResource, null, BufferSize, ResourceUsage.Dynamic, CpuAccessFlags.Write, ResourceOptionFlags.BufferStructured, StructSize); + Buffer = new Buffer(device, BufferSize, ResourceUsage.Dynamic, BindFlags.ShaderResource, CpuAccessFlags.Write, ResourceOptionFlags.BufferStructured, StructSize); + SRV = DXUtility.CreateShaderResourceView(device, Buffer, SharpDX.DXGI.Format.Unknown, SharpDX.Direct3D.ShaderResourceViewDimension.Buffer, 0, 0, StructCount, 0); + Data = new List(count); + DataArray = new T[count]; + } + public void Dispose() + { + if (SRV != null) + { + SRV.Dispose(); + SRV = null; + } + if (Buffer != null) + { + Buffer.Dispose(); + Buffer = null; + } + } + + public void Clear() + { + Data.Clear(); + CurrentCount = 0; + } + public bool Add(T item) + { + if (CurrentCount < StructCount) + { + Data.Add(item); + CurrentCount++; + return true; + } + return false; + } + + public void Update(DeviceContext context) + { + for (int i = 0; i < CurrentCount; i++) + { + DataArray[i] = Data[i]; + } + var dataBox = context.MapSubresource(Buffer, 0, MapMode.WriteDiscard, MapFlags.None); + Utilities.Write(dataBox.DataPointer, DataArray, 0, CurrentCount); + context.UnmapSubresource(Buffer, 0); + } + + public void SetVSResource(DeviceContext context, int slot) + { + context.VertexShader.SetShaderResource(slot, SRV); + } + public void SetPSResource(DeviceContext context, int slot) + { + context.PixelShader.SetShaderResource(slot, SRV); + } + + } + + + public class GpuBuffer where T : struct //Dynamic GPU buffer of items updated by compute shader + { + public int StructSize; + public int StructCount; + public int ItemTotalSize; + public int ItemCount; + public int Size; + public Buffer Buffer; + public ShaderResourceView SRV; + public UnorderedAccessView UAV; + + public GpuBuffer(Device device, int itemSize, int itemCount) + { + StructSize = System.Runtime.InteropServices.Marshal.SizeOf();// sizeof(T)), + StructCount = itemCount * itemSize; + ItemTotalSize = itemSize * StructSize; + ItemCount = itemCount; + Size = StructSize * itemSize * itemCount; + Buffer = DXUtility.CreateBuffer(device, Size, ResourceUsage.Default, BindFlags.ShaderResource | BindFlags.UnorderedAccess, 0, ResourceOptionFlags.BufferStructured, StructSize); + SRV = DXUtility.CreateShaderResourceView(device, Buffer, Format.Unknown, ShaderResourceViewDimension.Buffer, 0, 0, StructCount, 0); + UAV = DXUtility.CreateUnorderedAccessView(device, Buffer, Format.Unknown, UnorderedAccessViewDimension.Buffer, 0, StructCount, 0, 0); + } + public void Dispose() + { + if (UAV != null) + { + UAV.Dispose(); + UAV = null; + } + if (SRV != null) + { + SRV.Dispose(); + SRV = null; + } + if (Buffer != null) + { + Buffer.Dispose(); + Buffer = null; + } + } + } + + + public class GpuTexture //texture and render targets (depth, MS). + { + public Texture2D Texture; + public Texture2D TextureMS; + public Texture2D Depth; + public Texture2D DepthMS; + public RenderTargetView RTV; + public DepthStencilView DSV; + public RenderTargetView MSRTV; + public DepthStencilView MSDSV; + public ShaderResourceView SRV; + public int VramUsage; + public bool Multisampled; + public bool UseDepth; + + public void Init(Device device, int w, int h, Format f, int sc, int sq, bool depth, Format df) + { + VramUsage = 0; + Multisampled = (sc > 1); + UseDepth = depth; + ResourceUsage u = ResourceUsage.Default; + BindFlags b = BindFlags.RenderTarget | BindFlags.ShaderResource; + RenderTargetViewDimension rtvd = RenderTargetViewDimension.Texture2D; + ShaderResourceViewDimension srvd = ShaderResourceViewDimension.Texture2D;// D3D11_SRV_DIMENSION_TEXTURE2D; + int fs = DXUtility.ElementSize(f); + int wh = w * h; + BindFlags db = BindFlags.DepthStencil;// D3D11_BIND_DEPTH_STENCIL; + DepthStencilViewDimension dsvd = DepthStencilViewDimension.Texture2D; + + Texture = DXUtility.CreateTexture2D(device, w, h, 1, 1, f, 1, 0, u, b, 0, 0); + RTV = DXUtility.CreateRenderTargetView(device, Texture, f, rtvd, 0, 0, 0); + SRV = DXUtility.CreateShaderResourceView(device, Texture, f, srvd, 1, 0, 0, 0); + VramUsage += (wh * fs); + + if (Multisampled) + { + b = BindFlags.RenderTarget; + rtvd = RenderTargetViewDimension.Texture2DMultisampled; + dsvd = DepthStencilViewDimension.Texture2DMultisampled; + + TextureMS = DXUtility.CreateTexture2D(device, w, h, 1, 1, f, sc, sq, u, b, 0, 0); + MSRTV = DXUtility.CreateRenderTargetView(device, TextureMS, f, rtvd, 0, 0, 0); + VramUsage += (wh * fs); + + if (depth) + { + DepthMS = DXUtility.CreateTexture2D(device, w, h, 1, 1, df, sc, sq, u, db, 0, 0); + MSDSV = DXUtility.CreateDepthStencilView(device, DepthMS, df, dsvd); + VramUsage += (wh * DXUtility.ElementSize(df)); + } + } + else + { + if (depth) + { + Depth = DXUtility.CreateTexture2D(device, w, h, 1, 1, df, sc, sq, u, db, 0, 0); + DSV = DXUtility.CreateDepthStencilView(device, Depth, df, dsvd); + VramUsage += (wh * DXUtility.ElementSize(df)); + } + } + } + public void Dispose() + { + if (SRV != null) + { + SRV.Dispose(); + SRV = null; + } + if (MSDSV != null) + { + MSDSV.Dispose(); + MSDSV = null; + } + if (MSRTV != null) + { + MSRTV.Dispose(); + MSRTV = null; + } + if (DSV != null) + { + DSV.Dispose(); + DSV = null; + } + if (RTV != null) + { + RTV.Dispose(); + RTV = null; + } + if (DepthMS != null) + { + DepthMS.Dispose(); + DepthMS = null; + } + if (Depth != null) + { + Depth.Dispose(); + Depth = null; + } + if (TextureMS != null) + { + TextureMS.Dispose(); + TextureMS = null; + } + if (Texture != null) + { + Texture.Dispose(); + Texture = null; + } + } + public GpuTexture(Device device, int w, int h, Format f, int sc, int sq, bool depth, Format df) + { + Init(device, w, h, f, sc, sq, depth, df); + } + public GpuTexture(Device device, int w, int h, Format f, int sc, int sq) + { + Init(device, w, h, f, sc, sq, false, Format.Unknown); + } + public GpuTexture(Device device, int w, int h, Format f) + { + Init(device, w, h, f, 1, 0, false, Format.Unknown); + } + + public void Clear(DeviceContext context, Color4 colour) + { + if (Multisampled) + { + context.ClearRenderTargetView(MSRTV, colour); + if (UseDepth) + { + context.ClearDepthStencilView(MSDSV, DepthStencilClearFlags.Depth, 1.0f, 0); + } + } + else + { + context.ClearRenderTargetView(RTV, colour); + if (UseDepth) + { + context.ClearDepthStencilView(DSV, DepthStencilClearFlags.Depth, 1.0f, 0); + } + } + } + + public void ClearDepth(DeviceContext context) + { + if (!UseDepth) return; + if (Multisampled) + { + context.ClearDepthStencilView(MSDSV, DepthStencilClearFlags.Depth, 1.0f, 0); + } + else + { + context.ClearDepthStencilView(DSV, DepthStencilClearFlags.Depth, 1.0f, 0); + } + } + + public void SetRenderTarget(DeviceContext context) + { + if (Multisampled) + { + context.OutputMerger.SetRenderTargets(UseDepth ? MSDSV : null, MSRTV); + } + else + { + context.OutputMerger.SetRenderTargets(UseDepth ? DSV : null, RTV); + } + } + + } + + +} diff --git a/Rendering/Utils/RenderTargetSwitch.cs b/Rendering/Utils/RenderTargetSwitch.cs new file mode 100644 index 0000000..6182f2a --- /dev/null +++ b/Rendering/Utils/RenderTargetSwitch.cs @@ -0,0 +1,86 @@ +using SharpDX; +using SharpDX.Direct3D11; +using SharpDX.Mathematics.Interop; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.Rendering +{ + public class RenderTargetSwitch + { + + RenderTargetView[] OrigRenderTargetViewArr; + DepthStencilView OrigDepthStencilView; + RasterizerState OrigRasterizerState; + RawViewportF[] OrigViewports; + bool IsReset = true; + //bool ResetOnDestroy = false; + int RenderTargetCount = 1; + + + public void Dispose() + { + if (OrigRenderTargetViewArr != null) + { + for (int i = 0; i < RenderTargetCount; i++) + { + if (OrigRenderTargetViewArr[i] != null) + { + OrigRenderTargetViewArr[i].Dispose(); + } + } + OrigRenderTargetViewArr = null; + } + if (OrigDepthStencilView != null) + { + OrigDepthStencilView.Dispose(); + OrigDepthStencilView = null; + } + if (OrigRasterizerState != null) + { + OrigRasterizerState.Dispose(); + OrigRasterizerState = null; + } + } + + public void Set(DeviceContext context) + { + Dispose(); + + OrigRenderTargetViewArr = context.OutputMerger.GetRenderTargets(RenderTargetCount, out OrigDepthStencilView); + OrigViewports = context.Rasterizer.GetViewports(); + OrigRasterizerState = context.Rasterizer.State; + + //OrigRenderTargetViewArr = new RenderTargetView[RenderTargetCount]; + //uint origNumViewports = 1; + //dc->OMGetRenderTargets(RenderTargetCount, OrigRenderTargetViewArr, &OrigDepthStencilView); + //dc->RSGetViewports(&origNumViewports, &OrigViewport); + //dc->RSGetState(&OrigRasterizerState); + + IsReset = false; + } + public void Reset(DeviceContext context) + { + if (IsReset) return; + + context.OutputMerger.SetRenderTargets(OrigDepthStencilView, OrigRenderTargetViewArr); + context.Rasterizer.State = OrigRasterizerState; + context.Rasterizer.SetViewports(OrigViewports); + + //auto dc = DXManager::GetDeviceContext(); + //dc->OMSetRenderTargets(RenderTargetCount, OrigRenderTargetViewArr, OrigDepthStencilView); + //dc->RSSetState(OrigRasterizerState); + //dc->RSSetViewports(1, &OrigViewport); + + IsReset = true; + + Dispose(); + } + + + + }; +} diff --git a/Rendering/Utils/Shadowmap.cs b/Rendering/Utils/Shadowmap.cs new file mode 100644 index 0000000..ecd0c2a --- /dev/null +++ b/Rendering/Utils/Shadowmap.cs @@ -0,0 +1,1061 @@ +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using Resource = SharpDX.Direct3D11.Resource; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using CodeWalker.World; +using CodeWalker.Properties; + +namespace CodeWalker.Rendering +{ + public class Shadowmap + { + Texture2D DepthTexture; + SamplerState DepthTextureSS; + ShaderResourceView DepthTextureSRV; + DepthStencilView DepthTextureDSV; + RasterizerState DepthRenderRS; + DepthStencilState DepthRenderDS; + ViewportF DepthRenderVP; + GpuVarsBuffer ShadowVars; + RenderTargetSwitch RTS = new RenderTargetSwitch(); + public List Cascades; + Matrix SceneCamView; + Matrix LightView; + //Matrix LightViewInv; + Vector3 LightDirection; + int TextureSize; + public int CascadeCount; + //public const int MaxCascades = 6; + int PCFSize; + float PCFOffset; + float BlurBetweenCascades; + Vector3 WorldMin; + Vector3 WorldMax; + public Vector3 SceneOrigin; + Vector3 SceneCamPos; + Vector3 SceneMin; + Vector3 SceneMax; + Vector3 SceneCenter; + Vector3 SceneExtent; + + long graphicsMemoryUsage = 0; + public long VramUsage + { + get + { + return graphicsMemoryUsage; + } + } + + public Shadowmap(Device device) + { + TextureSize = 1024; //todo: make this a setting... + CascadeCount = Math.Min(Settings.Default.ShadowCascades, 8);// 6; //use setting + PCFSize = 3; + PCFOffset = 0.000125f; //0.002f + BlurBetweenCascades = 0.05f; + + ShadowVars = new GpuVarsBuffer(device); + + + + + //DepthTexture = DXUtility.CreateTexture2D(device, TextureSize, TextureSize, 1, 16, Format.R32_Typeless, 1, 0, ResourceUsage.Default, BindFlags.DepthStencil | BindFlags.ShaderResource, 0, 0); + //DepthTextureSS = DXUtility.CreateSamplerState(device, TextureAddressMode.Border, new Color4(1.0f), Comparison.Always, Filter.MinMagMipLinear, 0, 0.0f, 0.0f, 0.0f); + //DepthTextureSRV = DXUtility.CreateShaderResourceView(device, DepthTexture, Format.R32_Float, ShaderResourceViewDimension.Texture2DArray, 1, 0, 16, 0); + + DepthTexture = DXUtility.CreateTexture2D(device, TextureSize* CascadeCount, TextureSize, 1, 1, Format.R32_Typeless, 1, 0, ResourceUsage.Default, BindFlags.DepthStencil | BindFlags.ShaderResource, 0, 0); + DepthTextureSS = DXUtility.CreateSamplerState(device, TextureAddressMode.Border, new Color4(0.0f), Comparison.Less, Filter.ComparisonMinMagLinearMipPoint, 0, 0.0f, 0.0f, 0.0f); + DepthTextureSRV = DXUtility.CreateShaderResourceView(device, DepthTexture, Format.R32_Float, ShaderResourceViewDimension.Texture2D, 1, 0, 0, 0); + DepthTextureDSV = DXUtility.CreateDepthStencilView(device, DepthTexture, Format.D32_Float, DepthStencilViewDimension.Texture2D); + + Cascades = new List(CascadeCount); + for (int i = 0; i < CascadeCount; i++) + { + ShadowmapCascade c = new ShadowmapCascade(); + c.Owner = this; + c.Index = i; + c.ZNear = 0.0f; + c.ZFar = 1.0f; + c.IntervalNear = 0.0f; + c.IntervalFar = 1.0f; + //c.DepthTextureDSV = DXUtility.CreateDepthStencilView(device, DepthTexture, Format.D32_Float, i); + c.DepthRenderVP = new ViewportF() + { + Height = (float)TextureSize, + Width = (float)TextureSize, + MaxDepth = 1.0f, + MinDepth = 0.0f, + X = (float)(TextureSize * i), + Y = 0, + }; + Cascades.Add(c); + } + + DepthRenderRS = DXUtility.CreateRasterizerState(device, FillMode.Solid, CullMode.None, true, false, true, 0, 0.0f, 1.0f); + DepthRenderDS = DXUtility.CreateDepthStencilState(device, true, DepthWriteMask.All); + + DepthRenderVP = new ViewportF(); + DepthRenderVP.Height = (float)TextureSize; + DepthRenderVP.Width = (float)TextureSize; + DepthRenderVP.MaxDepth = 1.0f; + DepthRenderVP.MinDepth = 0.0f; + DepthRenderVP.X = 0; + DepthRenderVP.Y = 0; + + graphicsMemoryUsage = (long)(TextureSize * TextureSize * CascadeCount * 4); + } + public void Dispose() + { + graphicsMemoryUsage = 0; + if (DepthTexture != null) + { + DepthTexture.Dispose(); + DepthTexture = null; + } + if (DepthTextureSS != null) + { + DepthTextureSS.Dispose(); + DepthTextureSS = null; + } + if (DepthTextureSRV != null) + { + DepthTextureSRV.Dispose(); + DepthTextureSRV = null; + } + if (DepthTextureDSV != null) + { + DepthTextureDSV.Dispose(); + DepthTextureDSV = null; + } + if (DepthRenderRS != null) + { + DepthRenderRS.Dispose(); + DepthRenderRS = null; + } + if (DepthRenderDS != null) + { + DepthRenderDS.Dispose(); + DepthRenderDS = null; + } + if (ShadowVars != null) + { + ShadowVars.Dispose(); + ShadowVars = null; + } + if (Cascades != null) + { + //foreach (var cascade in Cascades) + //{ + // if (cascade.DepthTextureDSV != null) + // { + // cascade.DepthTextureDSV.Dispose(); + // cascade.DepthTextureDSV = null; + // } + //} + Cascades.Clear(); + Cascades = null; + } + } + + + public void BeginUpdate(DeviceContext context, Camera cam, Vector3 lightDir, List items) + { + //items should be potential shadow casters. + + RTS.Set(context); + + var ppos = cam.Position;// p.GetCurrentPosition(); + var view = cam.ViewMatrix;// p.GetCurrentView(); + var proj = cam.ProjMatrix;// p.GetCurrentProj(); + var viewproj = cam.ViewProjMatrix;// p.GetCurrentViewProj(); + + + //need to compute a local scene space for the shadows. use a snapped version of the camera coords... + Vector3 pp = ppos; + float snapsize = 20.0f;// 1000000; //20m in planet space... //ideally should snap to texel size + SceneOrigin.X = pp.X - (pp.X % snapsize); + SceneOrigin.Y = pp.Y - (pp.Y % snapsize); + SceneOrigin.Z = pp.Z - (pp.Z % snapsize); + SceneCamPos = (pp - SceneOrigin);//.ToV3F();// *0.0001f; + + + //the items passed in here are visible items. need to compute the scene bounds from these. + Vector4 vFLTMAX = new Vector4(float.MaxValue);// FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX ); + Vector4 vFLTMIN = new Vector4(float.MinValue);// -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX ); + Vector3 vHMAX = new Vector3(float.MaxValue);// V3H(9223372036854775807); + Vector3 vHMIN = new Vector3(float.MinValue);// V3H(-((huge)9223372036854775807)); + WorldMin = vHMAX; + WorldMax = vHMIN; + foreach (var item in items) + { + Vector3 icamrel = item.Inst.CamRel;// item->Seed.Position.RelativeTo(ppos).ToV3F(); + float idist = icamrel.Length();// V3FLength(icamrel); + float irad = item.Inst.Renderable.Key.BoundingSphereRadius;// ((huge)item->Radius + 1); //+1 to account for rounding down + if ((idist-irad) > 3000.0f) continue; //3km limit + + Vector3 imin = item.Inst.BBMin - 100.0f; //extra bias to make sure scene isn't too small in model view... + Vector3 imax = item.Inst.BBMax + 100.0f; + //Vector3 ipos = item.Inst.Position;// item->Seed.Position; + //Vector3 imin = ipos - irad; + //Vector3 imax = ipos + irad; + + WorldMin = Vector3.Min(WorldMin, imin); + WorldMax = Vector3.Max(WorldMax, imax); + } + SceneMin = (WorldMin - SceneOrigin);// *0.0001f; + SceneMax = (WorldMax - SceneOrigin);// *0.0001f; + SceneCenter = (SceneMax + SceneMin) * 0.5f; + SceneExtent = (SceneMax - SceneMin) * 0.5f; + + //M16F camViewInv = M16FInverse(camView); + Matrix sceneCamTrans = Matrix.Translation(-SceneCamPos); + SceneCamView = Matrix.Multiply(sceneCamTrans, view); + Matrix camViewInv = Matrix.Invert(SceneCamView); + + Vector3 lightUp = new Vector3(0.0f, 1.0f, 0.0f); //BUG: should select this depending on light dir!? + LightView = Matrix.LookAtLH(lightDir, Vector3.Zero, lightUp); //BUG?: pos/lightdir wrong way around?? + //LightView = Matrix.LookAtLH(Vector3.Zero, -lightDir, lightUp); //BUG?: pos/lightdir wrong way around?? + LightDirection = lightDir; + + Vector4[] vSceneAABBPointsLightSpace = new Vector4[8]; + // This function simply converts the center and extents of an AABB into 8 points + CreateAABBPoints(ref vSceneAABBPointsLightSpace, SceneCenter, SceneExtent); + // Transform the scene AABB to Light space. + for (int index = 0; index < 8; ++index) + { + //vSceneAABBPointsLightSpace[index] = XMVector4Transform(vSceneAABBPointsLightSpace[index], matLightCameraView); + vSceneAABBPointsLightSpace[index] = LightView.Multiply(vSceneAABBPointsLightSpace[index]); + } + + + float fFrustumIntervalBegin, fFrustumIntervalEnd; + Vector4 vLightCameraOrthographicMin; // light space frustrum aabb + Vector4 vLightCameraOrthographicMax; + float fCameraNearFarRange = 1000.0f; //(far - near) //1000m in planet space + float[] fCascadeIntervals = { 0.0075f, 0.02f, 0.06f, 0.15f, 0.5f, 1.0f, 1.5f, 2.5f }; + //CascadeCount = 6; + //float fCascadeIntervals[] = { 0.005f, 0.015f, 0.03f, 0.06f, 0.12f, 0.25f, 0.6f, 1.0f }; + //CascadeCount = 8; + + Vector4 vWorldUnitsPerTexel = Vector4.Zero; + float fInvTexelCount = 1.0f / (float)TextureSize; + + // We loop over the cascades to calculate the orthographic projection for each cascade. + for (int iCascadeIndex = 0; iCascadeIndex < CascadeCount; ++iCascadeIndex) + { + ShadowmapCascade cascade = Cascades[iCascadeIndex]; + + fFrustumIntervalBegin = 0.0f; + // Scale the intervals between 0 and 1. They are now percentages that we can scale with. + fFrustumIntervalEnd = fCascadeIntervals[iCascadeIndex]; + fFrustumIntervalBegin = fFrustumIntervalBegin * fCameraNearFarRange; + fFrustumIntervalEnd = fFrustumIntervalEnd * fCameraNearFarRange; + Vector4[] vFrustumPoints = new Vector4[8]; + + + // This function takes the began and end intervals along with the projection matrix and returns the 8 + // points that repreresent the cascade Interval + CreateFrustumPointsFromCascadeInterval(fFrustumIntervalBegin, fFrustumIntervalEnd, proj, ref vFrustumPoints); + + vLightCameraOrthographicMin = vFLTMAX; + vLightCameraOrthographicMax = vFLTMIN; + + Vector4 vTempTranslatedCornerPoint; + // This next section of code calculates the min and max values for the orthographic projection. + for (int icpIndex = 0; icpIndex < 8; ++icpIndex) + { + // Transform the frustum from camera view space to world space. + vFrustumPoints[icpIndex] = camViewInv.Multiply(vFrustumPoints[icpIndex]);// +V4FF(SceneCamPos, 0.0f);// XMVector4Transform(vFrustumPoints[icpIndex], matInverseViewCamera); + // Transform the point from world space to Light Camera Space. + vTempTranslatedCornerPoint = LightView.Multiply(vFrustumPoints[icpIndex]);// XMVector4Transform(vFrustumPoints[icpIndex], matLightCameraView); + // Find the closest point. + vLightCameraOrthographicMin = Vector4.Min(vTempTranslatedCornerPoint, vLightCameraOrthographicMin); + vLightCameraOrthographicMax = Vector4.Max(vTempTranslatedCornerPoint, vLightCameraOrthographicMax); + } + + // This code removes the shimmering effect along the edges of shadows due to + // the light changing to fit the camera. + // Fit the ortho projection to the cascades far plane and a near plane of zero. + // Pad the projection to be the size of the diagonal of the Frustum partition. + // + // To do this, we pad the ortho transform so that it is always big enough to cover + // the entire camera view frustum. + Vector4 vDiagonal = (vFrustumPoints[0] - vFrustumPoints[6]); + + // The bound is the length of the diagonal of the frustum interval. + float fCascadeBound = vDiagonal.XYZ().Length();// V3FLength(V4FToV3F(vDiagonal)); + vDiagonal = new Vector4(fCascadeBound); + + // The offset calculated will pad the ortho projection so that it is always the same size + // and big enough to cover the entire cascade interval. + Vector4 vBorderOffset = (vDiagonal - (vLightCameraOrthographicMax - vLightCameraOrthographicMin)) * 0.5f; + // Set the Z and W components to zero. + //vBoarderOffset *= g_vMultiplySetzwToZero; + vBorderOffset.Z = 0.0f; + vBorderOffset.W = 0.0f; + + // Add the offsets to the projection. + vLightCameraOrthographicMax += vBorderOffset; + vLightCameraOrthographicMin -= vBorderOffset; + + // The world units per texel are used to snap the shadow the orthographic projection + // to texel sized increments. This keeps the edges of the shadows from shimmering. + float fWorldUnitsPerTexel = fCascadeBound / (float)TextureSize; + vWorldUnitsPerTexel = new Vector4(fWorldUnitsPerTexel, fWorldUnitsPerTexel, 1.0f, 1.0f); //1.0 instead of 0.0 to remove divide by 0 + + // We snap the camera to 1 pixel increments so that moving the camera does not cause the shadows to jitter. + // This is a matter of integer dividing by the world space size of a texel + vLightCameraOrthographicMin = vLightCameraOrthographicMin / vWorldUnitsPerTexel; + vLightCameraOrthographicMin = vLightCameraOrthographicMin.Floor(); + vLightCameraOrthographicMin = vLightCameraOrthographicMin * vWorldUnitsPerTexel; + + vLightCameraOrthographicMax = vLightCameraOrthographicMax / vWorldUnitsPerTexel; + vLightCameraOrthographicMax = vLightCameraOrthographicMax.Floor(); + vLightCameraOrthographicMax = vLightCameraOrthographicMax * vWorldUnitsPerTexel; + + + //These are the unconfigured near and far plane values. They are purposly awful to show + // how important calculating accurate near and far planes is. + float fNearPlane;// = 100000.0f; + float fFarPlane;// = -100000.0f; + + + //V4F tmpmin = vLightCameraOrthographicMin; + //vLightCameraOrthographicMin = -vLightCameraOrthographicMax; + //vLightCameraOrthographicMax = -tmpmin; + + // By intersecting the light frustum with the scene AABB we can get a tighter bound on the near and far plane. + ComputeNearAndFar(out fNearPlane, out fFarPlane, vLightCameraOrthographicMin, vLightCameraOrthographicMax, vSceneAABBPointsLightSpace); + + + //near/far swap necessary because the scene camera has negative aspect ratio... + //float tmpn = fNearPlane; + //fNearPlane = -fFarPlane; + //fFarPlane = -tmpn; + + + + + // Craete the orthographic projection for this cascade. + cascade.Ortho = Matrix.OrthoOffCenterLH(vLightCameraOrthographicMin.X, vLightCameraOrthographicMax.X, vLightCameraOrthographicMin.Y, vLightCameraOrthographicMax.Y, fNearPlane, fFarPlane); + //M16FOrthographicOffCenter(cascade.Ortho, vLightCameraOrthographicMin.x, vLightCameraOrthographicMax.x, vLightCameraOrthographicMax.y, vLightCameraOrthographicMin.y, fNearPlane, fFarPlane); + //D3DXMatrixOrthoOffCenterLH(&m_matShadowProj[iCascadeIndex], + // XMVectorGetX(vLightCameraOrthographicMin), + // XMVectorGetX(vLightCameraOrthographicMax), + // XMVectorGetY(vLightCameraOrthographicMin), + // XMVectorGetY(vLightCameraOrthographicMax), + // fNearPlane, fFarPlane); + + cascade.ZNear = fNearPlane; + cascade.ZFar = fFarPlane; + cascade.IntervalNear = fFrustumIntervalBegin; + cascade.IntervalFar = fFrustumIntervalEnd; + //m_fCascadePartitionsFrustum[iCascadeIndex] = fFrustumIntervalEnd; + + cascade.Matrix = Matrix.Multiply(LightView, cascade.Ortho); + //cascade.Matrix = cascade.Ortho; + cascade.MatrixInv = Matrix.Invert(cascade.Matrix); + cascade.WorldUnitsPerTexel = fWorldUnitsPerTexel; + cascade.WorldUnitsToCascadeUnits = 2.0f / fCascadeBound;// (cascade.WorldUnitsPerTexel * fInvTexelCount); + } + + + context.ClearDepthStencilView(DepthTextureDSV, DepthStencilClearFlags.Depth, 1.0f, 0); + //context.ClearDepthStencilView(cascade.DepthTextureDSV, DepthStencilClearFlags.Depth, 1.0f, 0); + //ID3D11RenderTargetView* pnullView = NULL; + // Set a null render target so as not to render color. + context.OutputMerger.SetRenderTargets(DepthTextureDSV, (RenderTargetView)null); + //context.OutputMerger.SetRenderTargets(cascade.DepthTextureDSV, (RenderTargetView)null); + //context->OMSetRenderTargets(1, &pnullView, cascade.DepthTextureDSV.Get()); + + context.OutputMerger.SetDepthStencilState(DepthRenderDS); + //context->OMSetDepthStencilState(DepthRenderDS.Get(), 1); + + context.Rasterizer.State = DepthRenderRS; + //context->RSSetState(DepthRenderRS.Get()); + + } + + public void BeginDepthRender(DeviceContext context, int cascadeIndex) + { + ShadowmapCascade cascade = Cascades[cascadeIndex]; + + //context.ClearDepthStencilView(DepthTextureDSV, DepthStencilClearFlags.Depth, 1.0f, 0); + ////context.ClearDepthStencilView(cascade.DepthTextureDSV, DepthStencilClearFlags.Depth, 1.0f, 0); + ////ID3D11RenderTargetView* pnullView = NULL; + //// Set a null render target so as not to render color. + //context.OutputMerger.SetRenderTargets(DepthTextureDSV, (RenderTargetView)null); + ////context.OutputMerger.SetRenderTargets(cascade.DepthTextureDSV, (RenderTargetView)null); + ////context->OMSetRenderTargets(1, &pnullView, cascade.DepthTextureDSV.Get()); + + //context.OutputMerger.SetDepthStencilState(DepthRenderDS); + ////context->OMSetDepthStencilState(DepthRenderDS.Get(), 1); + + //context.Rasterizer.State = DepthRenderRS; + ////context->RSSetState(DepthRenderRS.Get()); + + context.Rasterizer.SetViewport(cascade.DepthRenderVP); + //context.Rasterizer.SetViewport(DepthRenderVP); + //context->RSSetViewports(1, &DepthRenderVP); + + } + + public void EndUpdate(DeviceContext context) + { + RTS.Reset(context); + } + + public void SetFinalRenderResources(DeviceContext context) + { + + //ShadowmapVars & v = ShadowVars.Vars; + ShadowVars.Vars.CamScenePos = new Vector4(SceneCamPos, 0.0f); //in shadow scene coords + ShadowVars.Vars.CamSceneView = Matrix.Transpose(SceneCamView); + ShadowVars.Vars.LightView = Matrix.Transpose(LightView); + ShadowVars.Vars.LightDir = new Vector4(LightDirection, 0.0f); + + Matrix dxmatTextureScale = Matrix.Scaling(0.5f, -0.5f, 1.0f); + Matrix dxmatTextureTranslation = Matrix.Translation(0.5f, 0.5f, 0.0f); + Matrix dxmatTextureST = Matrix.Multiply(dxmatTextureScale, dxmatTextureTranslation); + + for (int i = 0; i < CascadeCount; ++i) + { + ShadowmapCascade cascade = Cascades[i]; + + + //M16F mShadowTexture = m_matShadowProj[index] * dxmatTextureScale * dxmatTextureTranslation; + Matrix mShadowTexture = Matrix.Multiply(cascade.Ortho, dxmatTextureST); + + //ShadowVars.Vars.CascadeScales[i].x = mShadowTexture.M11; + //ShadowVars.Vars.CascadeScales[i].y = mShadowTexture.M22; + //ShadowVars.Vars.CascadeScales[i].z = mShadowTexture.M33; + //ShadowVars.Vars.CascadeScales[i].w = 1.0f; + ShadowVars.Vars.CascadeScales.Set(i, new Vector4(mShadowTexture.M11, mShadowTexture.M22, mShadowTexture.M33, 1.0f)); + + //v.CascadeOffsets[i].x = mShadowTexture.M41; + //v.CascadeOffsets[i].y = mShadowTexture.M42; + //v.CascadeOffsets[i].z = mShadowTexture.M43; + //v.CascadeOffsets[i].w = 0.0f; + ShadowVars.Vars.CascadeOffsets.Set(i, new Vector4(mShadowTexture.M41, mShadowTexture.M42, mShadowTexture.M43, 0.0f)); + + //v.CascadeDepths[i].x = cascade.IntervalFar; + //v.CascadeDepths[i].y = 0.0f; + //v.CascadeDepths[i].z = 0.0f; + //v.CascadeDepths[i].w = 0.0f; + ShadowVars.Vars.CascadeDepths.Set(i, new Vector4(cascade.IntervalFar, 0.0f, 0.0f, 0.0f)); + } + + ShadowVars.Vars.CascadeCount = CascadeCount; + ShadowVars.Vars.CascadeVisual = 0; + + ShadowVars.Vars.PCFLoopStart = (PCFSize) / -2; + ShadowVars.Vars.PCFLoopEnd = (PCFSize) / 2 + 1; + + + // The border padding values keep the pixel shader from reading the borders during PCF filtering. + float txs = (float)TextureSize; + ShadowVars.Vars.BorderPaddingMax = (txs - 1.0f) / txs; + ShadowVars.Vars.BorderPaddingMin = 1.0f / txs; + + ShadowVars.Vars.Bias = PCFOffset; + ShadowVars.Vars.BlurBetweenCascades = BlurBetweenCascades; + ShadowVars.Vars.CascadeCountInv = 1.0f / (float)CascadeCount; + ShadowVars.Vars.TexelSize = 1.0f / txs; + ShadowVars.Vars.TexelSizeX = ShadowVars.Vars.TexelSize / (float)CascadeCount; + + ShadowVars.Update(context); + + + SetBuffers(context); + + } + + public void SetBuffers(DeviceContext context) + { + context.VertexShader.SetConstantBuffer(1, ShadowVars.Buffer); //todo: set resource slots + context.PixelShader.SetConstantBuffer(1, ShadowVars.Buffer); + context.PixelShader.SetShaderResource(1, DepthTextureSRV); + context.PixelShader.SetSampler(1, DepthTextureSS); + } + + + + + static readonly Vector3[] vExtentsMap = + { + new Vector3(1.0f, 1.0f, -1.0f), + new Vector3( -1.0f, 1.0f, -1.0f ), + new Vector3(1.0f, -1.0f, -1.0f ), + new Vector3( -1.0f, -1.0f, -1.0f ), + new Vector3( 1.0f, 1.0f, 1.0f ), + new Vector3( -1.0f, 1.0f, 1.0f ), + new Vector3( 1.0f, -1.0f, 1.0f ), + new Vector3( -1.0f, -1.0f, 1.0f ) + }; + void CreateAABBPoints(ref Vector4[] vAABBPoints, Vector3 vCenter, Vector3 vExtents) + { + //-------------------------------------------------------------------------------------- + // This function converts the "center, extents" version of an AABB into 8 points. + //-------------------------------------------------------------------------------------- + //This map enables us to use a for loop and do vector math. + for (int index = 0; index < 8; ++index) + { + vAABBPoints[index] = new Vector4((vExtentsMap[index] * vExtents) + vCenter, 1.0f); + } + } + + static readonly Vector4[] HomogeneousPoints = + { + // Corners of the projection frustum in homogeneous space. + new Vector4( 1.0f, 0.0f, 1.0f, 1.0f ), // right (at far plane) + new Vector4( -1.0f, 0.0f, 1.0f, 1.0f ), // left + new Vector4( 0.0f, 1.0f, 1.0f, 1.0f ), // top + new Vector4( 0.0f, -1.0f, 1.0f, 1.0f ), // bottom + new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ), // near + new Vector4( 0.0f, 0.0f, 1.0f, 1.0f ) // far + }; + void ComputeFrustumFromProjection(out ShadowmapFrustum sf, Matrix pProjection) + { + //----------------------------------------------------------------------------- + // Build a frustum from a persepective projection matrix. The matrix may only + // contain a projection; any rotation, translation or scale will cause the + // constructed frustum to be incorrect. + //----------------------------------------------------------------------------- + + + Matrix matInverse; + + Matrix.Invert(ref pProjection, out matInverse); + + // Compute the frustum corners in world space. + Vector4[] Points = new Vector4[6]; + + for (int i = 0; i < 6; i++) + { + // Transform point. + //Points[i] = XMVector4Transform(HomogenousPoints[i], matInverse); + Points[i] = matInverse.Multiply(HomogeneousPoints[i]); + } + + sf = new ShadowmapFrustum(); + + sf.Origin = new Vector3(0.0f, 0.0f, 0.0f); + sf.Orientation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + + // Compute the slopes. + Points[0] = Points[0] * (1.0f / Points[0].Z);// XMVectorReciprocal(XMVectorSplatZ(Points[0])); + Points[1] = Points[1] * (1.0f / Points[1].Z);// XMVectorReciprocal(XMVectorSplatZ(Points[1])); + Points[2] = Points[2] * (1.0f / Points[2].Z);// XMVectorReciprocal(XMVectorSplatZ(Points[2])); + Points[3] = Points[3] * (1.0f / Points[3].Z);// XMVectorReciprocal(XMVectorSplatZ(Points[3])); + + sf.RightSlope = Points[0].X;// XMVectorGetX(Points[0]); + sf.LeftSlope = Points[1].X;// XMVectorGetX(Points[1]); + sf.TopSlope = Points[2].Y;// XMVectorGetY(Points[2]); + sf.BottomSlope = Points[3].Y;// XMVectorGetY(Points[3]); + + // Compute near and far. + Points[4] = Points[4] * (1.0f / Points[4].W);// XMVectorReciprocal(XMVectorSplatW(Points[4])); + Points[5] = Points[5] * (1.0f / Points[5].W);// XMVectorReciprocal(XMVectorSplatW(Points[5])); + + sf.Near = Points[4].Z;// XMVectorGetZ(Points[4]); + sf.Far = Points[5].Z;// XMVectorGetZ(Points[5]); + } + + + void CreateFrustumPointsFromCascadeInterval(float fCascadeIntervalBegin, float fCascadeIntervalEnd, Matrix vProjection, ref Vector4[] pvCornerPointsWorld) + { + //-------------------------------------------------------------------------------------- + // This function takes the camera's projection matrix and returns the 8 + // points that make up a view frustum. + // The frustum is scaled to fit within the Begin and End interval paramaters. + //-------------------------------------------------------------------------------------- + + ShadowmapFrustum vViewFrust; + + ComputeFrustumFromProjection(out vViewFrust, vProjection); + vViewFrust.Near = -fCascadeIntervalBegin; //negative due to negative aspect ratio projection matrix.. + vViewFrust.Far = -fCascadeIntervalEnd; + + Vector3 vGrabY = new Vector3(0.0f, 1.0f, 0.0f);// ,0x00000000 }; + Vector3 vGrabX = new Vector3(1.0f, 0.0f, 0.0f);// , 0x00000000 }; + + Vector3 vRightTop = new Vector3(vViewFrust.RightSlope, vViewFrust.TopSlope, 1.0f);// , 1.0f }; + Vector3 vLeftBottom = new Vector3(vViewFrust.LeftSlope, vViewFrust.BottomSlope, 1.0f);// , 1.0f }; + Vector3 vNear = new Vector3(vViewFrust.Near, vViewFrust.Near, vViewFrust.Near);// ,1.0f }; + Vector3 vFar = new Vector3(vViewFrust.Far, vViewFrust.Far, vViewFrust.Far);// ,1.0f }; + Vector3 vRightTopNear = vRightTop * vNear;// XMVectorMultiply(vRightTop, vNear); + Vector3 vRightTopFar = vRightTop * vFar;// XMVectorMultiply(vRightTop, vFar); + Vector3 vLeftBottomNear = vLeftBottom * vNear;// XMVectorMultiply(vLeftBottom, vNear); + Vector3 vLeftBottomFar = vLeftBottom * vFar;// XMVectorMultiply(vLeftBottom, vFar); + + pvCornerPointsWorld[0] = new Vector4(vRightTopNear, 1.0f); + pvCornerPointsWorld[1] = new Vector4(V3FSelect(vRightTopNear, vLeftBottomNear, vGrabX), 1.0f); + pvCornerPointsWorld[2] = new Vector4(vLeftBottomNear, 1.0f); + pvCornerPointsWorld[3] = new Vector4(V3FSelect(vRightTopNear, vLeftBottomNear, vGrabY), 1.0f); + + pvCornerPointsWorld[4] = new Vector4(vRightTopFar, 1.0f); + pvCornerPointsWorld[5] = new Vector4(V3FSelect(vRightTopFar, vLeftBottomFar, vGrabX), 1.0f); + pvCornerPointsWorld[6] = new Vector4(vLeftBottomFar, 1.0f); + pvCornerPointsWorld[7] = new Vector4(V3FSelect(vRightTopFar, vLeftBottomFar, vGrabY), 1.0f); + } + Vector3 V3FSelect(Vector3 v1, Vector3 v2, Vector3 control) + { + Vector3 r; + r.X = (control.X == 0.0f) ? v1.X : v2.X; + r.Y = (control.Y == 0.0f) ? v1.Y : v2.Y; + r.Z = (control.Z == 0.0f) ? v1.Z : v2.Z; + return r; + } + + static readonly int[] iAABBTriIndexes = + { + // These are the indices used to tesselate an AABB into a list of triangles. + 0,1,2, 1,2,3, + 4,5,6, 5,6,7, + 0,2,4, 2,4,6, + 1,3,5, 3,5,7, + 0,1,4, 1,4,5, + 2,3,6, 3,6,7 + }; + void ComputeNearAndFar(out float fNearPlane, out float fFarPlane, Vector4 vLightCameraOrthographicMin, Vector4 vLightCameraOrthographicMax, Vector4[] pvPointsInCameraView) + { + //-------------------------------------------------------------------------------------- + // Computing an accurate near and flar plane will decrease surface acne and Peter-panning. + // Surface acne is the term for erroneous self shadowing. Peter-panning is the effect where + // shadows disappear near the base of an object. + // As offsets are generally used with PCF filtering due self shadowing issues, computing the + // correct near and far planes becomes even more important. + // This concept is not complicated, but the intersection code is. + //-------------------------------------------------------------------------------------- + + // Initialize the near and far planes + fNearPlane = float.MaxValue;// FLT_MAX; + fFarPlane = float.MinValue;// -FLT_MAX; + + ShadowmapTriangle[] triangleList = new ShadowmapTriangle[16]; + int iTriangleCnt = 1; + + triangleList[0].pt0 = pvPointsInCameraView[0]; + triangleList[0].pt1 = pvPointsInCameraView[1]; + triangleList[0].pt2 = pvPointsInCameraView[2]; + triangleList[0].culled = false; + + + int[] iPointPassesCollision = new int[3]; + + // At a high level: + // 1. Iterate over all 12 triangles of the AABB. + // 2. Clip the triangles against each plane. Create new triangles as needed. + // 3. Find the min and max z values as the near and far plane. + + //This is easier because the triangles are in camera spacing making the collisions tests simple comparisions. + + float fLightCameraOrthographicMinX = vLightCameraOrthographicMin.X; + float fLightCameraOrthographicMaxX = vLightCameraOrthographicMax.X; + float fLightCameraOrthographicMinY = vLightCameraOrthographicMin.Y; + float fLightCameraOrthographicMaxY = vLightCameraOrthographicMax.Y; + + for (int AABBTriIter = 0; AABBTriIter < 12; ++AABBTriIter) + { + + triangleList[0].pt0 = pvPointsInCameraView[iAABBTriIndexes[AABBTriIter * 3 + 0]]; + triangleList[0].pt1 = pvPointsInCameraView[iAABBTriIndexes[AABBTriIter * 3 + 1]]; + triangleList[0].pt2 = pvPointsInCameraView[iAABBTriIndexes[AABBTriIter * 3 + 2]]; + iTriangleCnt = 1; + triangleList[0].culled = false; + + // Clip each invidual triangle against the 4 frustums. When ever a triangle is clipped into new triangles, + //add them to the list. + for (int frustumPlaneIter = 0; frustumPlaneIter < 4; ++frustumPlaneIter) + { + + float fEdge; + int iComponent; + + if (frustumPlaneIter == 0) + { + fEdge = fLightCameraOrthographicMinX; // todo make float temp + iComponent = 0; + } + else if (frustumPlaneIter == 1) + { + fEdge = fLightCameraOrthographicMaxX; + iComponent = 0; + } + else if (frustumPlaneIter == 2) + { + fEdge = fLightCameraOrthographicMinY; + iComponent = 1; + } + else + { + fEdge = fLightCameraOrthographicMaxY; + iComponent = 1; + } + + for (int triIter = 0; triIter < iTriangleCnt; ++triIter) + { + // We don't delete triangles, so we skip those that have been culled. + if (!triangleList[triIter].culled) + { + int iInsideVertCount = 0; + Vector4 tempOrder; + // Test against the correct frustum plane. + // This could be written more compactly, but it would be harder to understand. + + if (frustumPlaneIter == 0) + { + for (int triPtIter = 0; triPtIter < 3; ++triPtIter) + { + if (triangleList[triIter].pt(triPtIter).X > vLightCameraOrthographicMin.X) + { + iPointPassesCollision[triPtIter] = 1; + } + else + { + iPointPassesCollision[triPtIter] = 0; + } + iInsideVertCount += iPointPassesCollision[triPtIter]; + } + } + else if (frustumPlaneIter == 1) + { + for (int triPtIter = 0; triPtIter < 3; ++triPtIter) + { + if (triangleList[triIter].pt(triPtIter).X < vLightCameraOrthographicMax.X) + { + iPointPassesCollision[triPtIter] = 1; + } + else + { + iPointPassesCollision[triPtIter] = 0; + } + iInsideVertCount += iPointPassesCollision[triPtIter]; + } + } + else if (frustumPlaneIter == 2) + { + for (int triPtIter = 0; triPtIter < 3; ++triPtIter) + { + if (triangleList[triIter].pt(triPtIter).Y > vLightCameraOrthographicMin.Y) + { + iPointPassesCollision[triPtIter] = 1; + } + else + { + iPointPassesCollision[triPtIter] = 0; + } + iInsideVertCount += iPointPassesCollision[triPtIter]; + } + } + else + { + for (int triPtIter = 0; triPtIter < 3; ++triPtIter) + { + if (triangleList[triIter].pt(triPtIter).Y < vLightCameraOrthographicMax.Y) + { + iPointPassesCollision[triPtIter] = 1; + } + else + { + iPointPassesCollision[triPtIter] = 0; + } + iInsideVertCount += iPointPassesCollision[triPtIter]; + } + } + + // Move the points that pass the frustum test to the begining of the array. + if ((iPointPassesCollision[1] != 0) && (iPointPassesCollision[0] == 0)) + { + tempOrder = triangleList[triIter].pt0; + triangleList[triIter].pt0 = triangleList[triIter].pt1; + triangleList[triIter].pt1 = tempOrder; + iPointPassesCollision[0] = 1; + iPointPassesCollision[1] = 0; + } + if ((iPointPassesCollision[2] != 0) && (iPointPassesCollision[1] == 0)) + { + tempOrder = triangleList[triIter].pt1; + triangleList[triIter].pt1 = triangleList[triIter].pt2; + triangleList[triIter].pt2 = tempOrder; + iPointPassesCollision[1] = 1; + iPointPassesCollision[2] = 0; + } + if ((iPointPassesCollision[1] != 0) && (iPointPassesCollision[0] == 0)) + { + tempOrder = triangleList[triIter].pt0; + triangleList[triIter].pt0 = triangleList[triIter].pt1; + triangleList[triIter].pt1 = tempOrder; + iPointPassesCollision[0] = 1; + iPointPassesCollision[1] = 0; + } + + if (iInsideVertCount == 0) + { // All points failed. We're done, + triangleList[triIter].culled = true; + } + else if (iInsideVertCount == 1) + {// One point passed. Clip the triangle against the Frustum plane + triangleList[triIter].culled = false; + + // + Vector4 vVert0ToVert1 = triangleList[triIter].pt1 - triangleList[triIter].pt0; + Vector4 vVert0ToVert2 = triangleList[triIter].pt2 - triangleList[triIter].pt0; + + // Find the collision ratio. + float fHitPointTimeRatio = fEdge - triangleList[triIter].pt0[iComponent]; + // Calculate the distance along the vector as ratio of the hit ratio to the component. + float fDistanceAlongVector01 = fHitPointTimeRatio / vVert0ToVert1[iComponent]; + float fDistanceAlongVector02 = fHitPointTimeRatio / vVert0ToVert2[iComponent]; + // Add the point plus a percentage of the vector. + vVert0ToVert1 = vVert0ToVert1 * fDistanceAlongVector01; + vVert0ToVert1 = vVert0ToVert1 + triangleList[triIter].pt0; + vVert0ToVert2 = vVert0ToVert2 * fDistanceAlongVector02; + vVert0ToVert2 = vVert0ToVert2 + triangleList[triIter].pt0; + + triangleList[triIter].pt1 = vVert0ToVert2; + triangleList[triIter].pt2 = vVert0ToVert1; + + } + else if (iInsideVertCount == 2) + { // 2 in // tesselate into 2 triangles + + + // Copy the triangle\(if it exists) after the current triangle out of + // the way so we can override it with the new triangle we're inserting. + triangleList[iTriangleCnt] = triangleList[triIter + 1]; + + triangleList[triIter].culled = false; + triangleList[triIter + 1].culled = false; + + // Get the vector from the outside point into the 2 inside points. + Vector4 vVert2ToVert0 = triangleList[triIter].pt0 - triangleList[triIter].pt2; + Vector4 vVert2ToVert1 = triangleList[triIter].pt1 - triangleList[triIter].pt2; + + // Get the hit point ratio. + float fHitPointTime_2_0 = fEdge - triangleList[triIter].pt2[iComponent]; + float fDistanceAlongVector_2_0 = fHitPointTime_2_0 / vVert2ToVert0[iComponent]; + // Calcaulte the new vert by adding the percentage of the vector plus point 2. + vVert2ToVert0 = vVert2ToVert0 * fDistanceAlongVector_2_0; + vVert2ToVert0 = vVert2ToVert0 + triangleList[triIter].pt2; + + // Add a new triangle. + triangleList[triIter + 1].pt0 = triangleList[triIter].pt0; + triangleList[triIter + 1].pt1 = triangleList[triIter].pt1; + triangleList[triIter + 1].pt2 = vVert2ToVert0; + + //Get the hit point ratio. + float fHitPointTime_2_1 = fEdge - triangleList[triIter].pt2[iComponent]; + float fDistanceAlongVector_2_1 = fHitPointTime_2_1 / vVert2ToVert1[iComponent]; + vVert2ToVert1 = vVert2ToVert1 * fDistanceAlongVector_2_1; + vVert2ToVert1 = vVert2ToVert1 + triangleList[triIter].pt2; + triangleList[triIter].pt0 = triangleList[triIter + 1].pt1; + triangleList[triIter].pt1 = triangleList[triIter + 1].pt2; + triangleList[triIter].pt2 = vVert2ToVert1; + // Increment triangle count and skip the triangle we just inserted. + ++iTriangleCnt; + ++triIter; + + + } + else + { // all in + triangleList[triIter].culled = false; + + } + }// end if !culled loop + } + } + for (int index = 0; index < iTriangleCnt; ++index) + { + if (!triangleList[index].culled) + { + // Set the near and far plan and the min and max z values respectivly. + for (int vertind = 0; vertind < 3; ++vertind) + { + float fTriangleCoordZ = triangleList[index].pt(vertind).Z; + if (fNearPlane > fTriangleCoordZ) + { + fNearPlane = fTriangleCoordZ; + } + if (fFarPlane < fTriangleCoordZ) + { + fFarPlane = fTriangleCoordZ; + } + } + } + } + } + + } + + + } + + + + public struct ShadowmapVars + { + public Vector4 CamScenePos; //in shadow scene coords + public Matrix CamSceneView; + public Matrix LightView; + public Vector4 LightDir; + public ShadowmapVarsCascadeData CascadeOffsets; + public ShadowmapVarsCascadeData CascadeScales; + public ShadowmapVarsCascadeData CascadeDepths; //in scene eye space + //public Vector4 CascadeOffsets[16]; + //public Vector4 CascadeScales[16]; + //public Vector4 CascadeDepths[16]; //in scene eye space + public int CascadeCount; + public int CascadeVisual; + public int PCFLoopStart; + public int PCFLoopEnd; + public float BorderPaddingMin; + public float BorderPaddingMax; + public float Bias; + public float BlurBetweenCascades; + public float CascadeCountInv; + public float TexelSize; + public float TexelSizeX; + public float Pad2; + } + + public struct ShadowmapVarsCascadeData + { + public Vector4 V00; + public Vector4 V01; + public Vector4 V02; + public Vector4 V03; + public Vector4 V04; + public Vector4 V05; + public Vector4 V06; + public Vector4 V07; + public Vector4 V08; + public Vector4 V09; + public Vector4 V10; + public Vector4 V11; + public Vector4 V12; + public Vector4 V13; + public Vector4 V14; + public Vector4 V15; + + public void Set(int index, Vector4 v) + { + switch (index) + { + case 0: V00 = v; break; + case 1: V01 = v; break; + case 2: V02 = v; break; + case 3: V03 = v; break; + case 4: V04 = v; break; + case 5: V05 = v; break; + case 6: V06 = v; break; + case 7: V07 = v; break; + case 8: V08 = v; break; + case 9: V09 = v; break; + case 10: V10 = v; break; + case 11: V11 = v; break; + case 12: V12 = v; break; + case 13: V13 = v; break; + case 14: V14 = v; break; + case 15: V15 = v; break; + } + } + public Vector4 Get(int index) + { + switch (index) + { + case 0: return V00; + case 1: return V01; + case 2: return V02; + case 3: return V03; + case 4: return V04; + case 5: return V05; + case 6: return V06; + case 7: return V07; + case 8: return V08; + case 9: return V09; + case 10: return V10; + case 11: return V11; + case 12: return V12; + case 13: return V13; + case 14: return V14; + case 15: return V15; + } + return Vector4.Zero; + } + + } + + public class ShadowmapCascade + { + public Shadowmap Owner { get; set; } + public int Index { get; set; } + public float IntervalNear { get; set; } + public float IntervalFar { get; set; } + public float ZNear { get; set; } + public float ZFar { get; set; } + public Matrix Ortho { get; set; } + public Matrix Matrix { get; set; } + public Matrix MatrixInv { get; set; } + //public DepthStencilView DepthTextureDSV { get; set; } + public ViewportF DepthRenderVP { get; set; } + public float WorldUnitsPerTexel { get; set; } //updated each frame for culling + public float WorldUnitsToCascadeUnits { get; set; } + } + + public struct ShadowmapFrustum + { + public Vector3 Origin; // Origin of the frustum (and projection). + public Quaternion Orientation; // Unit quaternion representing rotation. + public float RightSlope; // Positive X slope (X/Z). + public float LeftSlope; // Negative X slope. + public float TopSlope; // Positive Y slope (Y/Z). + public float BottomSlope; // Negative Y slope. + public float Near, Far; // Z of the near plane and far plane. + } + + public struct ShadowmapTriangle + { + //-------------------------------------------------------------------------------------- + // Used to compute an intersection of the orthographic projection and the Scene AABB + //-------------------------------------------------------------------------------------- + public Vector4 pt0; + public Vector4 pt1; + public Vector4 pt2; + public bool culled; + + public Vector4 pt(int i) + { + switch (i) + { + default: + case 0: return pt0; + case 1: return pt1; + case 2: return pt2; + } + } + public void pt(int i, Vector4 v) + { + switch (i) + { + default: + case 0: pt0 = v; break; + case 1: pt1 = v; break; + case 2: pt2 = v; break; + } + } + } + + +} diff --git a/Rendering/Utils/UnitCapsule.cs b/Rendering/Utils/UnitCapsule.cs new file mode 100644 index 0000000..6561281 --- /dev/null +++ b/Rendering/Utils/UnitCapsule.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using SharpDX.DXGI; + +namespace CodeWalker.Rendering +{ + public class UnitCapsule + { + private Buffer VertexBuffer { get; set; } + private Buffer IndexBuffer { get; set; } + private InputLayout InputLayout { get; set; } + private VertexBufferBinding vbbinding; + private int indexcount; + + private struct SphTri + { + public int v1; + public int v2; + public int v3; + public SphTri(int i1, int i2, int i3) + { + v1 = i1; + v2 = i2; + v3 = i3; + } + } + + public UnitCapsule(Device device, byte[] vsbytes, int detail) + { + + InputLayout = new InputLayout(device, vsbytes, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + //new InputElement("NORMAL", 0, Format.R32G32B32A32_Float, 16, 0), + }); + + + + List verts = new List(); + Dictionary vdict = new Dictionary(); + List curtris = new List(); + //List nxttris = new List(); + + verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f));//top end + verts.Add(new Vector4(0.0f, 1.0f, 0.0f, 1.0f));//bottom end + + //detail = nlats each hemisphere + //nlons = detail*4 + + int nlats = detail; + int nlons = detail * 4; + int firstlat = 1 - nlats; + int lastlat = nlats-1; + int lastlon = nlons - 1; + int vertsperlon = 2 + (nlats - 1) * 2; + float latrng = 1.0f / (detail); + float lonrng = 1.0f / (nlons); + float halfpi = (float)(0.5 * Math.PI); + float twopi = (float)(2.0 * Math.PI); + + for (int lon = 0; lon < nlons; lon++) + { + float tlon = lon * lonrng; + float rlon = tlon * twopi; + float lonx = (float)Math.Sin(rlon); + float lonz = (float)Math.Cos(rlon); + for (int lat = firstlat; lat < nlats; lat++) + { + float tlat = lat * latrng; + float rlat = tlat * halfpi; + float laty = (float)Math.Sin(rlat); + float latxz = (float)Math.Cos(rlat); + float hemi = (lat > 0) ? 1.0f : 0.0f; + + verts.Add(new Vector4(lonx * latxz, laty, lonz * latxz, hemi)); + + if (lat == 0) + { + verts.Add(new Vector4(lonx * latxz, laty, lonz * latxz, 1.0f)); //split at the "equator" + } + } + } + + for (int lon = 0; lon < nlons; lon++) + { + int i0 = 2 + lon * vertsperlon;//top row + int i1 = i0 + vertsperlon; + int i2 = i1 - 1;//bottom row + int i3 = i2 + vertsperlon; + + if (lon == lastlon) + { + i1 = 2; + i3 = 1 + vertsperlon; + } + + curtris.Add(new SphTri(0, i1, i0)); //top cap triangles + + for (int lat = firstlat; lat <= lastlat; lat++) + { + int offs = lat - firstlat; + int f1 = i0 + offs; + int f2 = f1 + vertsperlon; + int f3 = f1 + 1; + if (lon == lastlon) + { + f2 = 2 + offs; + } + int f4 = f2 + 1; + curtris.Add(new SphTri(f1, f2, f3)); + curtris.Add(new SphTri(f3, f2, f4)); //fill the rest + } + + curtris.Add(new SphTri(1, i2, i3)); //bottom cap triangles + + + } + + + + + + #region cube version (unfinished) + /* cube version + + verts.Add(new Vector4(-1.0f, 0.0f, 0.0f, 0.0f)); + verts.Add(new Vector4(1.0f, 0.0f, 0.0f, 0.0f)); + verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f)); + verts.Add(new Vector4(0.0f, 1.0f, 0.0f, 1.0f));//bottom end + verts.Add(new Vector4(0.0f, 0.0f, -1.0f, 0.0f)); + verts.Add(new Vector4(0.0f, 0.0f, 1.0f, 0.0f)); + + verts.Add(new Vector4(-1.0f, 0.0f, 0.0f, 1.0f));//0==6 - bottom equator split + verts.Add(new Vector4(1.0f, 0.0f, 0.0f, 1.0f));//1==7 + verts.Add(new Vector4(0.0f, 0.0f, -1.0f, 1.0f));//4==8 + verts.Add(new Vector4(0.0f, 0.0f, 1.0f, 1.0f));//5==9 + + curtris.Add(new SphTri(0, 4, 2)); + curtris.Add(new SphTri(4, 1, 2)); + curtris.Add(new SphTri(1, 5, 2)); + curtris.Add(new SphTri(5, 0, 2)); + + curtris.Add(new SphTri(8, 6, 3));//split halves - Y axis + curtris.Add(new SphTri(7, 8, 3)); + curtris.Add(new SphTri(9, 7, 3)); + curtris.Add(new SphTri(6, 9, 3)); + + for (int i = 0; i < verts.Count; i++) + { + vdict[verts[i]] = i; + } + + + for (int i = 0; i < detail; i++) + { + nxttris.Clear(); + foreach (var tri in curtris) + { + Vector4 v1 = verts[tri.v1]; + Vector4 v2 = verts[tri.v2]; + Vector4 v3 = verts[tri.v3]; + Vector4 s1 = new Vector4(Vector3.Normalize((v1 + v2).XYZ()), v1.W); + Vector4 s2 = new Vector4(Vector3.Normalize((v2 + v3).XYZ()), v1.W); + Vector4 s3 = new Vector4(Vector3.Normalize((v3 + v1).XYZ()), v1.W); + int i1, i2, i3; + if (!vdict.TryGetValue(s1, out i1)) + { + i1 = verts.Count; + verts.Add(s1); + vdict[s1] = i1; + } + if (!vdict.TryGetValue(s2, out i2)) + { + i2 = verts.Count; + verts.Add(s2); + vdict[s2] = i2; + } + if (!vdict.TryGetValue(s3, out i3)) + { + i3 = verts.Count; + verts.Add(s3); + vdict[s3] = i3; + } + nxttris.Add(new SphTri(tri.v1, i1, i3)); + nxttris.Add(new SphTri(tri.v2, i2, i1)); + nxttris.Add(new SphTri(tri.v3, i3, i2)); + nxttris.Add(new SphTri(i1, i2, i3)); + } + var cur = curtris; + curtris = nxttris; + nxttris = cur; + } + */ + #endregion + + + + + List idata = new List(); + foreach (var tri in curtris) + { + idata.Add((uint)tri.v1); + idata.Add((uint)tri.v2); + idata.Add((uint)tri.v3); + } + + + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, verts.ToArray()); + vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0); + + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, idata.ToArray()); + indexcount = idata.Count; + + } + + + public void Draw(DeviceContext context) + { + context.InputAssembler.InputLayout = InputLayout; + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + + context.DrawIndexed(indexcount, 0, 0); + } + + public void DrawInstanced(DeviceContext context, int count) + { + context.InputAssembler.InputLayout = InputLayout; + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + + context.DrawIndexedInstanced(indexcount, count, 0, 0, 0); + } + + + public void Dispose() + { + if (VertexBuffer != null) + { + VertexBuffer.Dispose(); + VertexBuffer = null; + } + if (IndexBuffer != null) + { + IndexBuffer.Dispose(); + IndexBuffer = null; + } + if (InputLayout != null) + { + InputLayout.Dispose(); + InputLayout = null; + } + } + + } + + +} diff --git a/Rendering/Utils/UnitCube.cs b/Rendering/Utils/UnitCube.cs new file mode 100644 index 0000000..55e89f9 --- /dev/null +++ b/Rendering/Utils/UnitCube.cs @@ -0,0 +1,228 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using SharpDX.DXGI; + +namespace CodeWalker.Rendering +{ + public class UnitCube + { + private Buffer VertexBuffer { get; set; } + private Buffer IndexBuffer { get; set; } + private InputLayout InputLayout { get; set; } + private VertexBufferBinding vbbinding; + private bool issigned; + private bool islines; + private bool isnormals; + private int indexcount; + + public UnitCube(Device device, byte[] vsbytes, bool signed, bool lines, bool normals) + { + issigned = signed; + islines = lines; + isnormals = normals; + + if (normals) + { + InputLayout = new InputLayout(device, vsbytes, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32A32_Float, 16, 0), + }); + } + else + { + InputLayout = new InputLayout(device, vsbytes, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + }); + } + + + if (signed) + { + if (normals) + { + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + //position (x4), normal (x3) + //-Z face + -1.0f, -1.0f, -1.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, + -1.0f, 1.0f, -1.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, + //+Z face + -1.0f, -1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, + -1.0f, 1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, + //-Y face + -1.0f, -1.0f, -1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, + -1.0f, -1.0f, 1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, + //+Y face + -1.0f, 1.0f, -1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, + -1.0f, 1.0f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, + //-X face + -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, + -1.0f, -1.0f, 1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, + //+X face + 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, + }); + vbbinding = new VertexBufferBinding(VertexBuffer, 32, 0); + } + else + { + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + //position (x4) + -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + }); + vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0); + } + } + else + { + if (normals) + { + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + //position (x4), normal (x3) + //-Z face + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, + 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, + //+Z face + 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, + 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, + //-Y face + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, + //+Y face + 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, + 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, + //-X face + 0.0f, 0.0f, 0.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, + 0.0f, 0.0f, 1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, + //+X face + 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, + 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, + }); + vbbinding = new VertexBufferBinding(VertexBuffer, 32, 0); + } + else + { + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + //position (x4) + 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + }); + vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0); + } + } + if (lines) + { + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new uint[] + { + 0,1,1,3,3,2,2,0, + 4,5,5,7,7,6,6,4, + 0,4,1,5,3,7,2,6, + }); + indexcount = 24; + } + else + { + if (normals) + { + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new uint[] + { + 0,2,1,1,2,3, + 4,5,6,5,7,6, + 8,9,10,9,11,10, + 12,14,13,13,14,15, + 16,18,17,17,18,19, + 20,21,22,21,23,22 + }); + indexcount = 36; + } + else + { + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new uint[] + { + 0,2,1,1,2,3, + 4,5,6,5,7,6, + //todo: other faces + }); + indexcount = 12; //36.. + } + } + + } + + + public void Draw(DeviceContext context) + { + context.InputAssembler.InputLayout = InputLayout; + + if (islines) + { + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineList; + } + else + { + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + } + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R32_UInt, 0); + + context.DrawIndexed(indexcount, 0, 0); + } + + public void DrawInstanced(DeviceContext context, int count) + { + context.InputAssembler.InputLayout = InputLayout; + + if (islines) + { + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineList; + } + else + { + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + } + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R32_UInt, 0); + + context.DrawIndexedInstanced(indexcount, count, 0, 0, 0); + } + + + public void Dispose() + { + if (VertexBuffer != null) + { + VertexBuffer.Dispose(); + VertexBuffer = null; + } + if (IndexBuffer != null) + { + IndexBuffer.Dispose(); + IndexBuffer = null; + } + if (InputLayout != null) + { + InputLayout.Dispose(); + InputLayout = null; + } + } + + } +} diff --git a/Rendering/Utils/UnitCylinder.cs b/Rendering/Utils/UnitCylinder.cs new file mode 100644 index 0000000..4e5aa71 --- /dev/null +++ b/Rendering/Utils/UnitCylinder.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using SharpDX.DXGI; + +namespace CodeWalker.Rendering +{ + public class UnitCylinder + { + private Buffer VertexBuffer { get; set; } + private Buffer IndexBuffer { get; set; } + private InputLayout InputLayout { get; set; } + private VertexBufferBinding vbbinding; + private int indexcount; + + private struct SphTri + { + public int v1; + public int v2; + public int v3; + public SphTri(int i1, int i2, int i3) + { + v1 = i1; + v2 = i2; + v3 = i3; + } + } + + public UnitCylinder(Device device, byte[] vsbytes, int detail) + { + + InputLayout = new InputLayout(device, vsbytes, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("NORMAL", 0, Format.R32G32B32A32_Float, 16, 0), + }); + + + + List verts = new List(); + Dictionary vdict = new Dictionary(); + List curtris = new List(); + //List nxttris = new List(); + + verts.Add(new Vector4(0.0f, 0.0f, 0.0f, 0.0f));//top end (translated by VS!) + verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f));//top normal + verts.Add(new Vector4(0.0f, 0.0f, 0.0f, 1.0f));//bottom end + verts.Add(new Vector4(0.0f, 1.0f, 0.0f, 1.0f));//bottom normal + + int nlons = detail * 4; + int lastlon = nlons - 1; + float latrng = 1.0f / (detail); + float lonrng = 1.0f / (nlons); + float twopi = (float)(2.0 * Math.PI); + + for (int lon = 0; lon < nlons; lon++) + { + float tlon = lon * lonrng; + float rlon = tlon * twopi; + float lonx = (float)Math.Sin(rlon); + float lonz = (float)Math.Cos(rlon); + + verts.Add(new Vector4(lonx, 0.0f, lonz, 0.0f));//0 + verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f));//top normal + verts.Add(new Vector4(lonx, 0.0f, lonz, 0.0f));//1 + verts.Add(new Vector4(lonx, 0.0f, lonz, 0.0f));//side normal + verts.Add(new Vector4(lonx, 0.0f, lonz, 1.0f));//2 + verts.Add(new Vector4(lonx, 0.0f, lonz, 0.0f));//side normal + verts.Add(new Vector4(lonx, 0.0f, lonz, 1.0f));//3 + verts.Add(new Vector4(0.0f, 1.0f, 0.0f, 0.0f));//bottom normal + } + + for (int lon = 0; lon < nlons; lon++) + { + int i0 = 2 + lon * 4;// vertsperlon;//top row + int i1 = i0 + 4;// vertsperlon; + int i2 = i0 + 3;//bottom row + int i3 = i2 + 4;// vertsperlon; + int f1 = i0 + 1; + int f2 = f1 + 4;// vertsperlon; + + if (lon == lastlon) + { + i1 = 2; + i3 = 5;// 1 + vertsperlon; + f2 = 3;// + offs; + } + + + curtris.Add(new SphTri(0, i1, i0)); //top cap triangles + + curtris.Add(new SphTri(f1, f2, f1+1)); + curtris.Add(new SphTri(f1+1, f2, f2+1)); //fill the rest + + curtris.Add(new SphTri(1, i2, i3)); //bottom cap triangles + + + } + + + + + + List idata = new List(); + foreach (var tri in curtris) + { + idata.Add((uint)tri.v1); + idata.Add((uint)tri.v2); + idata.Add((uint)tri.v3); + } + + + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, verts.ToArray()); + vbbinding = new VertexBufferBinding(VertexBuffer, 32, 0); + + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, idata.ToArray()); + indexcount = idata.Count; + + } + + + public void Draw(DeviceContext context) + { + context.InputAssembler.InputLayout = InputLayout; + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + + context.DrawIndexed(indexcount, 0, 0); + } + + public void DrawInstanced(DeviceContext context, int count) + { + context.InputAssembler.InputLayout = InputLayout; + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + + context.DrawIndexedInstanced(indexcount, count, 0, 0, 0); + } + + + public void Dispose() + { + if (VertexBuffer != null) + { + VertexBuffer.Dispose(); + VertexBuffer = null; + } + if (IndexBuffer != null) + { + IndexBuffer.Dispose(); + IndexBuffer = null; + } + if (InputLayout != null) + { + InputLayout.Dispose(); + InputLayout = null; + } + } + + } + + +} diff --git a/Rendering/Utils/UnitDisc.cs b/Rendering/Utils/UnitDisc.cs new file mode 100644 index 0000000..8c14868 --- /dev/null +++ b/Rendering/Utils/UnitDisc.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using SharpDX.DXGI; + +namespace CodeWalker.Rendering +{ + public class UnitDisc + { + public int SegmentCount { get; set; } + public int IndexCount { get; set; } + public Buffer VertexBuffer { get; set; } + public Buffer IndexBuffer { get; set; } + + private VertexBufferBinding vbbinding; + + public UnitDisc(Device device, int segmentCount, bool invert = false) + { + SegmentCount = segmentCount; + List verts = new List(); + List inds = new List(); + verts.Add(Vector3.Zero); + float incr = (float)Math.PI * 2.0f / segmentCount; + for (int i = 0; i < segmentCount; i++) + { + float a = incr * i; + float px = (float)Math.Sin(a); + float py = (float)Math.Cos(a); + verts.Add(new Vector3(px, py, 0)); + } + for (int i = 0; i < segmentCount; i++) + { + uint ci = (uint)((i == 0) ? segmentCount : i); + uint ni = (uint)i + 1; + inds.Add(0); + inds.Add(invert ? ni : ci); + inds.Add(invert ? ci : ni); + } + IndexCount = inds.Count; + + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, verts.ToArray()); + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, inds.ToArray()); + vbbinding = new VertexBufferBinding(VertexBuffer, 12, 0); + } + + + public void Draw(DeviceContext context) + { + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + context.DrawIndexed(IndexCount, 0, 0); + } + public void DrawInstanced(DeviceContext context, int instcount) + { + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + context.DrawIndexedInstanced(IndexCount, instcount, 0, 0, 0); + } + + public void Dispose() + { + if (VertexBuffer != null) + { + VertexBuffer.Dispose(); + VertexBuffer = null; + } + if (IndexBuffer != null) + { + IndexBuffer.Dispose(); + IndexBuffer = null; + } + } + + public InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), + }; + } + + + } +} diff --git a/Rendering/Utils/UnitQuad.cs b/Rendering/Utils/UnitQuad.cs new file mode 100644 index 0000000..4c08b25 --- /dev/null +++ b/Rendering/Utils/UnitQuad.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using SharpDX.DXGI; + +namespace CodeWalker.Rendering +{ + public class UnitQuad + { + public Buffer VertexBuffer { get; set; } + public Buffer IndexBuffer { get; set; } + + private VertexBufferBinding vbbinding; + + public UnitQuad(Device device, bool invert = false) + { + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + //position (x4), texture (x2) + -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, + //new Vector4(-1.0f, -1.0f, 0.0f, 1.0f), new Vector4(1.0f, -1.0f, 0.0f, 1.0f), + //new Vector4(-1.0f, 1.0f, 0.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + //new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.5f, -0.5f, 0.5f, 1.0f), + //new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), new Vector4(0.5f, 0.5f, 0.5f, 1.0f), + }); + if (invert) + { + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new[] + { + 0u,1u,2u,1u,3u,2u + }); + } + else + { + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new[] + { + 0u,2u,1u,1u,2u,3u + }); + } + + vbbinding = new VertexBufferBinding(VertexBuffer, 24, 0); + } + + + public void Draw(DeviceContext context) + { + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + context.DrawIndexed(6, 0, 0); + } + public void DrawInstanced(DeviceContext context, int instcount) + { + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + context.DrawIndexedInstanced(6, instcount, 0, 0, 0); + } + + public void Dispose() + { + if (VertexBuffer != null) + { + VertexBuffer.Dispose(); + VertexBuffer = null; + } + if (IndexBuffer != null) + { + IndexBuffer.Dispose(); + IndexBuffer = null; + } + } + + + public InputElement[] GetLayout() + { + return new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0), + }; + } + + } +} diff --git a/Rendering/Utils/UnitSphere.cs b/Rendering/Utils/UnitSphere.cs new file mode 100644 index 0000000..bbf36da --- /dev/null +++ b/Rendering/Utils/UnitSphere.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using SharpDX.DXGI; + +namespace CodeWalker.Rendering +{ + public class UnitSphere + { + private Buffer VertexBuffer { get; set; } + private Buffer IndexBuffer { get; set; } + private InputLayout InputLayout { get; set; } + private VertexBufferBinding vbbinding; + private int indexcount; + + private struct SphTri + { + public int v1; + public int v2; + public int v3; + public SphTri(int i1,int i2, int i3) + { + v1 = i1; + v2 = i2; + v3 = i3; + } + } + + public UnitSphere(Device device, byte[] vsbytes, int detail) + { + + InputLayout = new InputLayout(device, vsbytes, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + //new InputElement("NORMAL", 0, Format.R32G32B32A32_Float, 16, 0), + }); + + + + List verts = new List(); + Dictionary vdict = new Dictionary(); + List curtris = new List(); + List nxttris = new List(); + + verts.Add(new Vector3(-1.0f, 0.0f, 0.0f)); + verts.Add(new Vector3(1.0f, 0.0f, 0.0f)); + verts.Add(new Vector3(0.0f, -1.0f, 0.0f)); + verts.Add(new Vector3(0.0f, 1.0f, 0.0f)); + verts.Add(new Vector3(0.0f, 0.0f, -1.0f)); + verts.Add(new Vector3(0.0f, 0.0f, 1.0f)); + curtris.Add(new SphTri(0, 4, 2)); + curtris.Add(new SphTri(4, 1, 2)); + curtris.Add(new SphTri(1, 5, 2)); + curtris.Add(new SphTri(5, 0, 2)); + curtris.Add(new SphTri(4, 0, 3)); + curtris.Add(new SphTri(1, 4, 3)); + curtris.Add(new SphTri(5, 1, 3)); + curtris.Add(new SphTri(0, 5, 3)); + + for (int i = 0; i < verts.Count; i++) + { + vdict[verts[i]] = i; + } + + + for (int i = 0; i < detail; i++) + { + nxttris.Clear(); + foreach (var tri in curtris) + { + Vector3 v1 = verts[tri.v1]; + Vector3 v2 = verts[tri.v2]; + Vector3 v3 = verts[tri.v3]; + Vector3 s1 = Vector3.Normalize(v1 + v2); + Vector3 s2 = Vector3.Normalize(v2 + v3); + Vector3 s3 = Vector3.Normalize(v3 + v1); + int i1, i2, i3; + if (!vdict.TryGetValue(s1, out i1)) + { + i1 = verts.Count; + verts.Add(s1); + vdict[s1] = i1; + } + if (!vdict.TryGetValue(s2, out i2)) + { + i2 = verts.Count; + verts.Add(s2); + vdict[s2] = i2; + } + if (!vdict.TryGetValue(s3, out i3)) + { + i3 = verts.Count; + verts.Add(s3); + vdict[s3] = i3; + } + nxttris.Add(new SphTri(tri.v1, i1, i3)); + nxttris.Add(new SphTri(tri.v2, i2, i1)); + nxttris.Add(new SphTri(tri.v3, i3, i2)); + nxttris.Add(new SphTri(i1, i2, i3)); + } + var cur = curtris; + curtris = nxttris; + nxttris = cur; + } + + + List vdata = new List(); + foreach (var vert in verts) + { + vdata.Add(new Vector4(vert, 1.0f)); + } + + List idata = new List(); + foreach (var tri in curtris) + { + idata.Add((uint)tri.v1); + idata.Add((uint)tri.v2); + idata.Add((uint)tri.v3); + } + + + VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, vdata.ToArray()); + vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0); + + IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, idata.ToArray()); + indexcount = idata.Count; + + } + + + public void Draw(DeviceContext context) + { + context.InputAssembler.InputLayout = InputLayout; + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + + context.DrawIndexed(indexcount, 0, 0); + } + + public void DrawInstanced(DeviceContext context, int count) + { + context.InputAssembler.InputLayout = InputLayout; + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, vbbinding); + context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0); + + context.DrawIndexedInstanced(indexcount, count, 0, 0, 0); + } + + + public void Dispose() + { + if (VertexBuffer != null) + { + VertexBuffer.Dispose(); + VertexBuffer = null; + } + if (IndexBuffer != null) + { + IndexBuffer.Dispose(); + IndexBuffer = null; + } + if (InputLayout != null) + { + InputLayout.Dispose(); + InputLayout = null; + } + } + + } + + +} diff --git a/Resources/CW.ico b/Resources/CW.ico new file mode 100644 index 0000000000000000000000000000000000000000..6c7a70df7aecc591c7f1367ab52fcc797235a36b GIT binary patch literal 17006 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

Q$hFN4?g7Q`3#_{z=)? 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

  • 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

    KQmGAjTt&YTfl zTMx^C=!=}4FGEs-0b~iP#p^U`wm;t1fm#pg%SU&Nv9kdISl&31})Jk0w z{$&RL#dMjN^ZZB)xx(Jxc7dLOO41FXe|cW7@(I|QIQcE8+}`~76)1T47=?xRR@9GX zrJZ#L^a}$1pAXHYT`Ebn#Vs@CJu*ngpHTk=2P%$IKm+EtEyVD;wi{z4P$(A0i3w9M zx-AycM0@nMd&42q;pW`CfTwf9^c3Fsgl^HcMp{*K7>}vP?!?A%*V;(CP6}j^3XI?5 zRH4)5#Q=)b^Zq=H48!nNK8@(@Pn+0Q>s7&Wu!6Sd`AJREI*4kT@j6GC@nLHSKBw+= zwZ-fyT>|;lX*|gFv`H9{gx7ItkY=8PRH=#xddtGrw5UXZZ$+k{+xIIu0nYblT1w?ca;5&k1 z>qN0IP@ufDN*2v45EYZ+Fwup2tgU(k;$Vu*XJQ6HvR)+XA>cTF%5drNWr&55Suz>05iX@@~C>wyqKW>_k_N(n~{)K$jc`+1T(Z zgBiB4zQ*FQ}roe~c2HhejpWWqqJCd`K2t9FSlARbB}U5P)4Y)m+Ps-kO{!S%>k(6?te zGX8p-AnvFJWxJ>a^FY8f@>N_GlwaksjXqaAuroo_oX#fiRAu=K+%bXQDk$--Ut z!dY9W@8_mpj(WRuId{kg2{QZKP=_AFKaFn*midOfCj23?o_}sj`#c|5b{lQp7U9y+ z84~d(zXNj+0bbon_m#M_g7e;43jEo*+TBa$5vEv_q6o#M3?|Lzp7#%QSBg?y&w2I! zlO3>FML$;Q@=D)`yKA%7;Yb@b81BVXvaHQ5l)l0{9zQ4EL#h-n&ezJEhtCw=;+(4f zlQ0b!2zk=bnX%M$Z)(@3xoFyF$$>Pjk$Rifo*Q!4I1rR5s#UG=NRcgzV4cxZoHQ-= z`3ZW{+*(%{(w|2Fub?(Ry<_q?ujZ`3mbk$7^Ym~N28j%witt|YlfLkQ5v~-CjpT5* zgFjoYcd7AP`&uU~Ch_S`%rtR`{@PL3^$zylNoSRO3PDc#!4cJJ{`i(;c!n+J`!%#n z%eNF-8MnfK_@@Btg#usNc05LH2!Sko+X)9?N`t5AJD=qn8U5~tNHm+F z%=-^J5Mv1a3tlE)pERoG5u922!B7)>sAaZ>qrc4jpy; z*bac%djSg=^ydWT&cgx(qhufxnneL|1xnr{sT#6iMLBnTE9k9<(B$9ez>zksfv4F>1t+_=AW*OC*^Nm`W*si52nO3mH=H4olcWpKSu@c zNHKX-Rr;C`Pj2k7$gs^__4D4dzCB`Wz*uwl%aE}d#C8aXxuytj@SyldE=$LZBir-| z8vo8D;`MSDjSNki$EW@h>YhgL%u^jYgR#>g>p_VPvk@@bkO zSIBZo)?y*M+4!Zk;+56}W0zPrP9$d~=Log?Rl5barL@zO!s)Wf_Ji`^nt0#!rQ~@} zn_NBMT9FwJf|{LgEtof2XW|J}@R9*QZIr^(OY0Kvi0t7!o%sb>82 zgYn)c1;cYGjTTFd$3@m_3ENUfcc^TB_#(;%?VN_pH9Xr)7JL^nNJCvM_L-~bTFlX* zCt!(yuSU17E9FxIoJ>0RbEgt-w3Im(>g9p|m_z&aF)dIVQ)k}?Yoa1ATkrpYT`*Q=%Jl1IwT#3Jwu2o=MeXrthfTVST2!fOhMk#fz6yaST z<+EvK|8eWb?kM{Zv62JH{s!_3iWhurK)hzqr&U9d2Qb0CpD%vrzD_g5LcLuXaZ5DO zW_zU0I(Hfr&KSQS4>QQ>p^I=`;U6x@Wl1wjxzSR8NE=EQJvDw!DcQ+#@k`%-wtKu5 z6u!Zny+8Z>xR#<@NERp!G?iLn+(9{?cYiR_f@uH?dH>cghxwMBj{=%T8OebCL6y`B z2o;T*w&oWH3K_sTnMzibbynBoI8#OGd$U93@-)`g40++?&%(}YpAr^rXg@DIKzEi3 zYqRtoKDveJh$l{myp%*??v_p61)zwC;G#EP;o#;O1tuolcdbUel<8~s)m!Z^(m^>E z=T%CN0j8BHoLp(Zj1Ns}d1Fx!jmrgTPTfqHAlt}3$97AnkJGc`ZH66E1lPB48fq?O zjo5g=GR~bw48hATT7uQPR_}X{X9lV zKJ+h?bztXWfWpK6-nIl*&>Wrja5c#|1FmcmpWE-#z0p2z%NgS!rj$jZCyb19kcR1s zXATxIrcv0=Uah*0ON*cay5?C??nm%E*lR|C{IaLsR`1kiPNZ;A@f5KT4s!{1s^1O>NF@sty5wnGM?^qUrS}Z#~Id8<@j91 zEp%ywo}3IzE^)rK^jrlywYvhRF`Pv;P{y<$2PBPTt{?#)zMe4RTMDHRTn`2C?S66S$GYz1|30pdl(HSzDe}%VZoN3bw00DU@Wuz6DvuBIav$DzWe3p|rW@MTV^XpRj zW5QLW%wuB?s<;|{uE^}&>?+dN- z^KtarW=W+abfXFLbNu9V!o-sv-U`?!ysBFUzAJT99NxVIzz>QwHQc|#Mr7iqzJxT? zrM@2QWLb3SZY}w~jl@Dw1qKg))8EG7N0QAFM>GGkrDdJnn!9_8cPny(`i8SzBQviH zKSJaba%@2=l2)XX!?*6t0(}lsI`ezY*mG;j3JAgjTb|zgUtNJU*?J0_vkaUO9L|Y6 zSo7XxynOc@qXN&1A;U^Qb~6vfDYcDt>JL;*I_Tnio^nK$d&?GMm!@e#<69wZNfCDq zfH|Ci;ym=h@X2Zwu8vLlDDLwol%kghK> z`_61%{kZT=GtdPl(K09Fms+l^SsU4cKMnbAP>rMaGL{HpXqm$H*$m&^pn8*5o;cx; zM`JdMxREC=38cyJHKB)b)d@x4+W`ns=(GA#Bvs~{O$$Cg+d#vW_%}hDyA_kU$G zah~33SlE-iu@ht%$p1FGPmqa<@xH*T5X1p9isd$am3qL9T`s`mzU*Kw-Y7F@nsfXd zWqenOK)8E*fA@Srmh$?x}3yEz$mk&)!zapV^#R}nF;rIZbQvcCu5%QY;iD9 zz53=(QM5oj^es0vx+hPj0l7_agO)ZXJ#l^KlPnV&1LbpMEn`=))$65lkEs5U%Xpso zEx)xLpZL60$dn-x0P-@gFB7DXzI4QoA&)tAfvb!((IJ~z=aWInWWtIfWS>~v3am!t zfUe){)Y_w;1c^a0Jweci@_rpO-BzxLmsl|#hfxY&;9WBY8MQk_z_l1^}-GgTl z-Itts^k+n_`d$}qS(>j*2iON@igD;FadvZf4QUHC`7Rt-Z&vEa)AyPkEed>ga4eQ{ zud``5A~{dz5f1xLM$x~q*0G{}$U9Hw#`Uct3EUtUj_r3@kaLFwS9G_z?67*6Vqkg? z;pB)=-C99G*B=Z5H)v;grDz+JR4jHV{^C8^+;E^o54_M8tE#8J8c#E9`@1GpF|R`F zdcIK_3g+SeczK?;C^*h9a3aXl`oo~$L&wPk+xX$e%fLiipj&cNV)L$JN0o)tC7tn~c?pK~PIJ^nw4-5XZG6PE6ctsNQoG*>5-O2kt#_v*)aSwu z^!zCQYQy*Xdth>!-0g7qW8uknf>JM-em&wro@NP!IG4@$Q|AR4q2hr%#`vk23wZ&t?9yWSW>- z3$o_2AF+~!C$8Vv5!Mj51G0Zv2~(w3KaUWh#WcD6%t>|IeP}h&*Zd3IgzRysVTF zkgU59V|gnfoil5E<~ctsewwybukn*FN0ouK?z+A(-f#+4jWpSDp^yn(&42xK;7u@& zNwB%_!Sv;u=!}BRAG=u^VtPs{>3uP&uUaA%N zvtSKJV}Fy6&)wh|pe6IF>o2}B!C{1ysa5wtLLiM;bm_SIrg-8#HpNx4KM@IK`fL@8 zg}L^%GD;!o9(eH%^80?KUio!7lWbq*i{%(vwkb;E1pZ!Tq$NS3IF4TdPjt?=vsgrD zDz4l5JX(k&N&vF!H4TDSH0q`K4=}$Smj$-xBlMU>#rMpU=qH?3>N`%!F&MKYOiYVg z(B?>cIwP>;=z$6v+dY}sZOtgUC++F$e%~UvsHI8IDV^5mios6bb5Z9sRN1P^nWrg_ z-huHZM#}nZ<8MJu8hZT>_=hPC!BBzaqte=H6cqUxf z5DGKH52oKaRb+acfnE+Nw(0^^V#P1`;+#2tG2?ofmw=lQ^D);6I6#S(9Nu;F7jz}~Q zP#&-!mmne?6Eh0!c+jXMP+0yNUNK5vkkNc*1bqd!md}^f+gMnhJ(&rLKIb{w$WUD; zC#bk3(Y|oi^9w`L29b*c0grxt*Z3`EglZ}KAi~vmf zhPz={^`b9W^k5m&^zZ&pwWZbkg6ZH5o#o!5wI6U{w61DIk!byrS`3w$6HX1XFi32V z@q08U;Ww68M<`D7ysmpPP$;$46roTV-T__mS>81DLm}c*gkdW)a$42DK#-&`sX<3W zltE3EHOWVzGa+3NFxzh@IgzGs*pS@d+GCw6j`CAB;gf=%&0Uqnuzl7U;kop5^a0on zvZK>i(tk(#Zi}5RU3efE%Nr?<6%kIpNvc%9>h*mxBa=kvGv(&Wazn>N-tMb6Yq=i)KBQ$6=aMw>g$pSi(7ju zncJV_j)}P;Kxqj{s?~faT(;+0Y6EYbvR750D4FUJnD z*+m=Bnog~@K0#Hh=405LF)I1!hjTAc^_>q|gDdM-f`2d$_qKuFV2l#cg<7*b6={=y zS7zXjKr|RKdK;xXH4iY0}HRt<`oPXI4d!h9@g-M9n-1#$JPwsW#10ri`s^^&C=4#@ zE~w!W{dt^mefg(cWECxem@|gEl6z|J3R^iRJkb8tNB<&(PJXh~9;Ig}n~lo_#aL1i z*_-BNcBA7JrQsIPlm%b8vIC}}I00hv&?oA|#CQ7SxS@0|>%MC~V%3(V2#7C4;)GG| z%>(n>CJ8nSsY&QmqL<_vk{|%cCtgHBq8rJZZs zub%~Sq9{6S3$5pRT-LY<+FFi9H7hZeXS5EVWZptAi;v$8$^tlIMQO9Q`wtTqi&%|( zKUI$SJzb-s#UHdY2fbbzi-(*9h)MN)h`54sY3aKWEtaUJ=qHMI4yOA%VVDh zDPft{R`Rn|R)Uz)^k%^dX2IsVm=)SaE^I04n2k`}B@2>YOBA(@jmZ3Eo+A}q|ra61k?SwL8dVaHJJPz#EnLI_8*sTcFBHwS< zp&_;>! za7A1Ip`@d)=OqvOiCcg}eMOKd4g50)&W0YQR14g#(U4ly%RKu71_x`ODo=rr-KfMO z!91e7%e`99R@Jjyzzx0ywF>zKuqh7LHlQt_DJwI!_7CH`VdhqKiU9qlp{6o?-$JEOm|reX#OyEpqIRv#eRk{IufuOpRF&5TBDQ3 z-Yj4lhxBQHwtqnzkV6a}1m$ASoj#RyU4EED>wOIdt!beK9QD-i(ZYlmr0Vi>sjfct zb1_>{FA`WOW$z5JG3*VI_8yu%#YW6eVd5Fi#D0JX9`A#=KO@vd^2p;!QxDZob_la# z)c+|sMYB!6L}9i}{Z&g~5o!x)o^<0&om?J&`t?xi!ZeGeZ0kCR50=({lpO!M3~rE0 zoUZ&%{X44edn`>3>gXUOc8S@(p03`pW)a*6@gtUg8)LfNI4C0Z0%tDR4Rrye*F?;V zP1`l%&_x!V3wPRE1Uv*Cu5;(YyYu;QxZ>?{|92#Rq(mlO%{u6$Q03Yr2WNzIP8Qaq2+P3o z#vUrt@QcJ{){44_uoTc$FjNlpB7b{))LCmNKBIzQ@}A@3F;h*0;#RZeB>zPQJcj4hIEF8%22o(>GyAL z(-B+wEPcyYE>4N91eIT>qSEMffNkt;A?4EQ=?{B$RLgRD95(+}s^D*h z!-RS5K+41mSz#Lyg%s(=%6lJK%!-;Wq+IIPSIdhHNG3QP-xg`jn?4{M>9(?flcaxA ztmz&UoG*d=aKtn?OT|qgp(A{lERg(!7V>h8xVu@}7Q~#NR*f#8y>~4DgaN zl>M6r3+&w2o7kS|KW?H3UAPV2rn~d*TN%ZT^CsWMc(C#GeHI!jx>5g01^^H?$FuA+ z<>aB7(;U8dFE9M0WsX}6#&JPodg6eh*Kt#_oh`iOGet7T$~K^TG}c<8M9rPt2HuzA zB5V!E*vXWXM*a8@fWEHERi7-jyO=$H4F&^ccMu4%R(SV5ulFFTw3~B&qN?h%;jkw6ns5+VE zzGH$oJaa8*SePT|;)Mz_uksxI>EwnZ_O$Y?_ z$#thO+8?1h3!-Mxf}c}N3OCcp1qYd)Y;(*ZT~t*;XR6A+WpqvX^mi}S1&|wZkz_{v z#>qvF)fFq{XJon+aHsJs`)up$%n{i7_+*(uQu}xt+X%yxWlf1as1KMuSLs|sp7`o) gimp^2c + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + ///

    + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SelectFolderForm)); + this.OkButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.FolderBrowseButton = new System.Windows.Forms.Button(); + this.FolderTextBox = new System.Windows.Forms.TextBox(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.CancelButt = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // OkButton + // + this.OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.OkButton.Location = new System.Drawing.Point(319, 78); + this.OkButton.Name = "OkButton"; + this.OkButton.Size = new System.Drawing.Size(75, 23); + this.OkButton.TabIndex = 64; + this.OkButton.Text = "Ok"; + this.OkButton.UseVisualStyleBackColor = true; + this.OkButton.Click += new System.EventHandler(this.OkButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(157, 13); + this.label1.TabIndex = 63; + this.label1.Text = "Please select your GTAV folder:"; + // + // FolderBrowseButton + // + this.FolderBrowseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.FolderBrowseButton.Location = new System.Drawing.Point(367, 35); + this.FolderBrowseButton.Name = "FolderBrowseButton"; + this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.FolderBrowseButton.TabIndex = 62; + this.FolderBrowseButton.Text = "..."; + this.FolderBrowseButton.UseVisualStyleBackColor = true; + this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click); + // + // FolderTextBox + // + this.FolderTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FolderTextBox.Location = new System.Drawing.Point(12, 36); + this.FolderTextBox.Name = "FolderTextBox"; + this.FolderTextBox.Size = new System.Drawing.Size(345, 20); + this.FolderTextBox.TabIndex = 61; + this.FolderTextBox.TextChanged += new System.EventHandler(this.FolderTextBox_TextChanged); + // + // CancelButt + // + this.CancelButt.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.CancelButt.Location = new System.Drawing.Point(238, 78); + this.CancelButt.Name = "CancelButt"; + this.CancelButt.Size = new System.Drawing.Size(75, 23); + this.CancelButt.TabIndex = 65; + this.CancelButt.Text = "Cancel"; + this.CancelButt.UseVisualStyleBackColor = true; + this.CancelButt.Click += new System.EventHandler(this.CancelButton_Click); + // + // SelectFolderForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(406, 113); + this.Controls.Add(this.CancelButt); + this.Controls.Add(this.OkButton); + this.Controls.Add(this.label1); + this.Controls.Add(this.FolderBrowseButton); + this.Controls.Add(this.FolderTextBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MinimumSize = new System.Drawing.Size(422, 152); + this.Name = "SelectFolderForm"; + this.Text = "Select GTAV folder - CodeWalker by dexyfex"; + this.Load += new System.EventHandler(this.SelectFolderForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button OkButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button FolderBrowseButton; + private System.Windows.Forms.TextBox FolderTextBox; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.Button CancelButt; + } +} \ No newline at end of file diff --git a/SelectFolderForm.cs b/SelectFolderForm.cs new file mode 100644 index 0000000..45c69c2 --- /dev/null +++ b/SelectFolderForm.cs @@ -0,0 +1,67 @@ +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class SelectFolderForm : Form + { + + public string SelectedFolder { get; set; } + public DialogResult Result { get; set; } = DialogResult.Cancel; + + public SelectFolderForm() + { + InitializeComponent(); + } + + private void SelectFolderForm_Load(object sender, EventArgs e) + { + FolderTextBox.Text = Settings.Default.GTAFolder; + } + + private void FolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = FolderTextBox.Text; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + FolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void FolderTextBox_TextChanged(object sender, EventArgs e) + { + SelectedFolder = FolderTextBox.Text; + } + + private void CancelButton_Click(object sender, EventArgs e) + { + Close(); + } + + private void OkButton_Click(object sender, EventArgs e) + { + if (!Directory.Exists(SelectedFolder)) + { + MessageBox.Show("The folder \"" + SelectedFolder + "\" does not exist, or cannot be accessed. Please select another."); + return; + } + if (!File.Exists(SelectedFolder + "\\gta5.exe")) + { + MessageBox.Show("GTA5.exe not found in folder:\n" + SelectedFolder); + return; + } + Result = DialogResult.OK; + Close(); + } + } +} diff --git a/SelectFolderForm.resx b/SelectFolderForm.resx new file mode 100644 index 0000000..bd12579 --- /dev/null +++ b/SelectFolderForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Settings.cs b/Settings.cs new file mode 100644 index 0000000..716f1e4 --- /dev/null +++ b/Settings.cs @@ -0,0 +1,28 @@ +namespace CodeWalker.Properties { + + + // This class allows you to handle specific events on the settings class: + // The SettingChanging event is raised before a setting's value is changed. + // The PropertyChanged event is raised after a setting's value is changed. + // The SettingsLoaded event is raised after the setting values are loaded. + // The SettingsSaving event is raised before the setting values are saved. + internal sealed partial class Settings { + + public Settings() { + // // To add event handlers for saving and changing settings, uncomment the lines below: + // + // this.SettingChanging += this.SettingChangingEventHandler; + // + // this.SettingsSaving += this.SettingsSavingEventHandler; + // + } + + private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + // Add code to handle the SettingChangingEvent event here. + } + + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + // Add code to handle the SettingsSaving event here. + } + } +} diff --git a/SettingsForm.Designer.cs b/SettingsForm.Designer.cs new file mode 100644 index 0000000..2d5ff1a --- /dev/null +++ b/SettingsForm.Designer.cs @@ -0,0 +1,875 @@ +namespace CodeWalker +{ + partial class SettingsForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingsForm)); + this.MainTabControl = new System.Windows.Forms.TabControl(); + this.ControlsTabPage = new System.Windows.Forms.TabPage(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.CameraSmoothingUpDown = new System.Windows.Forms.NumericUpDown(); + this.CameraSensitivityUpDown = new System.Windows.Forms.NumericUpDown(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.KeyBindingNameLabel = new System.Windows.Forms.Label(); + this.KeyBindingsListView = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.KeyBindingComboBox = new System.Windows.Forms.ComboBox(); + this.KeyBindButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.AdvancedTabPage = new System.Windows.Forms.TabPage(); + this.DoneButton = new System.Windows.Forms.Button(); + this.SaveButton = new System.Windows.Forms.Button(); + this.ResetButton = new System.Windows.Forms.Button(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.FolderBrowseButton = new System.Windows.Forms.Button(); + this.FolderTextBox = new System.Windows.Forms.TextBox(); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.label7 = new System.Windows.Forms.Label(); + this.ShadowCascadesUpDown = new System.Windows.Forms.NumericUpDown(); + this.label8 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.CacheSizeUpDown = new System.Windows.Forms.NumericUpDown(); + this.label10 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.CacheTimeUpDown = new System.Windows.Forms.NumericUpDown(); + this.label12 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.ExcludeFoldersTextBox = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.GPUCacheTimeUpDown = new System.Windows.Forms.NumericUpDown(); + this.label15 = new System.Windows.Forms.Label(); + this.label16 = new System.Windows.Forms.Label(); + this.GPUFlushTimeUpDown = new System.Windows.Forms.NumericUpDown(); + this.label17 = new System.Windows.Forms.Label(); + this.label18 = new System.Windows.Forms.Label(); + this.GeometryCacheSizeUpDown = new System.Windows.Forms.NumericUpDown(); + this.label19 = new System.Windows.Forms.Label(); + this.label20 = new System.Windows.Forms.Label(); + this.TextureCacheSizeUpDown = new System.Windows.Forms.NumericUpDown(); + this.label21 = new System.Windows.Forms.Label(); + this.label22 = new System.Windows.Forms.Label(); + this.CollisionCacheSizeUpDown = new System.Windows.Forms.NumericUpDown(); + this.label23 = new System.Windows.Forms.Label(); + this.MainTabControl.SuspendLayout(); + this.ControlsTabPage.SuspendLayout(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.CameraSmoothingUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CameraSensitivityUpDown)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.AdvancedTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ShadowCascadesUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CacheSizeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CacheTimeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.GPUCacheTimeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.GPUFlushTimeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.GeometryCacheSizeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.TextureCacheSizeUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CollisionCacheSizeUpDown)).BeginInit(); + this.SuspendLayout(); + // + // MainTabControl + // + this.MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTabControl.Controls.Add(this.ControlsTabPage); + this.MainTabControl.Controls.Add(this.AdvancedTabPage); + this.MainTabControl.Location = new System.Drawing.Point(12, 12); + this.MainTabControl.Name = "MainTabControl"; + this.MainTabControl.SelectedIndex = 0; + this.MainTabControl.Size = new System.Drawing.Size(460, 430); + this.MainTabControl.TabIndex = 0; + // + // ControlsTabPage + // + this.ControlsTabPage.Controls.Add(this.groupBox2); + this.ControlsTabPage.Controls.Add(this.groupBox1); + this.ControlsTabPage.Location = new System.Drawing.Point(4, 22); + this.ControlsTabPage.Name = "ControlsTabPage"; + this.ControlsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ControlsTabPage.Size = new System.Drawing.Size(452, 397); + this.ControlsTabPage.TabIndex = 0; + this.ControlsTabPage.Text = "Controls"; + this.ControlsTabPage.UseVisualStyleBackColor = true; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.label3); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.CameraSmoothingUpDown); + this.groupBox2.Controls.Add(this.CameraSensitivityUpDown); + this.groupBox2.Location = new System.Drawing.Point(6, 301); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(440, 90); + this.groupBox2.TabIndex = 10; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Mouse settings"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(242, 30); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(181, 26); + this.label4.TabIndex = 8; + this.label4.Text = "Change speed / zoom: Mouse wheel\r\nRotate camera: Left drag"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(6, 56); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(97, 13); + this.label3.TabIndex = 3; + this.label3.Text = "Camera smoothing:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(6, 30); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(94, 13); + this.label2.TabIndex = 2; + this.label2.Text = "Camera sensitivity:"; + // + // CameraSmoothingUpDown + // + this.CameraSmoothingUpDown.DecimalPlaces = 1; + this.CameraSmoothingUpDown.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.CameraSmoothingUpDown.Location = new System.Drawing.Point(116, 54); + this.CameraSmoothingUpDown.Name = "CameraSmoothingUpDown"; + this.CameraSmoothingUpDown.Size = new System.Drawing.Size(77, 20); + this.CameraSmoothingUpDown.TabIndex = 7; + this.CameraSmoothingUpDown.ValueChanged += new System.EventHandler(this.CameraSmoothingUpDown_ValueChanged); + // + // CameraSensitivityUpDown + // + this.CameraSensitivityUpDown.DecimalPlaces = 1; + this.CameraSensitivityUpDown.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.CameraSensitivityUpDown.Location = new System.Drawing.Point(116, 28); + this.CameraSensitivityUpDown.Name = "CameraSensitivityUpDown"; + this.CameraSensitivityUpDown.Size = new System.Drawing.Size(77, 20); + this.CameraSensitivityUpDown.TabIndex = 6; + this.CameraSensitivityUpDown.ValueChanged += new System.EventHandler(this.CameraSensitivityUpDown_ValueChanged); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.KeyBindingNameLabel); + this.groupBox1.Controls.Add(this.KeyBindingsListView); + this.groupBox1.Controls.Add(this.KeyBindingComboBox); + this.groupBox1.Controls.Add(this.KeyBindButton); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(6, 6); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(440, 288); + this.groupBox1.TabIndex = 5; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Key bindings"; + // + // KeyBindingNameLabel + // + this.KeyBindingNameLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.KeyBindingNameLabel.AutoSize = true; + this.KeyBindingNameLabel.Location = new System.Drawing.Point(259, 28); + this.KeyBindingNameLabel.Name = "KeyBindingNameLabel"; + this.KeyBindingNameLabel.Size = new System.Drawing.Size(107, 13); + this.KeyBindingNameLabel.TabIndex = 6; + this.KeyBindingNameLabel.Text = "(No binding selected)"; + // + // KeyBindingsListView + // + this.KeyBindingsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.KeyBindingsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.KeyBindingsListView.FullRowSelect = true; + this.KeyBindingsListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.KeyBindingsListView.HideSelection = false; + this.KeyBindingsListView.Location = new System.Drawing.Point(6, 19); + this.KeyBindingsListView.Name = "KeyBindingsListView"; + this.KeyBindingsListView.Size = new System.Drawing.Size(237, 263); + this.KeyBindingsListView.TabIndex = 3; + this.KeyBindingsListView.UseCompatibleStateImageBehavior = false; + this.KeyBindingsListView.View = System.Windows.Forms.View.Details; + this.KeyBindingsListView.SelectedIndexChanged += new System.EventHandler(this.KeyBindingsListView_SelectedIndexChanged); + // + // columnHeader1 + // + this.columnHeader1.Text = "Action"; + this.columnHeader1.Width = 147; + // + // columnHeader2 + // + this.columnHeader2.Text = "Key"; + // + // KeyBindingComboBox + // + this.KeyBindingComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.KeyBindingComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.KeyBindingComboBox.Enabled = false; + this.KeyBindingComboBox.FormattingEnabled = true; + this.KeyBindingComboBox.Location = new System.Drawing.Point(293, 54); + this.KeyBindingComboBox.Name = "KeyBindingComboBox"; + this.KeyBindingComboBox.Size = new System.Drawing.Size(104, 21); + this.KeyBindingComboBox.TabIndex = 4; + this.KeyBindingComboBox.SelectedIndexChanged += new System.EventHandler(this.KeyBindingComboBox_SelectedIndexChanged); + // + // KeyBindButton + // + this.KeyBindButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.KeyBindButton.Enabled = false; + this.KeyBindButton.Location = new System.Drawing.Point(403, 53); + this.KeyBindButton.Name = "KeyBindButton"; + this.KeyBindButton.Size = new System.Drawing.Size(31, 23); + this.KeyBindButton.TabIndex = 5; + this.KeyBindButton.Text = "..."; + this.KeyBindButton.UseVisualStyleBackColor = true; + this.KeyBindButton.Click += new System.EventHandler(this.KeyBindButton_Click); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(259, 58); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(28, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Key:"; + // + // AdvancedTabPage + // + this.AdvancedTabPage.Controls.Add(this.label22); + this.AdvancedTabPage.Controls.Add(this.CollisionCacheSizeUpDown); + this.AdvancedTabPage.Controls.Add(this.label23); + this.AdvancedTabPage.Controls.Add(this.label20); + this.AdvancedTabPage.Controls.Add(this.TextureCacheSizeUpDown); + this.AdvancedTabPage.Controls.Add(this.label21); + this.AdvancedTabPage.Controls.Add(this.label18); + this.AdvancedTabPage.Controls.Add(this.GeometryCacheSizeUpDown); + this.AdvancedTabPage.Controls.Add(this.label19); + this.AdvancedTabPage.Controls.Add(this.label16); + this.AdvancedTabPage.Controls.Add(this.GPUFlushTimeUpDown); + this.AdvancedTabPage.Controls.Add(this.label17); + this.AdvancedTabPage.Controls.Add(this.label14); + this.AdvancedTabPage.Controls.Add(this.GPUCacheTimeUpDown); + this.AdvancedTabPage.Controls.Add(this.label15); + this.AdvancedTabPage.Controls.Add(this.label13); + this.AdvancedTabPage.Controls.Add(this.ExcludeFoldersTextBox); + this.AdvancedTabPage.Controls.Add(this.label11); + this.AdvancedTabPage.Controls.Add(this.CacheTimeUpDown); + this.AdvancedTabPage.Controls.Add(this.label12); + this.AdvancedTabPage.Controls.Add(this.label9); + this.AdvancedTabPage.Controls.Add(this.CacheSizeUpDown); + this.AdvancedTabPage.Controls.Add(this.label10); + this.AdvancedTabPage.Controls.Add(this.label8); + this.AdvancedTabPage.Controls.Add(this.ShadowCascadesUpDown); + this.AdvancedTabPage.Controls.Add(this.label7); + this.AdvancedTabPage.Controls.Add(this.label6); + this.AdvancedTabPage.Controls.Add(this.FolderBrowseButton); + this.AdvancedTabPage.Controls.Add(this.FolderTextBox); + this.AdvancedTabPage.Controls.Add(this.label5); + this.AdvancedTabPage.Location = new System.Drawing.Point(4, 22); + this.AdvancedTabPage.Name = "AdvancedTabPage"; + this.AdvancedTabPage.Padding = new System.Windows.Forms.Padding(3); + this.AdvancedTabPage.Size = new System.Drawing.Size(452, 404); + this.AdvancedTabPage.TabIndex = 1; + this.AdvancedTabPage.Text = "Advanced"; + this.AdvancedTabPage.UseVisualStyleBackColor = true; + // + // DoneButton + // + this.DoneButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.DoneButton.Location = new System.Drawing.Point(397, 448); + this.DoneButton.Name = "DoneButton"; + this.DoneButton.Size = new System.Drawing.Size(75, 23); + this.DoneButton.TabIndex = 3; + this.DoneButton.Text = "Done"; + this.DoneButton.UseVisualStyleBackColor = true; + this.DoneButton.Click += new System.EventHandler(this.DoneButton_Click); + // + // SaveButton + // + this.SaveButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.SaveButton.Location = new System.Drawing.Point(284, 448); + this.SaveButton.Name = "SaveButton"; + this.SaveButton.Size = new System.Drawing.Size(107, 23); + this.SaveButton.TabIndex = 2; + this.SaveButton.Text = "Save settings"; + this.SaveButton.UseVisualStyleBackColor = true; + this.SaveButton.Click += new System.EventHandler(this.SaveButton_Click); + // + // ResetButton + // + this.ResetButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.ResetButton.Location = new System.Drawing.Point(158, 448); + this.ResetButton.Name = "ResetButton"; + this.ResetButton.Size = new System.Drawing.Size(107, 23); + this.ResetButton.TabIndex = 1; + this.ResetButton.Text = "Reset all settings"; + this.ResetButton.UseVisualStyleBackColor = true; + this.ResetButton.Click += new System.EventHandler(this.ResetButton_Click); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(6, 3); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(349, 13); + this.label5.TabIndex = 0; + this.label5.Text = "NOTE: These settings require CodeWalker to be restarted to take effect."; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(6, 31); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(71, 13); + this.label6.TabIndex = 50; + this.label6.Text = "GTA V folder:"; + // + // FolderBrowseButton + // + this.FolderBrowseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.FolderBrowseButton.Location = new System.Drawing.Point(419, 27); + this.FolderBrowseButton.Name = "FolderBrowseButton"; + this.FolderBrowseButton.Size = new System.Drawing.Size(27, 23); + this.FolderBrowseButton.TabIndex = 49; + this.FolderBrowseButton.Text = "..."; + this.FolderBrowseButton.UseVisualStyleBackColor = true; + this.FolderBrowseButton.Click += new System.EventHandler(this.FolderBrowseButton_Click); + // + // FolderTextBox + // + this.FolderTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FolderTextBox.Location = new System.Drawing.Point(110, 28); + this.FolderTextBox.Name = "FolderTextBox"; + this.FolderTextBox.Size = new System.Drawing.Size(303, 20); + this.FolderTextBox.TabIndex = 48; + this.FolderTextBox.TextChanged += new System.EventHandler(this.FolderTextBox_TextChanged); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(6, 100); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(98, 13); + this.label7.TabIndex = 51; + this.label7.Text = "Shadow cascades:"; + // + // ShadowCascadesUpDown + // + this.ShadowCascadesUpDown.Location = new System.Drawing.Point(110, 98); + this.ShadowCascadesUpDown.Maximum = new decimal(new int[] { + 6, + 0, + 0, + 0}); + this.ShadowCascadesUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.ShadowCascadesUpDown.Name = "ShadowCascadesUpDown"; + this.ShadowCascadesUpDown.Size = new System.Drawing.Size(48, 20); + this.ShadowCascadesUpDown.TabIndex = 52; + this.ShadowCascadesUpDown.Value = new decimal(new int[] { + 6, + 0, + 0, + 0}); + this.ShadowCascadesUpDown.ValueChanged += new System.EventHandler(this.ShadowCascadesUpDown_ValueChanged); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(174, 95); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(236, 26); + this.label8.TabIndex = 53; + this.label8.Text = "The total number of shadow cascades to render.\r\nLess cascades = better performanc" + + "e"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(192, 169); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(226, 13); + this.label9.TabIndex = 56; + this.label9.Text = "Maximum cache system memory usage, in MB."; + // + // CacheSizeUpDown + // + this.CacheSizeUpDown.Increment = new decimal(new int[] { + 128, + 0, + 0, + 0}); + this.CacheSizeUpDown.Location = new System.Drawing.Point(110, 167); + this.CacheSizeUpDown.Maximum = new decimal(new int[] { + 16384, + 0, + 0, + 0}); + this.CacheSizeUpDown.Minimum = new decimal(new int[] { + 1024, + 0, + 0, + 0}); + this.CacheSizeUpDown.Name = "CacheSizeUpDown"; + this.CacheSizeUpDown.Size = new System.Drawing.Size(64, 20); + this.CacheSizeUpDown.TabIndex = 60; + this.CacheSizeUpDown.ThousandsSeparator = true; + this.CacheSizeUpDown.Value = new decimal(new int[] { + 2048, + 0, + 0, + 0}); + this.CacheSizeUpDown.ValueChanged += new System.EventHandler(this.CacheSizeUpDown_ValueChanged); + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(6, 169); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(87, 13); + this.label10.TabIndex = 54; + this.label10.Text = "Main cache size:"; + // + // label11 + // + this.label11.Location = new System.Drawing.Point(175, 132); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(269, 34); + this.label11.TabIndex = 59; + this.label11.Text = "The minimum duration, in seconds, that resources will remain loaded in memory."; + // + // CacheTimeUpDown + // + this.CacheTimeUpDown.DecimalPlaces = 1; + this.CacheTimeUpDown.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.CacheTimeUpDown.Location = new System.Drawing.Point(110, 135); + this.CacheTimeUpDown.Maximum = new decimal(new int[] { + 60, + 0, + 0, + 0}); + this.CacheTimeUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.CacheTimeUpDown.Name = "CacheTimeUpDown"; + this.CacheTimeUpDown.Size = new System.Drawing.Size(48, 20); + this.CacheTimeUpDown.TabIndex = 58; + this.CacheTimeUpDown.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.CacheTimeUpDown.ValueChanged += new System.EventHandler(this.CacheTimeUpDown_ValueChanged); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(6, 137); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(88, 13); + this.label12.TabIndex = 57; + this.label12.Text = "Main cache time:"; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(6, 64); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(82, 13); + this.label13.TabIndex = 62; + this.label13.Text = "Exclude folders:"; + // + // ExcludeFoldersTextBox + // + this.ExcludeFoldersTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ExcludeFoldersTextBox.Location = new System.Drawing.Point(110, 61); + this.ExcludeFoldersTextBox.Name = "ExcludeFoldersTextBox"; + this.ExcludeFoldersTextBox.Size = new System.Drawing.Size(303, 20); + this.ExcludeFoldersTextBox.TabIndex = 50; + this.ExcludeFoldersTextBox.TextChanged += new System.EventHandler(this.ExcludeFoldersTextBox_TextChanged); + // + // label14 + // + this.label14.Location = new System.Drawing.Point(175, 204); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(269, 34); + this.label14.TabIndex = 65; + this.label14.Text = "The minimum duration, in seconds, that resources will remain loaded in graphics m" + + "emory."; + // + // GPUCacheTimeUpDown + // + this.GPUCacheTimeUpDown.DecimalPlaces = 1; + this.GPUCacheTimeUpDown.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.GPUCacheTimeUpDown.Location = new System.Drawing.Point(110, 207); + this.GPUCacheTimeUpDown.Maximum = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.GPUCacheTimeUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.GPUCacheTimeUpDown.Name = "GPUCacheTimeUpDown"; + this.GPUCacheTimeUpDown.Size = new System.Drawing.Size(48, 20); + this.GPUCacheTimeUpDown.TabIndex = 64; + this.GPUCacheTimeUpDown.Value = new decimal(new int[] { + 5, + 0, + 0, + 65536}); + this.GPUCacheTimeUpDown.ValueChanged += new System.EventHandler(this.GPUCacheTimeUpDown_ValueChanged); + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(6, 209); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(88, 13); + this.label15.TabIndex = 63; + this.label15.Text = "GPU cache time:"; + // + // label16 + // + this.label16.Location = new System.Drawing.Point(175, 236); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(269, 34); + this.label16.TabIndex = 68; + this.label16.Text = "The minimum duration, in seconds, between unloading batches of resources from gra" + + "phics memory."; + // + // GPUFlushTimeUpDown + // + this.GPUFlushTimeUpDown.DecimalPlaces = 2; + this.GPUFlushTimeUpDown.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.GPUFlushTimeUpDown.Location = new System.Drawing.Point(110, 239); + this.GPUFlushTimeUpDown.Maximum = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.GPUFlushTimeUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 131072}); + this.GPUFlushTimeUpDown.Name = "GPUFlushTimeUpDown"; + this.GPUFlushTimeUpDown.Size = new System.Drawing.Size(48, 20); + this.GPUFlushTimeUpDown.TabIndex = 67; + this.GPUFlushTimeUpDown.Value = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.GPUFlushTimeUpDown.ValueChanged += new System.EventHandler(this.GPUFlushTimeUpDown_ValueChanged); + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(6, 241); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(80, 13); + this.label17.TabIndex = 66; + this.label17.Text = "GPU flush time:"; + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(184, 273); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(247, 13); + this.label18.TabIndex = 70; + this.label18.Text = "Maximum geometry graphics memory usage, in MB."; + // + // GeometryCacheSizeUpDown + // + this.GeometryCacheSizeUpDown.Increment = new decimal(new int[] { + 128, + 0, + 0, + 0}); + this.GeometryCacheSizeUpDown.Location = new System.Drawing.Point(110, 271); + this.GeometryCacheSizeUpDown.Maximum = new decimal(new int[] { + 4096, + 0, + 0, + 0}); + this.GeometryCacheSizeUpDown.Minimum = new decimal(new int[] { + 256, + 0, + 0, + 0}); + this.GeometryCacheSizeUpDown.Name = "GeometryCacheSizeUpDown"; + this.GeometryCacheSizeUpDown.Size = new System.Drawing.Size(58, 20); + this.GeometryCacheSizeUpDown.TabIndex = 71; + this.GeometryCacheSizeUpDown.ThousandsSeparator = true; + this.GeometryCacheSizeUpDown.Value = new decimal(new int[] { + 512, + 0, + 0, + 0}); + this.GeometryCacheSizeUpDown.ValueChanged += new System.EventHandler(this.GeometryCacheSizeUpDown_ValueChanged); + // + // label19 + // + this.label19.AutoSize = true; + this.label19.Location = new System.Drawing.Point(6, 273); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(88, 13); + this.label19.TabIndex = 69; + this.label19.Text = "Geometry cache:"; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(184, 305); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(236, 13); + this.label20.TabIndex = 73; + this.label20.Text = "Maximum texture graphics memory usage, in MB."; + // + // TextureCacheSizeUpDown + // + this.TextureCacheSizeUpDown.Increment = new decimal(new int[] { + 256, + 0, + 0, + 0}); + this.TextureCacheSizeUpDown.Location = new System.Drawing.Point(110, 303); + this.TextureCacheSizeUpDown.Maximum = new decimal(new int[] { + 8192, + 0, + 0, + 0}); + this.TextureCacheSizeUpDown.Minimum = new decimal(new int[] { + 256, + 0, + 0, + 0}); + this.TextureCacheSizeUpDown.Name = "TextureCacheSizeUpDown"; + this.TextureCacheSizeUpDown.Size = new System.Drawing.Size(58, 20); + this.TextureCacheSizeUpDown.TabIndex = 74; + this.TextureCacheSizeUpDown.ThousandsSeparator = true; + this.TextureCacheSizeUpDown.Value = new decimal(new int[] { + 1024, + 0, + 0, + 0}); + this.TextureCacheSizeUpDown.ValueChanged += new System.EventHandler(this.TextureCacheSizeUpDown_ValueChanged); + // + // label21 + // + this.label21.AutoSize = true; + this.label21.Location = new System.Drawing.Point(6, 305); + this.label21.Name = "label21"; + this.label21.Size = new System.Drawing.Size(79, 13); + this.label21.TabIndex = 72; + this.label21.Text = "Texture cache:"; + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(184, 337); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(246, 13); + this.label22.TabIndex = 76; + this.label22.Text = "Maximum collisions graphics memory usage, in MB."; + // + // CollisionCacheSizeUpDown + // + this.CollisionCacheSizeUpDown.Increment = new decimal(new int[] { + 32, + 0, + 0, + 0}); + this.CollisionCacheSizeUpDown.Location = new System.Drawing.Point(110, 335); + this.CollisionCacheSizeUpDown.Maximum = new decimal(new int[] { + 512, + 0, + 0, + 0}); + this.CollisionCacheSizeUpDown.Minimum = new decimal(new int[] { + 64, + 0, + 0, + 0}); + this.CollisionCacheSizeUpDown.Name = "CollisionCacheSizeUpDown"; + this.CollisionCacheSizeUpDown.Size = new System.Drawing.Size(58, 20); + this.CollisionCacheSizeUpDown.TabIndex = 77; + this.CollisionCacheSizeUpDown.ThousandsSeparator = true; + this.CollisionCacheSizeUpDown.Value = new decimal(new int[] { + 128, + 0, + 0, + 0}); + this.CollisionCacheSizeUpDown.ValueChanged += new System.EventHandler(this.CollisionCacheSizeUpDown_ValueChanged); + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(6, 337); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(81, 13); + this.label23.TabIndex = 75; + this.label23.Text = "Collision cache:"; + // + // SettingsForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(484, 483); + this.Controls.Add(this.ResetButton); + this.Controls.Add(this.SaveButton); + this.Controls.Add(this.DoneButton); + this.Controls.Add(this.MainTabControl); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "SettingsForm"; + this.Text = "Settings - CodeWalker by dexyfex"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.SettingsForm_FormClosed); + this.MainTabControl.ResumeLayout(false); + this.ControlsTabPage.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.CameraSmoothingUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CameraSensitivityUpDown)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.AdvancedTabPage.ResumeLayout(false); + this.AdvancedTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.ShadowCascadesUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CacheSizeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CacheTimeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.GPUCacheTimeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.GPUFlushTimeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.GeometryCacheSizeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.TextureCacheSizeUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CollisionCacheSizeUpDown)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TabControl MainTabControl; + private System.Windows.Forms.TabPage ControlsTabPage; + private System.Windows.Forms.TabPage AdvancedTabPage; + private System.Windows.Forms.Button DoneButton; + private System.Windows.Forms.Button SaveButton; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ComboBox KeyBindingComboBox; + private System.Windows.Forms.Button KeyBindButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ListView KeyBindingsListView; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.NumericUpDown CameraSensitivityUpDown; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown CameraSmoothingUpDown; + private System.Windows.Forms.Label KeyBindingNameLabel; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button ResetButton; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button FolderBrowseButton; + private System.Windows.Forms.TextBox FolderTextBox; + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.NumericUpDown ShadowCascadesUpDown; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.NumericUpDown CacheSizeUpDown; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.NumericUpDown CacheTimeUpDown; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.TextBox ExcludeFoldersTextBox; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.NumericUpDown GPUCacheTimeUpDown; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.NumericUpDown GPUFlushTimeUpDown; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.NumericUpDown GeometryCacheSizeUpDown; + private System.Windows.Forms.Label label19; + private System.Windows.Forms.Label label22; + private System.Windows.Forms.NumericUpDown CollisionCacheSizeUpDown; + private System.Windows.Forms.Label label23; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.NumericUpDown TextureCacheSizeUpDown; + private System.Windows.Forms.Label label21; + } +} \ No newline at end of file diff --git a/SettingsForm.cs b/SettingsForm.cs new file mode 100644 index 0000000..8ed3f18 --- /dev/null +++ b/SettingsForm.cs @@ -0,0 +1,323 @@ +using CodeWalker.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class SettingsForm : Form + { + private WorldForm worldForm; + + private KeyBindings keyBindings = new KeyBindings(Settings.Default.KeyBindings); + private string selKeyBinding = ""; + private Keys selKeyBindingVal = Keys.None; + + private float camSensitivity = Settings.Default.CameraSensitivity; + private float camSmoothing = Settings.Default.CameraSmoothing; + + + + public SettingsForm(WorldForm owner) + { + InitializeComponent(); + + worldForm = owner; + + var allkeys = Enum.GetValues(typeof(Keys)); + foreach (var keyval in allkeys) + { + KeyBindingComboBox.Items.Add(keyval); + } + + LoadKeyBindings(); + + LoadMouseSettings(); + + LoadAdvancedSettings(); + } + + private void LoadKeyBindings() + { + KeyBindingsListView.Items.Clear(); + AddKeyBinding("Move Forwards", keyBindings.MoveForward); + AddKeyBinding("Move Backwards", keyBindings.MoveBackward); + AddKeyBinding("Move Left", keyBindings.MoveLeft); + AddKeyBinding("Move Right", keyBindings.MoveRight); + AddKeyBinding("Move Up", keyBindings.MoveUp); + AddKeyBinding("Move Down", keyBindings.MoveDown); + AddKeyBinding("Move Slower / Zoom In", keyBindings.MoveSlowerZoomIn); + AddKeyBinding("Move Faster / Zoom Out", keyBindings.MoveFasterZoomOut); + AddKeyBinding("Toggle Mouse Select", keyBindings.ToggleMouseSelect); + AddKeyBinding("Toggle Toolbar", keyBindings.ToggleToolbar); + AddKeyBinding("Exit Edit Mode", keyBindings.ExitEditMode); + AddKeyBinding("Edit Position", keyBindings.EditPosition); + AddKeyBinding("Edit Rotation", keyBindings.EditRotation); + AddKeyBinding("Edit Scale", keyBindings.EditScale); + + } + private void LoadMouseSettings() + { + CameraSensitivityUpDown.Value = (decimal)camSensitivity * 1000; + CameraSmoothingUpDown.Value = (decimal)camSmoothing; + } + private void LoadAdvancedSettings() + { + FolderTextBox.Text = Settings.Default.GTAFolder; + ExcludeFoldersTextBox.Text = Settings.Default.ExcludeFolders; + ShadowCascadesUpDown.Value = Settings.Default.ShadowCascades; + CacheSizeUpDown.Value = Math.Min(Math.Max(Settings.Default.CacheSize / 1048576, CacheSizeUpDown.Minimum), CacheSizeUpDown.Maximum); + CacheTimeUpDown.Value = Math.Min(Math.Max((decimal)Settings.Default.CacheTime, CacheTimeUpDown.Minimum), CacheTimeUpDown.Maximum); + GPUCacheTimeUpDown.Value = Math.Min(Math.Max((decimal)Settings.Default.GPUCacheTime, GPUCacheTimeUpDown.Minimum), GPUCacheTimeUpDown.Maximum); + GPUFlushTimeUpDown.Value = Math.Min(Math.Max((decimal)Settings.Default.GPUCacheFlushTime, GPUFlushTimeUpDown.Minimum), GPUFlushTimeUpDown.Maximum); + GeometryCacheSizeUpDown.Value = Math.Min(Math.Max(Settings.Default.GPUGeometryCacheSize / 1048576, GeometryCacheSizeUpDown.Minimum), GeometryCacheSizeUpDown.Maximum); + TextureCacheSizeUpDown.Value = Math.Min(Math.Max(Settings.Default.GPUTextureCacheSize / 1048576, TextureCacheSizeUpDown.Minimum), TextureCacheSizeUpDown.Maximum); + CollisionCacheSizeUpDown.Value = Math.Min(Math.Max(Settings.Default.GPUBoundCompCacheSize / 1048576, CollisionCacheSizeUpDown.Minimum), CollisionCacheSizeUpDown.Maximum); + } + + + private void AddKeyBinding(string text, Keys key) + { + var lvi = KeyBindingsListView.Items.Add(text); + lvi.SubItems.Add(key.ToString()); + lvi.Tag = key; + } + + + public void SelectTab(string tab) + { + switch (tab) + { + case "Controls": + MainTabControl.SelectedTab = ControlsTabPage; + break; + case "Advanced": + MainTabControl.SelectedTab = AdvancedTabPage; + break; + } + + } + + + private void UpdateKeyBindingsListViewItem(string item, Keys val) + { + foreach (ListViewItem lvi in KeyBindingsListView.Items) + { + if (lvi.Text == item) + { + lvi.SubItems[1].Text = val.ToString(); + lvi.Tag = val; + break; + } + } + } + + + private void KeyBindingsListView_SelectedIndexChanged(object sender, EventArgs e) + { + var sel = (KeyBindingsListView.SelectedItems.Count == 1) ? KeyBindingsListView.SelectedItems[0] : null; + if (sel != null) + { + selKeyBinding = sel.Text; + selKeyBindingVal = (Keys)sel.Tag; + KeyBindingNameLabel.Text = selKeyBinding; + KeyBindingComboBox.SelectedItem = sel.Tag; + KeyBindingComboBox.Enabled = true; + KeyBindButton.Enabled = true; + } + else + { + selKeyBinding = string.Empty; + selKeyBindingVal = Keys.None; + KeyBindingNameLabel.Text = "(No binding selected)"; + KeyBindingComboBox.SelectedItem = null; + KeyBindingComboBox.Enabled = false; + KeyBindButton.Enabled = false; + } + } + + private void KeyBindingComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (!string.IsNullOrEmpty(selKeyBinding)) + { + Keys val = (Keys)KeyBindingComboBox.SelectedItem; + if (val != selKeyBindingVal) + { + selKeyBindingVal = val; + keyBindings.SetBinding(selKeyBinding, val); + UpdateKeyBindingsListViewItem(selKeyBinding, val); + + Settings.Default.KeyBindings = keyBindings.GetSetting(); + if (worldForm != null) + { + worldForm.SetKeyBindings(keyBindings); + } + } + } + } + + private void KeyBindButton_Click(object sender, EventArgs e) + { + KeyBindForm f = new KeyBindForm(); + f.SelectedKey = selKeyBindingVal; + if (f.ShowDialog() == DialogResult.OK) + { + var val = f.SelectedKey; + selKeyBindingVal = val; + KeyBindingComboBox.SelectedItem = val; + keyBindings.SetBinding(selKeyBinding, val); + UpdateKeyBindingsListViewItem(selKeyBinding, val); + + Settings.Default.KeyBindings = keyBindings.GetSetting(); + if (worldForm != null) + { + worldForm.SetKeyBindings(keyBindings); + } + } + } + + private void CameraSensitivityUpDown_ValueChanged(object sender, EventArgs e) + { + camSensitivity = (float)CameraSensitivityUpDown.Value * 0.001f; + Settings.Default.CameraSensitivity = camSensitivity; + if (worldForm != null) + { + worldForm.SetCameraSensitivity(camSensitivity, camSmoothing); + } + } + + private void CameraSmoothingUpDown_ValueChanged(object sender, EventArgs e) + { + camSmoothing = (float)CameraSmoothingUpDown.Value; + Settings.Default.CameraSmoothing = camSmoothing; + if (worldForm != null) + { + worldForm.SetCameraSensitivity(camSensitivity, camSmoothing); + } + } + + private void SaveButton_Click(object sender, EventArgs e) + { + //apply and save the settings. + + Settings.Default.KeyBindings = keyBindings.GetSetting(); + Settings.Default.CameraSensitivity = camSensitivity; + Settings.Default.CameraSmoothing = camSmoothing; + Settings.Default.Save(); + + DoneButton.Text = "Done"; + } + + private void DoneButton_Click(object sender, EventArgs e) + { + Close(); + } + + private void ResetButton_Click(object sender, EventArgs e) + { + if (MessageBox.Show("Are you sure you want to reset all CodeWalker settings to their default values?", "Confirm reset settings to defaults", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + var k = Settings.Default.Key; + Settings.Default.Reset(); + Settings.Default.Key = k; + Settings.Default.Save(); + + KeyBindingsListView.SelectedItems.Clear(); + + keyBindings = new KeyBindings(Settings.Default.KeyBindings); + LoadKeyBindings(); + + camSensitivity = Settings.Default.CameraSensitivity; + camSmoothing = Settings.Default.CameraSmoothing; + LoadMouseSettings(); + + + LoadAdvancedSettings(); + + + if (worldForm != null) + { + worldForm.SetKeyBindings(keyBindings); + worldForm.SetCameraSensitivity(camSensitivity, camSmoothing); + } + + } + } + + private void SettingsForm_FormClosed(object sender, FormClosedEventArgs e) + { + if (worldForm != null) + { + worldForm.OnSettingsFormClosed(); + } + } + + + + private void FolderTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.GTAFolder = FolderTextBox.Text; + } + + private void FolderBrowseButton_Click(object sender, EventArgs e) + { + FolderBrowserDialog.SelectedPath = Settings.Default.GTAFolder; + DialogResult res = FolderBrowserDialog.ShowDialog(); + if (res == DialogResult.OK) + { + FolderTextBox.Text = FolderBrowserDialog.SelectedPath; + } + } + + private void ExcludeFoldersTextBox_TextChanged(object sender, EventArgs e) + { + Settings.Default.ExcludeFolders = ExcludeFoldersTextBox.Text; + } + + private void ShadowCascadesUpDown_ValueChanged(object sender, EventArgs e) + { + Settings.Default.ShadowCascades = (int)ShadowCascadesUpDown.Value; + } + + private void CacheTimeUpDown_ValueChanged(object sender, EventArgs e) + { + Settings.Default.CacheTime = (double)CacheTimeUpDown.Value; + } + + private void CacheSizeUpDown_ValueChanged(object sender, EventArgs e) + { + Settings.Default.CacheSize = (long)CacheSizeUpDown.Value * 1048576; + } + + private void GPUCacheTimeUpDown_ValueChanged(object sender, EventArgs e) + { + Settings.Default.GPUCacheTime = (double)GPUCacheTimeUpDown.Value; + } + + private void GPUFlushTimeUpDown_ValueChanged(object sender, EventArgs e) + { + Settings.Default.GPUCacheFlushTime = (double)GPUFlushTimeUpDown.Value; + } + + private void GeometryCacheSizeUpDown_ValueChanged(object sender, EventArgs e) + { + Settings.Default.GPUGeometryCacheSize = (long)GeometryCacheSizeUpDown.Value * 1048576; + } + + private void TextureCacheSizeUpDown_ValueChanged(object sender, EventArgs e) + { + Settings.Default.GPUTextureCacheSize = (long)TextureCacheSizeUpDown.Value * 1048576; + } + + private void CollisionCacheSizeUpDown_ValueChanged(object sender, EventArgs e) + { + Settings.Default.GPUBoundCompCacheSize = (long)CollisionCacheSizeUpDown.Value * 1048576; + } + } +} diff --git a/SettingsForm.resx b/SettingsForm.resx new file mode 100644 index 0000000..bd12579 --- /dev/null +++ b/SettingsForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/Shaders/BasicPS.cso b/Shaders/BasicPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..c9d9284507cb585fbcd16e9966a18ba3adbfd1e9 GIT binary patch literal 10240 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 literal 0 HcmV?d00001 diff --git a/Shaders/BasicPS.hlsl b/Shaders/BasicPS.hlsl new file mode 100644 index 0000000..f55adfd --- /dev/null +++ b/Shaders/BasicPS.hlsl @@ -0,0 +1,528 @@ +#include "Shadowmap.hlsli" + +Texture2D Colourmap : register(t0); +Texture2D Bumpmap : register(t2); +Texture2D Specmap : register(t3); +Texture2D Detailmap : register(t4); +SamplerState TextureSS : register(s0); + + +cbuffer PSSceneVars : register(b0) +{ + ShaderGlobalLightParams GlobalLights; + uint EnableShadows; + uint RenderMode;//0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct + uint RenderModeIndex; + uint RenderSamplerCoord; +} +cbuffer PSGeomVars : register(b2) +{ + uint EnableTexture; + uint EnableTint; + uint EnableNormalMap; + uint EnableSpecMap; + uint EnableDetailMap; + uint IsDecal; + uint IsEmissive; + uint IsDistMap; + float bumpiness; + float AlphaScale; + float HardAlphaBlend; + float useTessellation; + float4 detailSettings; + float3 specMapIntMask; + float specularIntensityMult; + float specularFalloffMult; + float specularFresnel; + float wetnessMultiplier; + uint SpecOnly; +} + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float4 Shadows : TEXCOORD3; + float4 LightShadow : TEXCOORD4; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float4 Tint : COLOR2; + float4 Tangent : TEXCOORD5; + float4 Bitangent : TEXCOORD6; + float3 CamRelPos : TEXCOORD7; +}; + + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + float4 c = float4(0.5, 0.5, 0.5, 1); + if (RenderMode == 0) c = float4(1, 1, 1, 1); + if (EnableTexture == 1) + { + float2 texc = input.Texcoord0; + if (RenderMode >= 5) + { + if (RenderSamplerCoord == 2) texc = input.Texcoord1; + else if (RenderSamplerCoord == 3) texc = input.Texcoord2; + } + + c = Colourmap.Sample(TextureSS, texc); + + if (IsDistMap) c = float4(c.rgb*2, (c.r+c.g+c.b) - 1); + if ((IsDecal == 0) && (c.a <= 0.33)) discard; + if ((IsDecal == 1) && (c.a <= 0.0)) discard; + if(IsDecal==0) c.a = 1; + c.a = saturate(c.a*AlphaScale); + } + if (EnableTint > 0) + { + c.rgb *= input.Tint.rgb; + } + if (IsDecal == 1) + { + c.a *= input.Colour0.a; + } + + float3 norm = normalize(input.Normal); + + if (RenderMode == 1) //normals + { + c.rgb = norm*0.5+0.5; + } + else if (RenderMode == 2) //tangents + { + c.rgb = normalize(input.Tangent.rgb)*0.5+0.5; + } + else if (RenderMode == 3) //colours + { + c.rgb = input.Colour0.rgb; + if (RenderModeIndex == 2) c.rgb = input.Colour1.rgb; + } + else if (RenderMode == 4) //texcoords + { + c.rgb = float3(input.Texcoord0, 0); + if (RenderModeIndex == 2) c.rgb = float3(input.Texcoord1, 0); + if (RenderModeIndex == 3) c.rgb = float3(input.Texcoord2, 0); + } + + + float3 spec = 0; + + if (RenderMode == 0) + { + + float4 nv = Bumpmap.Sample(TextureSS, input.Texcoord0); //sample r1.xyzw, v2.xyxx, t3.xyzw, s3 (BumpSampler) + float4 sv = Specmap.Sample(TextureSS, input.Texcoord0); //sample r2.xyzw, v2.xyxx, t4.xyzw, s4 (SpecSampler) + + + float2 nmv = nv.xy; + float4 r0 = 0, r1, r2, r3; + + if (EnableNormalMap) + { + if (EnableDetailMap) + { + //detail normalmapp + r0.xy = input.Texcoord0 * detailSettings.zw; //mul r0.xy, v2.xyxx, detailSettings.zwzz + r0.zw = r0.xy * 3.17; //mul r0.zw, r0.xxxy, l(0.000000, 0.000000, 3.170000, 3.170000) + r0.xy = Detailmap.Sample(TextureSS, r0.xy).xy - 0.5; //sample r1.xyzw, r0.xyxx, t2.xyzw, s2 (DetailSampler) //mad r0.xy, r1.xyxx, l(2.000000, 2.000000, 0.000000, 0.000000), l(-1.000000, -1.000000, 0.000000, 0.000000) + r0.zw = Detailmap.Sample(TextureSS, r0.zw).xy - 0.5; //sample r1.xyzw, r0.zwzz, t2.xyzw, s2 (DetailSampler) //mad r0.zw, r1.xxxy, l(0.000000, 0.000000, 2.000000, 2.000000), l(0.000000, 0.000000, -1.000000, -1.000000) //r0.zw = r0.zw*0.5; //mul r0.zw, r0.zzzw, l(0.000000, 0.000000, 0.500000, 0.500000) + r0.xy = r0.xy + r0.zw; //mad r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000), r0.zwzz + r0.yz = r0.xy * detailSettings.y; //mul r0.yz, r0.xxyx, detailSettings.yyyy + //r0.x = -r0.x*detailSettings.x; //mul r0.x, -r0.x, detailSettings.x + nmv = r0.yz*sv.w + nv.xy; //mad r0.yz, r0.yyzy, r2.wwww, r1.xxyx //add detail to normal, using specmap(!) + } + + norm = NormalMap(nmv, bumpiness, input.Normal.xyz, input.Tangent.xyz, input.Bitangent.xyz); + + + } + + + + if (EnableSpecMap == 0) + { + sv = float4(0.1,0.1,0.1,0.1); + } + + float r1y = norm.z - 0.35; ////r1.y = r0.w*r1.x - 0.35; //mad r1.y, r0.w, r1.x, l(-0.350000) + + float3 globalScalars = float3(0.5, 0.5, 0.5); + float globalScalars2z = 1;// 0.65; //wet darkness? + float wetness = 0;// 10.0; + + r0.x = 0;// .5; + + r0.z = 1 - globalScalars2z; //add r0.z, -globalScalars2.z, l(1.000000) + r0.y = saturate(r1y*1.538462); //mul_sat r0.y, r1.y, l(1.538462) + r0.y = r0.y * wetness; //mul r0.y, r0.y, gDynamicBakesAndWetness.z + r0.y = r0.y * r0.z; //mul r0.y, r0.z, r0.y + r1.yz = input.Colour0.xy * globalScalars.zy; //mul r1.yz, v1.xxyx, globalScalars.zzyz //vertex.colour0 + r0.y = r0.y * r1.y; //mul r0.y, r0.y, r1.y + r0.x = r0.x * sv.w + 1.0; //mad r0.x, r0.x, r2.w, l(1.000000) + sv.xy = sv.xy*sv.xy; //mul r2.xy, r2.xyxx, r2.xyxx + r0.z = sv.w * specularFalloffMult; //mul r0.z, r2.w, specularFalloffMult + r3.y = r0.z * 0.001953125; //mul r3.y, r0.z, l(0.001953) (1/512) + r0.z = dot(sv.xyz, specMapIntMask); //dp3 r0.z, r2.xyzx, specMapIntMask.xyzx + r0.z = r0.z*specularIntensityMult; //mul r0.z, r0.z, specularIntensityMult + r3.x = r0.x * r0.z; //mul r3.x, r0.x, r0.z + r0.z = saturate(r0.z*r0.x + 0.4); //mad_sat r0.z, r0.z, r0.x, l(0.400000) + //sv.xy = r0.z*float2(0.5, 0.488281); //mul r2.xy, r0.zzzz, l(0.500000, 0.488281, 0.000000, 0.000000) + r0.z = 1 - r3.x*0.5; //mad r0.z, -r3.x, l(0.500000), l(1.000000) + r0.z = r0.z * r0.y; //mul r0.z, r0.z, r0.y + r0.y = r0.y * wetnessMultiplier; //mul r0.y, r0.y, wetnessMultiplier + r0.z = 1 - r0.z*0.5; //mad r0.z, r0.z, l(-0.500000), l(1.000000) + + float3 tc = c.rgb * r0.x; + c.rgb = tc * r0.z; //diffuse factors... + + float3 incident = normalize(input.CamRelPos); + float3 refl = normalize(reflect(incident, norm)); + float specb = saturate(dot(refl, GlobalLights.LightDir)); + float specp = max(exp(specb * 10) - 1, 0); + spec += GlobalLights.LightDirColour.rgb * 0.00006 * specp * r0.z * sv.x * specularIntensityMult;// ((specularIntensityMult != 0) ? 1 : 0); + + if (SpecOnly == 1) + { + c.a *= (EnableSpecMap == 0) ? nv.a : saturate(specp); + } + + } + + + float4 fc = c; + + c.rgb = FullLighting(c.rgb, spec, norm, input.Colour0, GlobalLights, EnableShadows, input.Shadows.x, input.LightShadow); + + + if (IsEmissive==1) + { + c.rgb += fc.rgb; + } + else + { + } + + //c.rgb = max(c.rgb, 0); + c.a = saturate(c.a); + return c; +} + + + + + +//normal_spec_detail.fxc_PS_DeferredTextured + +//mul r0.xy, v2.xyxx, detailSettings.zwzz +//mul r0.zw, r0.xxxy, l(0.000000, 0.000000, 3.170000, 3.170000) +//sample r1.xyzw, r0.xyxx, t2.xyzw, s2 (DetailSampler) +//mad r0.xy, r1.xyxx, l(2.000000, 2.000000, 0.000000, 0.000000), l(-1.000000, -1.000000, 0.000000, 0.000000) +//sample r1.xyzw, r0.zwzz, t2.xyzw, s2 (DetailSampler) +//mad r0.zw, r1.xxxy, l(0.000000, 0.000000, 2.000000, 2.000000), l(0.000000, 0.000000, -1.000000, -1.000000) +//mul r0.zw, r0.zzzw, l(0.000000, 0.000000, 0.500000, 0.500000) +//mad r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000), r0.zwzz +//mul r0.yz, r0.xxyx, detailSettings.yyyy +//mul r0.x, -r0.x, detailSettings.x +//sample r1.xyzw, v2.xyxx, t3.xyzw, s3 (BumpSampler) +//sample r2.xyzw, v2.xyxx, t4.xyzw, s4 (SpecSampler) +//mad r0.yz, r0.yyzy, r2.wwww, r1.xxyx +//mad r0.yz, r0.yyzy, l(0.000000, 2.000000, 2.000000, 0.000000), l(0.000000, -1.000000, -1.000000, 0.000000) +//max r0.w, bumpiness, l(0.001000) +//mul r1.xy, r0.wwww, r0.yzyy +//dp2 r0.y, r0.yzyy, r0.yzyy +//add r0.y, -r0.y, l(1.000000) +//sqrt r0.y, |r0.y| +//mul r1.yzw, r1.yyyy, v5.xxyz +//mad r1.xyz, r1.xxxx, v4.xyzx, r1.yzwy +//mad r0.yzw, r0.yyyy, v3.xxyz, r1.xxyz +//dp3 r1.x, r0.yzwy, r0.yzwy +//rsq r1.x, r1.x +//mad r1.y, r0.w, r1.x, l(-0.350000) +//mul r0.yzw, r0.yyzw, r1.xxxx +//mad o1.xyz, r0.yzwy, l(0.500000, 0.500000, 0.500000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) + +//add r0.z, -globalScalars2.z, l(1.000000) +//mul_sat r0.y, r1.y, l(1.538462) +//mul r0.y, r0.y, gDynamicBakesAndWetness.z +//mul r0.y, r0.z, r0.y +//mul r1.yz, v1.xxyx, globalScalars.zzyz +//mul r0.y, r0.y, r1.y +//mad r0.x, r0.x, r2.w, l(1.000000) +//mul r2.xy, r2.xyxx, r2.xyxx +//mul r0.z, r2.w, specularFalloffMult +//mul r3.y, r0.z, l(0.001953) +//dp3 r0.z, r2.xyzx, specMapIntMask.xyzx +//mul r0.z, r0.z, specularIntensityMult +//mul r3.x, r0.x, r0.z +//mad_sat r0.z, r0.z, r0.x, l(0.400000) +//mul r2.xy, r0.zzzz, l(0.500000, 0.488281, 0.000000, 0.000000) +//mad r0.z, -r3.x, l(0.500000), l(1.000000) +//mul r0.z, r0.z, r0.y +//mul r0.y, r0.y, wetnessMultiplier +//mad r0.z, r0.z, l(-0.500000), l(1.000000) + +//sample r4.xyzw, v2.xyxx, t0.xyzw, s0 //DiffuseSampler +//mul r4.xyzw, r0.xxxx, r4.xyzw +//mul o0.xyz, r0.zzzz, r4.xyzx +//mul r0.x, r4.w, v1.w +//mul o0.w, r0.x, globalScalars.x + +//add r0.x, wetnessMultiplier, l(-0.200000) +//mul_sat r0.x, r0.x, l(10.000000) +//mad_sat r0.z, v3.z, l(128.000000), l(-127.000000) +//mul o1.w, r0.x, r0.z +//mov r2.z, l(0.970000) +//mov r3.z, specularFresnel +//add r0.xzw, r2.xxyz, -r3.xxyz +//max r0.xzw, r0.xxzw, l(0.000000, 0.000000, 0.000000, 0.000000) +//mad r0.xyz, r0.xzwx, r0.yyyy, r3.xyzx +//sqrt o2.xy, r0.xyxx +//mov o2.z, r0.z +//mov o2.w, l(1.000000) + +//mad r1.x, v1.x, globalScalars.z, gLightArtificialIntAmbient0.w +//mul r0.xy, r1.xzxx, l(0.500000, 0.500000, 0.000000, 0.000000) +//sqrt o3.xy, r0.xyxx +//mov o3.zw, l(0,0,0,1.001884) + + + + + + + + + + + + + + + + + + + +/* +//normal_spec.fxc_PS_DeferredTextured +// + +max r0.x, bumpiness, l(0.001000) //cb12[1].w +sample r1.xyzw, v2.xyxx, BumpSampler.xyzw, s2 +mad r0.yz, r1.xxyx, l(0.000000, 2.000000, 2.000000, 0.000000), l(0.000000, -1.000000, -1.000000, 0.000000) +mul r0.xw, r0.xxxx, r0.yyyz +dp2 r0.y, r0.yzyy, r0.yzyy +add r0.y, -r0.y, l(1.000000) +sqrt r0.y, |r0.y| +mul r1.xyz, r0.wwww, v5.xyzx +mad r0.xzw, r0.xxxx, v4.xxyz, r1.xxyz +mad r0.xyz, r0.yyyy, v3.xyzx, r0.xzwx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mad r1.x, r0.z, r0.w, l(-0.350000) +mul r0.xyz, r0.wwww, r0.xyzx +mad o1.xyz, r0.xyzx, l(0.500000, 0.500000, 0.500000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) + +mul_sat r0.x, r1.x, l(1.538462) +mul r0.x, r0.x, gDynamicBakesAndWetness.z //cb5[3].z +add r0.y, -globalScalars2.z, l(1.000000) //cb2[12].z +mul r0.x, r0.y, r0.x +mul r1.yz, v1.xxyx, globalScalars.zzyz //vertex.colour0, cb2[11].zzyz +mul r0.x, r0.x, r1.y + +sample r2.xyzw, v2.xyxx, SpecSampler.xyzw, s3 +mul r2.xy, r2.xyxx, r2.xyxx +mul r0.y, r2.w, specularFalloffMult //cb12[0].y +mul r3.y, r0.y, l(0.001953) +dp3 r0.y, r2.xyzx, specMapIntMask.xyzx //cb12[1].xyzx +mul r3.x, r0.y, specularIntensityMult //cb12[0].z +mad_sat r0.y, r0.y, specularIntensityMult, l(0.400000) //cb12[0].z +mul r2.xy, r0.yyyy, l(0.500000, 0.488281, 0.000000, 0.000000) +mad r0.y, -r3.x, l(0.500000), l(1.000000) +mul r0.y, r0.y, r0.x +mul r0.x, r0.x, wetnessMultiplier; //cb12[2].x +mad r0.y, r0.y, l(-0.500000), l(1.000000) +sample r4.xyzw, v2.xyxx, DiffuseSampler.xyzw, s0 +mul o0.xyz, r0.yyyy, r4.xyzx +mul r0.y, r4.w, v1.w //vertex.colour0 +mul o0.w, r0.y, globalScalars.x //cb2[11].x + +add r0.y, wetnessMultiplier, l(-0.200000) //cb12[2].x +mul_sat r0.y, r0.y, l(10.000000) +mad_sat r0.z, v3.z, l(128.000000), l(-127.000000) +mul o1.w, r0.y, r0.z + +mov r2.z, l(0.970000) +mov r3.z, specularFresnel //cb12[0].x +add r0.yzw, r2.xxyz, -r3.xxyz +max r0.yzw, r0.yyzw, l(0.000000, 0.000000, 0.000000, 0.000000) +mad r0.xyz, r0.yzwy, r0.xxxx, r3.xyzx +sqrt o2.xy, r0.xyxx +mov o2.z, r0.z +mov o2.w, l(1.000000) + +mad r1.x, v1.x, globalScalars.z, gLightArtificialIntAmbient0.w //vertex.colour0, cb2[11].z, cb3[45].w +mul r0.xy, r1.xzxx, l(0.500000, 0.500000, 0.000000, 0.000000) +sqrt o3.xy, r0.xyxx +mov o3.zw, l(0,0,0,1.001884) + +ret +// Approximately 54 instruction slots used + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// DiffuseSampler sampler NA NA s0 1 +// BumpSampler sampler NA NA s2 1 +// SpecSampler sampler NA NA s3 1 +// DiffuseSampler texture float4 2d t0 1 +// BumpSampler texture float4 2d t2 1 +// SpecSampler texture float4 2d t3 1 +// misc_globals cbuffer NA NA cb2 1 +// lighting_globals cbuffer NA NA cb3 1 +// more_stuff cbuffer NA NA cb5 1 +// megashader_locals cbuffer NA NA cb12 1 +// +// +// Buffer Definitions: +// +// cbuffer misc_globals +// { +// +// float4 globalFade; // Offset: 0 Size: 16 [unused] +// float globalHeightScale; // Offset: 16 Size: 4 [unused] +// float4 g_Rage_Tessellation_CameraPosition;// Offset: 32 Size: 16 [unused] +// float4 g_Rage_Tessellation_CameraZAxis;// Offset: 48 Size: 16 [unused] +// float4 g_Rage_Tessellation_ScreenSpaceErrorParams;// Offset: 64 Size: 16 [unused] +// float4 g_Rage_Tessellation_LinearScale;// Offset: 80 Size: 16 [unused] +// float4 g_Rage_Tessellation_Frustum[4];// Offset: 96 Size: 64 [unused] +// float4 g_Rage_Tessellation_Epsilons;// Offset: 160 Size: 16 [unused] +// float4 globalScalars; // Offset: 176 Size: 16 +// float4 globalScalars2; // Offset: 192 Size: 16 +// float4 globalScalars3; // Offset: 208 Size: 16 [unused] +// float4 globalScreenSize; // Offset: 224 Size: 16 [unused] +// uint4 gTargetAAParams; // Offset: 240 Size: 16 [unused] +// float4 colorize; // Offset: 256 Size: 16 [unused] +// float4 gGlobalParticleShadowBias; // Offset: 272 Size: 16 [unused] +// float gGlobalParticleDofAlphaScale;// Offset: 288 Size: 4 [unused] +// float gGlobalFogIntensity; // Offset: 292 Size: 4 [unused] +// float4 gPlayerLFootPos; // Offset: 304 Size: 16 [unused] +// float4 gPlayerRFootPos; // Offset: 320 Size: 16 [unused] +// +// } +// +// cbuffer lighting_globals +// { +// +// float4 gDirectionalLight; // Offset: 0 Size: 16 [unused] +// float4 gDirectionalColour; // Offset: 16 Size: 16 [unused] +// int gNumForwardLights; // Offset: 32 Size: 4 [unused] +// float4 gLightPositionAndInvDistSqr[8];// Offset: 48 Size: 128 [unused] +// float4 gLightDirectionAndFalloffExponent[8];// Offset: 176 Size: 128 [unused] +// float4 gLightColourAndCapsuleExtent[8];// Offset: 304 Size: 128 [unused] +// float gLightConeScale[8]; // Offset: 432 Size: 116 [unused] +// float gLightConeOffset[8]; // Offset: 560 Size: 116 [unused] +// float4 gLightNaturalAmbient0; // Offset: 688 Size: 16 [unused] +// float4 gLightNaturalAmbient1; // Offset: 704 Size: 16 [unused] +// float4 gLightArtificialIntAmbient0;// Offset: 720 Size: 16 +// float4 gLightArtificialIntAmbient1;// Offset: 736 Size: 16 [unused] +// float4 gLightArtificialExtAmbient0;// Offset: 752 Size: 16 [unused] +// float4 gLightArtificialExtAmbient1;// Offset: 768 Size: 16 [unused] +// float4 gDirectionalAmbientColour; // Offset: 784 Size: 16 [unused] +// float4 globalFogParams[5]; // Offset: 800 Size: 80 [unused] +// float4 globalFogColor; // Offset: 880 Size: 16 [unused] +// float4 globalFogColorE; // Offset: 896 Size: 16 [unused] +// float4 globalFogColorN; // Offset: 912 Size: 16 [unused] +// float4 globalFogColorMoon; // Offset: 928 Size: 16 [unused] +// float4 gReflectionTweaks; // Offset: 944 Size: 16 [unused] +// +// } +// +// cbuffer more_stuff +// { +// +// float4 gEntitySelectColor[2]; // Offset: 0 Size: 32 [unused] +// float4 gAmbientOcclusionEffect; // Offset: 32 Size: 16 [unused] +// float4 gDynamicBakesAndWetness; // Offset: 48 Size: 16 +// float4 gAlphaRefVec0; // Offset: 64 Size: 16 [unused] +// float4 gAlphaRefVec1; // Offset: 80 Size: 16 [unused] +// float gAlphaTestRef; // Offset: 96 Size: 4 [unused] +// bool gTreesUseDiscard; // Offset: 100 Size: 4 [unused] +// float gReflectionMipCount; // Offset: 104 Size: 4 [unused] +// bool gUseTransparencyAA; // Offset: 108 Size: 4 [unused] +// bool gUseFogRay; // Offset: 112 Size: 4 [unused] +// +// } +// +// cbuffer megashader_locals +// { +// +// float specularFresnel; // Offset: 0 Size: 4 +// float specularFalloffMult; // Offset: 4 Size: 4 +// float specularIntensityMult; // Offset: 8 Size: 4 +// float3 specMapIntMask; // Offset: 16 Size: 12 +// float bumpiness; // Offset: 28 Size: 4 +// float wetnessMultiplier; // Offset: 32 Size: 4 +// float useTessellation; // Offset: 36 Size: 4 [unused] +// float HardAlphaBlend; // Offset: 40 Size: 4 [unused] +// +// } +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float +// COLOR 0 xyzw 1 NONE float xy w +// TEXCOORD 0 xy 2 NONE float xy +// TEXCOORD 1 xyz 3 NONE float xyz +// TEXCOORD 4 xyz 4 NONE float xyz +// TEXCOORD 5 xyz 5 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// SV_Target 1 xyzw 1 TARGET float xyzw +// SV_Target 2 xyzw 2 TARGET float xyzw +// SV_Target 3 xyzw 3 TARGET float xyzw +// +ps_4_0 +dcl_constantbuffer CB2[13], immediateIndexed +dcl_constantbuffer CB3[46], immediateIndexed +dcl_constantbuffer CB5[4], immediateIndexed +dcl_constantbuffer CB12[3], immediateIndexed +dcl_sampler s0, mode_default +dcl_sampler s2, mode_default +dcl_sampler s3, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texture2d (float,float,float,float) t2 +dcl_resource_texture2d (float,float,float,float) t3 +dcl_input_ps linear v1.xyw +dcl_input_ps linear v2.xy +dcl_input_ps linear v3.xyz +dcl_input_ps linear v4.xyz +dcl_input_ps linear v5.xyz +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xyzw +dcl_output o3.xyzw +dcl_temps 5 + +*/ + diff --git a/Shaders/BasicVS.hlsli b/Shaders/BasicVS.hlsli new file mode 100644 index 0000000..b18dd9c --- /dev/null +++ b/Shaders/BasicVS.hlsli @@ -0,0 +1,755 @@ +#include "Quaternion.hlsli" +#include "Shadowmap.hlsli" + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4 WindVector; +} +cbuffer VSEntityVars : register(b2) +{ + float4 CamRel; + float4 Orientation; + uint HasSkeleton; + uint HasTransforms; + uint TintPaletteIndex; + uint Pad1; + float3 Scale; + uint IsInstanced; +} +cbuffer VSModelVars : register(b3) +{ + float4x4 Transform; +} +cbuffer VSGeomVars : register(b4) +{ + uint EnableTint; + float TintYVal; + uint IsDecal; + uint EnableWind; + float4 WindOverrideParams; +} +cbuffer VSInstGlobals : register(b5) +{ + float4 gInstanceVars[24]; //instance rotation matrices +} +cbuffer VSInstLocals : register(b6) +{ + float3 vecBatchAabbMin; // Offset: 0 Size: 12 + float instPad0; + float3 vecBatchAabbDelta; // Offset: 16 Size: 12 + float instPad1; + float4 vecPlayerPos; // Offset: 32 Size: 16 + float2 _vecCollParams; // Offset: 48 Size: 8 + float2 instPad2; + float4 fadeAlphaDistUmTimer; // Offset: 256 Size: 16 + float4 uMovementParams; // Offset: 272 Size: 16 + float4 _fakedGrassNormal; // Offset: 288 Size: 16 [unused] + float3 gScaleRange; // Offset: 304 Size: 12 + float instPad3; + float4 gWindBendingGlobals; // Offset: 320 Size: 16 + float2 gWindBendScaleVar; // Offset: 336 Size: 8 + float gAlphaTest; // Offset: 344 Size: 4 [unused] + float gAlphaToCoverageScale; // Offset: 348 Size: 4 [unused] + float3 gLodFadeInstRange; // Offset: 352 Size: 12 [unused] + uint gUseComputeShaderOutputBuffer;// Offset: 364 Size: 4 +} + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float4 Shadows : TEXCOORD3; + float4 LightShadow : TEXCOORD4; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float4 Tint : COLOR2; + float4 Tangent : TEXCOORD5; + float4 Bitangent : TEXCOORD6; + float3 CamRelPos : TEXCOORD7; +}; + +Texture2D TintPalette : register(t0); +SamplerState TextureSS : register(s0); + + + + + +struct rage__fwGrassInstanceListDef__InstanceData //16 bytes, Key:2740378365 rage__fwGrassInstanceListDef__InstanceData//3985044770 +{ + uint PosXY_u16; // Offset: 0 + uint PosZ_u16_NormXY_u8; // Offset: 4 + uint ColorRGB_Scale_u8; // Offset: 8 + uint Ao_Pad3_u8; // Offset: 12 +}; +StructuredBuffer GrassInstances : register(t2); + + +float3 GetGrassInstancePosition(float3 ipos, float3 vc0, float3 vc1, uint iid) +{ + float3 opos = ipos; + + + float4 windBendParam = float4(gWindBendScaleVar.xy, gWindBendingGlobals.xy); + if (EnableWind == 0) + { + windBendParam = 0; + } + + + float4 r0, r1, r2, r3, r4, r5, r6, r7; + uint4 u0, u1, u2, u6; + + //r0.x = iid; //ld_structured r0.x, v5.x, l(0), t0.xxxx + //ushr r0.y, r0.x, l(16) + //and r0.y, r0.y, l(255) + //utof r0.y, r0.y + u0.y = (iid >> 16) & 255; + r0.y = (float)u0.y; + r1.y = r0.y * 0.0039215686; //mul r1.y, r0.y, l(0.003922) + //r2.x=iid //mov r2.x, v5.x + //r2.yz=1 //mov r2.yz, l(0,1.000000,1.000000,0) + u0.y = (iid >> 24); //ushr r0.y, r0.x, l(24) + u1.x = u0.x & 0xFFFF; //and r1.x, r0.x, l(0x0000ffff) + r0.x = (float)u0.y; //utof r0.x, r0.y + r1.z = r0.x * 0.0039215686; //mul r1.z, r0.x, l(0.003922) + r0.xyz = (gUseComputeShaderOutputBuffer != 0) ? float3(u1.x, r1.yz) : float3(iid, 1, 1); //movc r0.xyz, gUseComputeShaderOutputBuffer, r1.xyzx, r2.xyzx + float amo = r0.z*r0.y; //mul o4.x, r0.z, r0.y //alpha multiplier output + + r0.xyz = float3(iid, 1, 1); + + //ld_structured r1.xyzw, r0.x, l(0), t1.xyzw + rage__fwGrassInstanceListDef__InstanceData inst = GrassInstances[iid]; + u1.x = inst.PosXY_u16; + u1.y = inst.PosZ_u16_NormXY_u8; + u1.z = inst.ColorRGB_Scale_u8; + u1.w = inst.Ao_Pad3_u8; + + ////debug positioning + //float px = (float)((u1.x & 0xFFFF)); + //float py = (float)((u1.x >> 16) & 0xFFFF); + //float pz = (float)((u1.y & 0xFFFF)); + //float3 pab = float3(px, py, pz)*0.000015; + //float3 fpos = vecBatchAabbMin.xyz + vecBatchAabbDelta.xyz * pab; + //return opos + fpos - vecPlayerPos.xyz; + + + u2.w = u1.z >> 8; //ushr r2.w, r1.z, l(8) + u2.xy = u1.xy >> 16; //ushr r2.xy, r1.xyxx, l(16) + u2.yz = u2.yw & 255; //and r2.yz, r2.yywy, l(0, 255, 255, 0) + r3.y = (float)u2.x; //utof r3.y, r2.x + r2.x = (float)u2.y; //utof r2.x, r2.y + u0.w = u1.y >> 24; //ushr r0.w, r1.y, l(24) + r2.y = (float)u0.w; //utof r2.y, r0.w + r2.xy = r2.xy*0.0078431373 - 1.0; //mad r2.xy, r2.xyxx, l(0.007843, 0.007843, 0.000000, 0.000000), l(-1.000000, -1.000000, 0.000000, 0.000000) + r0.w = dot(r2.xy, r2.xy); //dp2 r0.w, r2.xyxx, r2.xyxx + r0.w = 1.0 - r0.w; //add r0.w, -r0.w, l(1.000000) + r2.z = sqrt(r0.w); //sqrt r2.z, r0.w + r0.w = r2.z*-0.018729 + 0.074261; //mad r0.w, r2.z, l(-0.018729), l(0.074261) + r0.w = r0.w*r2.z - 0.212114; //mad r0.w, r0.w, r2.z, l(-0.212114) + r0.w = r0.w*r2.z + 1.570729; //mad r0.w, r0.w, r2.z, l(1.570729) + r2.w = 1.0 - r2.z; //add r2.w, -r2.z, l(1.000000) + r2.w = sqrt(r2.w); //sqrt r2.w, r2.w + r2.xyz = -r2.z*float3(0, 0, 1) + r2.xyz; //mad r2.xyz, -r2.zzzz, l(0.000000, 0.000000, 1.000000, 0.000000), r2.xyzx + r0.w = r0.w*r2.w; //mul r0.w, r0.w, r2.w + r0.w = r0.w * vecPlayerPos.w; //mul r0.w, r0.w, vecPlayerPos.w + r5.x = sin(r0.w); //sincos r5.x, r6.x, r0.w + r6.x = cos(r0.w); + //r0.w = dot(r2.xyz, r2.xyz); //dp3 r0.w, r2.xyzx, r2.xyzx + //r0.w = 1.0 / sqrt(r0.w); //rsq r0.w, r0.w + //r2.xyz = r2.xyz*r0.w; //mul r2.xyz, r0.wwww, r2.xyzx + r2.xyz = normalize(r2.xyz); + r2.xyz = r2.xyz * r5.x; //mul r2.xyz, r5.xxxx, r2.xyzx + r2.xyz = r6.x*float3(0, 0, 1) + r2.xyz; //mad r2.xyz, r6.xxxx, l(0.000000, 0.000000, 1.000000, 0.000000), r2.xyzx + r5.xy = r2.yz*float2(1, 0); //mul r5.xy, r2.yzyy, l(1.000000, 0.000000, 0.000000, 0.000000) + r5.xy = r2.zx*float2(0, 1) - r5.xy; //mad r5.xy, r2.zxzz, l(0.000000, 1.000000, 0.000000, 0.000000), -r5.xyxx + r0.w = dot(r5.xy, r5.xy); //dp2 r0.w, r5.xyxx, r5.xyxx + r0.w = sqrt(r0.w); //sqrt r0.w, r0.w + r5.xy = r5.xy / r0.w; //div r5.xy, r5.xyxx, r0.wwww + r0.w = 1.0 - r2.z; //add r0.w, -r2.z, l(1.000000) + r2.w = r5.x*r0.w; //mul r2.w, r5.x, r0.w + r5.x = r2.w*r5.x + r2.z; //mad r5.x, r2.w, r5.x, r2.z + r5.z = r5.y*r2.w; //mul r5.z, r5.y, r2.w + r2.w = r5.y*r5.y; //mul r2.w, r5.y, r5.y + r5.w = r2.w*r0.w + r2.z; //mad r5.w, r2.w, r0.w, r2.z + u0.w = r2.z < 1.0; //lt r0.w, r2.z, l(1.000000) + r2.xyz = r2.xyz*float3(-1, -1, 1); //mul r2.xyz, r2.xyzx, l(-1.000000, -1.000000, 1.000000, 0.000000) + r2.xyz = (u0.w != 0) ? r2.xyz : float3(0, 0, 1); //movc r2.xyz, r0.wwww, r2.xyzx, l(0, 0, 1.000000, 0) + r5.xyz = (u0.w != 0) ? r5.xzw : float3(1, 0, 1); //movc r5.xyz, r0.wwww, r5.xzwx, l(1.000000, 0, 1.000000, 0) + r0.w = vc0.y * 6.283185; //mul r0.w, v2.y, l(6.283185) + r6.xyz = fadeAlphaDistUmTimer.z*uMovementParams.zzw + r0.w; //mad r6.xyz, fadeAlphaDistUmTimer.zzzz, uMovementParams.zzwz, r0.wwww + r6.xyz = sin(r6.xyz); //sincos r6.xyz, null, r6.xyzx + r0.w = 1.0 - vc0.z; //add r0.w, -v2.z, l(1.000000) + r7.z = r0.w * uMovementParams.y; //mul r7.z, r0.w, uMovementParams.y + r7.xy = vc0.x * uMovementParams.x; //mul r7.xy, v2.xxxx, uMovementParams.xxxx + r6.xyz = r6.xyz * r7.xyz; //mul r6.xyz, r6.xyzx, r7.xyzx + u0.w = u1.z >> 24; //ushr r0.w, r1.z, l(24) + r0.w = (float)u0.w; //utof r0.w, r0.w + r0.w = r0.w * 0.0039215686; //mul r0.w, r0.w, l(0.003922) + r2.w = gScaleRange.y - gScaleRange.x; //add r2.w, -gScaleRange.x, gScaleRange.y + r0.w = r2.w*r0.w + gScaleRange.x; //mad r0.w, r2.w, r0.w, gScaleRange.x + r2.w = gScaleRange.z * gScaleRange.y; //mul r2.w, gScaleRange.z, gScaleRange.y + u0.x = iid & 7; //and r0.x, r0.x, l(7) + u0.x = u0.x * 3; //imul null, r0.x, r0.x, l(3) + r2.w = dot(gInstanceVars[u0.x].ww, r2.ww); //dp2 r2.w, gInstanceVars[r0.x + 0].wwww, r2.wwww + r2.w = -gScaleRange.y * gScaleRange.z + r2.w; //mad r2.w, -gScaleRange.y, gScaleRange.z, r2.w + r0.w = r0.w + r2.w; //add r0.w, r0.w, r2.w + r0.w = max(r0.w, 0.0); //max r0.w, r0.w, l(0.000000) + r0.w = r0.w * r0.z; //mul r0.w, r0.z, r0.w //compute cull scale fadeout? + + r0.yzw = opos*r0.w + r6.xyz; //mad r0.yzw, v0.xxyz, r0.wwww, r6.xxyz //scale and offset (movement?) + r6.xyz = r0.z * gInstanceVars[u0.x + 1].xyz; //mul r6.xyz, r0.zzzz, gInstanceVars[r0.x + 1].xyzx //rotate vertex positions with instance matrix + r6.xyz = r0.y * gInstanceVars[u0.x].xyz + r6.xyz; //mad r6.xyz, r0.yyyy, gInstanceVars[r0.x + 0].xyzx, r6.xyzx + r0.yzw = r0.w * gInstanceVars[u0.x + 2].xyz + r6.xyz; //mad r0.yzw, r0.wwww, gInstanceVars[r0.x + 2].xxyz, r6.xxyz + //instance matrices!!! + + u6.xyzw = u1.xyzw & uint4(0xFFFF, 0xFFFF, 255, 255); //and r6.xyzw, r1.xyzw, l(0x0000ffff, 0x0000ffff, 255, 255) + u1.x = u1.z >> 16; //ushr r1.x, r1.z, l(16) + u1.x = u1.x & 255; //and r1.x, r1.x, l(255) + r3.xzw = (float3)u6.xyw; //utof r3.xzw, r6.xxyw + r4.z = (float)u1.x; //utof r4.z, r1.x + r4.y = (float)u2.z; //utof r4.y, r2.z + r4.x = (float)u6.z; //utof r4.x, r6.z + float3 tnt = r4.xyz * 0.0039215686; //mul o1.xyz, r4.xyzx, l(0.003922, 0.003922, 0.003922, 0.000000) ///colour tint output + float aoo = r3.w * 0.0039215686; //mul o4.y, r3.w, l(0.003922) //ambient occlusion value output + + r1.xyz = r3.xyz*vecBatchAabbDelta.xyz; //mul r1.xyz, r3.xyzx, vecBatchAabbDelta.xyzx + r1.xyz = r1.xyz/65535 + vecBatchAabbMin.xyz; //mad r1.xyz, r1.xyzx, l(0.000015, 0.000015, 0.000015, 0.000000), vecBatchAabbMin.xyzx + r1.w = dot(r1.xyz, r1.xyz); //dp3 r1.w, r1.xyzx, r1.xyzx + r1.w = cos(r1.w); //sincos null, r1.w, r1.w + r1.w = r1.w*0.5 + 0.5; //mad r1.w, r1.w, l(0.500000), l(0.500000) + r1.w = r1.w*windBendParam.y + 1.0; //gWindBendScaleVar.y + 1.0; //mad r1.w, gWindBendScaleVar.y, r1.w, l(1.000000) + r1.w = r1.w*windBendParam.x; //gWindBendScaleVar.x; //mul r1.w, r1.w, gWindBendScaleVar.x + r3.xy = r1.w*windBendParam.zw; //gWindBendingGlobals.xy; //mul r3.xy, r1.wwww, gWindBendingGlobals.xyxx + r5.w = r3.x; //mov r5.w, r3.x + r4.x = dot(r0.yzw, r5.xyw); //dp3 r4.x, r0.yzwy, r5.xywx + r3.zw = r5.yz; //mov r3.zw, r5.yyyz + r4.y = dot(r0.wyz, r3.yzw); //dp3 r4.y, r0.wyzw, r3.yzwy + r4.z = dot(r0.yzw, r2.xyz); //dp3 r4.z, r0.yzwy, r2.xyzx + r0.yzw = r1.xyz + r4.xyz; //add r0.yzw, r1.xxyz, r4.xxyz //add vertex position to instance position + + r1.yzw = r0.yzw - (vecPlayerPos.xyz - float3(0,0,-0.2)); //add r1.yzw, r0.yyzw, -vecPlayerPos.xxyz + r1.w = dot(r1.yzw, r1.yzw); //dp3 r1.w, r1.yzwy, r1.yzwy + r2.w = 1.0 / sqrt(r1.w); //rsq r2.w, r1.w + r1.w = _vecCollParams.x - r1.w; //add r1.w, -r1.w, _vecCollParams.x + r1.w = saturate(_vecCollParams.y * r1.w); //mul_sat r1.w, r1.w, _vecCollParams.y + r1.w = r1.w * 0.5; //mul r1.w, r1.w, l(0.500000) + r1.yz = r1.yz * r2.w; //mul r1.yz, r1.yyzy, r2.wwww + r1.yz = r1.yz * r1.w; //mul r1.yz, r1.yyzy, r1.wwww + r0.yz = r1.yz * vc1.z + r0.yz; //mad r0.yz, r1.yyzy, v3.zzzz, r0.yyzy //contribute player collision + + + //float3 fpos = r0.yzw; + return r0.yzw - vecPlayerPos.xyz; + + + //return CamRel.xyz + opos; +} + + +float3 ModelTransform(float3 ipos, float3 vc0, float3 vc1, uint iid) +{ + if (IsInstanced) + { + return GetGrassInstancePosition(ipos, vc0, vc1, iid); + } + else + { + float3 tpos = (HasTransforms == 1) ? mul(float4(ipos, 1), Transform).xyz : ipos; + float3 spos = tpos * Scale; + float3 bpos = mulvq(spos, Orientation); + if (EnableWind) + { + bpos = GeomWindMotion(bpos, vc0, WindVector, WindOverrideParams); + } + return CamRel.xyz + bpos; + } +} +float4 ScreenTransform(float3 opos) +{ + float4 pos = float4(opos, 1); + float4 cpos = mul(pos, ViewProj); + //if (IsDecal == 1) + //{ + // //cpos.z -= 0.003; //todo: correct decal z-bias + //} + cpos.z = DepthFunc(cpos.zw); + return cpos; +} +float3 NormalTransform(float3 inorm) +{ + float3 tnorm = (HasTransforms == 1) ? mul(inorm, (float3x3)Transform) : inorm; + float3 bnorm = normalize(mulvq(tnorm, Orientation)); + return bnorm; +} + +float4 ColourTint(float tx, float tx2, uint iid) +{ + float4 tnt = 1; + if (IsInstanced) + { + //RenderableGrassInstance inst = GrassInstances[iid]; + //tnt = Unpack4x8UNF(inst.Colour); + rage__fwGrassInstanceListDef__InstanceData inst = GrassInstances[iid]; + uint c = inst.ColorRGB_Scale_u8; + float3 rgb = float3(c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF); + tnt = float4(rgb * 0.003922, 1); + } + else if (EnableTint > 0) + { + float tu = (EnableTint == 1) ? tx : tx2; + tnt = TintPalette.SampleLevel(TextureSS, float2(tu, TintYVal), 0); + } + return tnt; +} + + + + + + + + + + + + + + + + + + + + + + + + + +//grass_batch.fxc_VS_Transform +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer rage_matrices +// { +// +// row_major float4x4 gWorld; // Offset: 0 Size: 64 [unused] +// row_major float4x4 gWorldView; // Offset: 64 Size: 64 [unused] +// row_major float4x4 gWorldViewProj; // Offset: 128 Size: 64 +// row_major float4x4 gViewInverse; // Offset: 192 Size: 64 [unused] +// +// } +// +// cbuffer grassglobals +// { +// +// bool bVehColl0Enabled; // Offset: 0 Size: 4 +// bool bVehColl1Enabled; // Offset: 4 Size: 4 +// bool bVehColl2Enabled; // Offset: 8 Size: 4 +// bool bVehColl3Enabled; // Offset: 12 Size: 4 +// float4 depthValueBias; // Offset: 16 Size: 16 [unused] +// +// } +// +// cbuffer grassbatchlocals +// { +// +// float3 vecBatchAabbMin; // Offset: 0 Size: 12 +// float3 vecBatchAabbDelta; // Offset: 16 Size: 12 +// float4 vecPlayerPos; // Offset: 32 Size: 16 +// float2 _vecCollParams; // Offset: 48 Size: 8 +// float4 _vecVehColl0B; // Offset: 64 Size: 16 +// float4 _vecVehColl0M; // Offset: 80 Size: 16 +// float4 _vecVehColl0R; // Offset: 96 Size: 16 +// float4 _vecVehColl1B; // Offset: 112 Size: 16 +// float4 _vecVehColl1M; // Offset: 128 Size: 16 +// float4 _vecVehColl1R; // Offset: 144 Size: 16 +// float4 _vecVehColl2B; // Offset: 160 Size: 16 +// float4 _vecVehColl2M; // Offset: 176 Size: 16 +// float4 _vecVehColl2R; // Offset: 192 Size: 16 +// float4 _vecVehColl3B; // Offset: 208 Size: 16 +// float4 _vecVehColl3M; // Offset: 224 Size: 16 +// float4 _vecVehColl3R; // Offset: 240 Size: 16 +// float4 fadeAlphaDistUmTimer; // Offset: 256 Size: 16 +// float4 uMovementParams; // Offset: 272 Size: 16 +// float4 _fakedGrassNormal; // Offset: 288 Size: 16 [unused] +// float3 gScaleRange; // Offset: 304 Size: 12 +// float4 gWindBendingGlobals; // Offset: 320 Size: 16 +// float2 gWindBendScaleVar; // Offset: 336 Size: 8 +// float gAlphaTest; // Offset: 344 Size: 4 [unused] +// float gAlphaToCoverageScale; // Offset: 348 Size: 4 [unused] +// float3 gLodFadeInstRange; // Offset: 352 Size: 12 [unused] +// uint gUseComputeShaderOutputBuffer;// Offset: 364 Size: 4 +// float2 gInstCullParams; // Offset: 368 Size: 8 [unused] +// uint gNumClipPlanes; // Offset: 376 Size: 4 [unused] +// float4 gClipPlanes[16]; // Offset: 384 Size: 256 [unused] +// float3 gCameraPosition; // Offset: 640 Size: 12 [unused] +// uint gLodInstantTransition; // Offset: 652 Size: 4 [unused] +// float4 gLodThresholds; // Offset: 656 Size: 16 [unused] +// float2 gCrossFadeDistance; // Offset: 672 Size: 8 [unused] +// float2 gLodFadeStartDist; // Offset: 680 Size: 8 [unused] +// float2 gLodFadeRange; // Offset: 688 Size: 8 [unused] +// float2 gLodFadePower; // Offset: 696 Size: 8 [unused] +// float2 gLodFadeTileScale; // Offset: 704 Size: 8 [unused] +// uint gIsShadowPass; // Offset: 712 Size: 4 [unused] +// float3 gLodFadeControlRange; // Offset: 720 Size: 12 [unused] +// float4 bDebugSwitches; // Offset: 736 Size: 16 [unused] +// +// } +// +// cbuffer grassbatch_instmtx +// { +// +// float4 gInstanceVars[24]; // Offset: 0 Size: 384 +// +// } +// +// Resource bind info for InstanceBuffer +// { +// +// struct +// { +// +// uint InstId_u16_CrossFade_Scale_u8;// Offset: 0 +// +// } $Element; // Offset: 0 Size: 4 +// +// } +// +// Resource bind info for RawInstanceBuffer +// { +// +// struct +// { +// +// uint PosXY_u16; // Offset: 0 +// uint PosZ_u16_NormXY_u8; // Offset: 4 +// uint ColorRGB_Scale_u8; // Offset: 8 +// uint Ao_Pad3_u8; // Offset: 12 +// +// } $Element; // Offset: 0 Size: 16 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// InstanceBuffer texture struct r/o t0 1 +// RawInstanceBuffer texture struct r/o t1 1 +// rage_matrices cbuffer NA NA cb1 1 +// grassglobals cbuffer NA NA cb4 1 +// grassbatch_instmtx cbuffer NA NA cb7 1 +// grassbatchlocals cbuffer NA NA cb11 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyzw 0 NONE float xyz +// NORMAL 0 xyz 1 NONE float xyz +// COLOR 0 xyzw 2 NONE float xyz +// COLOR 1 xyzw 3 NONE float x z +// TEXCOORD 0 xy 4 NONE float xy +// SV_InstanceID 0 x 5 INSTID uint x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xyzw +// TEXCOORD 0 xyzw 1 NONE float xyzw +// TEXCOORD 1 xyzw 2 NONE float xyzw +// TEXCOORD 2 xyzw 3 NONE float xyzw +// TEXCOORD 5 xy 4 NONE float xy +// +/* +vs_4_0 +dcl_globalFlags refactoringAllowed | enableRawAndStructuredBuffers +dcl_constantbuffer CB1[12], immediateIndexed +dcl_constantbuffer CB4[1], immediateIndexed +dcl_constantbuffer CB11[23], immediateIndexed +dcl_constantbuffer CB7[24], dynamicIndexed +dcl_resource_structured t0, 4 +dcl_resource_structured t1, 16 +dcl_input v0.xyz +dcl_input v1.xyz +dcl_input v2.xyz +dcl_input v3.xz +dcl_input v4.xy +dcl_input_sgv v5.x, instance_id +dcl_output_siv o0.xyzw, position +dcl_output o1.xyzw +dcl_output o2.xyzw +dcl_output o3.xyzw +dcl_output o4.xy +dcl_temps 8 + +ld_structured r0.x, v5.x, l(0), t0.xxxx +ushr r0.y, r0.x, l(16) +and r0.y, r0.y, l(255) +utof r0.y, r0.y +mul r1.y, r0.y, l(0.003922) +mov r2.x, v5.x +mov r2.yz, l(0,1.000000,1.000000,0) +ushr r0.y, r0.x, l(24) +and r1.x, r0.x, l(0x0000ffff) +utof r0.x, r0.y +mul r1.z, r0.x, l(0.003922) +movc r0.xyz, gUseComputeShaderOutputBuffer, r1.xyzx, r2.xyzx +ld_structured r1.xyzw, r0.x, l(0), t1.xyzw +ushr r2.w, r1.z, l(8) +ushr r2.xy, r1.xyxx, l(16) +and r2.yz, r2.yywy, l(0, 255, 255, 0) +utof r3.y, r2.x +utof r2.x, r2.y +utof r4.y, r2.z +ushr r0.w, r1.y, l(24) +utof r2.y, r0.w +mad r2.xy, r2.xyxx, l(0.007843, 0.007843, 0.000000, 0.000000), l(-1.000000, -1.000000, 0.000000, 0.000000) +dp2 r0.w, r2.xyxx, r2.xyxx +add r0.w, -r0.w, l(1.000000) +sqrt r2.z, r0.w +mad r0.w, r2.z, l(-0.018729), l(0.074261) +mad r0.w, r0.w, r2.z, l(-0.212114) +mad r0.w, r0.w, r2.z, l(1.570729) +add r2.w, -r2.z, l(1.000000) +mad r2.xyz, -r2.zzzz, l(0.000000, 0.000000, 1.000000, 0.000000), r2.xyzx +sqrt r2.w, r2.w +mul r0.w, r0.w, r2.w +mul r0.w, r0.w, vecPlayerPos.w +sincos r5.x, r6.x, r0.w +dp3 r0.w, r2.xyzx, r2.xyzx +rsq r0.w, r0.w +mul r2.xyz, r0.wwww, r2.xyzx +mul r2.xyz, r5.xxxx, r2.xyzx +mad r2.xyz, r6.xxxx, l(0.000000, 0.000000, 1.000000, 0.000000), r2.xyzx +mul r5.xy, r2.yzyy, l(1.000000, 0.000000, 0.000000, 0.000000) +mad r5.xy, r2.zxzz, l(0.000000, 1.000000, 0.000000, 0.000000), -r5.xyxx +dp2 r0.w, r5.xyxx, r5.xyxx +sqrt r0.w, r0.w +div r5.xy, r5.xyxx, r0.wwww +add r0.w, -r2.z, l(1.000000) +mul r2.w, r5.x, r0.w +mad r5.x, r2.w, r5.x, r2.z +mul r5.z, r5.y, r2.w +mul r2.w, r5.y, r5.y +mad r5.w, r2.w, r0.w, r2.z +lt r0.w, r2.z, l(1.000000) +mul r2.xyz, r2.xyzx, l(-1.000000, -1.000000, 1.000000, 0.000000) +movc r2.xyz, r0.wwww, r2.xyzx, l(0,0,1.000000,0) +movc r5.xyz, r0.wwww, r5.xzwx, l(1.000000,0,1.000000,0) +mul r0.w, v2.y, l(6.283185) +mad r6.xyz, fadeAlphaDistUmTimer.zzzz, uMovementParams.zzwz, r0.wwww +sincos r6.xyz, null, r6.xyzx +add r0.w, -v2.z, l(1.000000) +mul r7.z, r0.w, uMovementParams.y +mul r7.xy, v2.xxxx, uMovementParams.xxxx +mul r6.xyz, r6.xyzx, r7.xyzx +ushr r0.w, r1.z, l(24) +utof r0.w, r0.w +mul r0.w, r0.w, l(0.003922) +add r2.w, -gScaleRange.x, gScaleRange.y +mad r0.w, r2.w, r0.w, gScaleRange.x +mul r2.w, gScaleRange.z, gScaleRange.y +and r0.x, r0.x, l(7) +imul null, r0.x, r0.x, l(3) +dp2 r2.w, gInstanceVars[r0.x + 0].wwww, r2.wwww +mad r2.w, -gScaleRange.y, gScaleRange.z, r2.w +add r0.w, r0.w, r2.w +max r0.w, r0.w, l(0.000000) +mul r0.w, r0.z, r0.w + +mul o4.x, r0.z, r0.y //alpha multiplier output + +mad r0.yzw, v0.xxyz, r0.wwww, r6.xxyz //scale and offset (movement?) +mul r6.xyz, r0.zzzz, gInstanceVars[r0.x + 1].xyzx //rotate vertex positions with instance matrix +mad r6.xyz, r0.yyyy, gInstanceVars[r0.x + 0].xyzx, r6.xyzx +mad r0.yzw, r0.wwww, gInstanceVars[r0.x + 2].xxyz, r6.xxyz + +and r6.xyzw, r1.xyzw, l(0x0000ffff, 0x0000ffff, 255, 255) +ushr r1.x, r1.z, l(16) +and r1.x, r1.x, l(255) +utof r4.z, r1.x +utof r3.xzw, r6.xxyw +utof r4.x, r6.z +mul o1.xyz, r4.xyzx, l(0.003922, 0.003922, 0.003922, 0.000000) ///colour tint output +mul o4.y, r3.w, l(0.003922) //ambient occlusion value output + +mul r1.xyz, r3.xyzx, vecBatchAabbDelta.xyzx +mad r1.xyz, r1.xyzx, l(0.000015, 0.000015, 0.000015, 0.000000), vecBatchAabbMin.xyzx +dp3 r1.w, r1.xyzx, r1.xyzx +sincos null, r1.w, r1.w +mad r1.w, r1.w, l(0.500000), l(0.500000) +mad r1.w, gWindBendScaleVar.y, r1.w, l(1.000000) +mul r1.w, r1.w, gWindBendScaleVar.x +mul r3.xy, r1.wwww, gWindBendingGlobals.xyxx +mov r5.w, r3.x +dp3 r4.x, r0.yzwy, r5.xywx +mov r3.zw, r5.yyyz +dp3 r4.y, r0.wyzw, r3.yzwy +dp3 r4.z, r0.yzwy, r2.xyzx +add r0.yzw, r1.xxyz, r4.xxyz //add vertex position to instance position + +add r1.yzw, r0.yyzw, -vecPlayerPos.xxyz +dp3 r1.w, r1.yzwy, r1.yzwy +rsq r2.w, r1.w +add r1.w, -r1.w, _vecCollParams.x +mul_sat r1.w, r1.w, _vecCollParams.y +mul r1.w, r1.w, l(0.500000) +mul r1.yz, r1.yyzy, r2.wwww +mul r1.yz, r1.yyzy, r1.wwww +mad r0.yz, r1.yyzy, v3.zzzz, r0.yyzy //contribute player collision + +add r1.x, -r0.w, _vecVehColl0R.w +add r1.yz, r0.yyzy, -_vecVehColl0B.xxyx +dp2 r1.y, _vecVehColl0M.xyxx, r1.yzyy +mul_sat r1.y, r1.y, _vecVehColl0M.w +mad r1.yz, r1.yyyy, _vecVehColl0M.xxyx, _vecVehColl0B.xxyx +add r1.yz, r0.yyzy, -r1.yyzy +dp2 r1.w, r1.yzyy, r1.yzyy +add r2.w, -r1.w, _vecVehColl0R.y +mul_sat r2.w, r2.w, _vecVehColl0R.z +mad r1.x, r2.w, r1.x, r0.w +mul r2.w, r2.w, _vecVehColl0R.x +mul r3.x, _vecVehColl0R.x, l(0.500000) +mul r3.x, r3.x, r3.x +lt r3.x, r1.w, r3.x +rsq r1.w, r1.w +mul r1.yz, r1.wwww, r1.yyzy +mul r1.yz, r1.yyzy, r2.wwww +mad r4.xy, r1.yzyy, v3.zzzz, r0.yzyy +add r1.y, _vecVehColl0R.w, l(-0.250000) +movc r4.z, r3.x, r1.y, r1.x +add r1.x, r0.w, -_vecVehColl0R.w +ge r1.x, l(2.000000), |r1.x| +movc r1.xyz, r1.xxxx, r4.xyzx, r0.yzwy +movc r0.yzw, bVehColl0Enabled, r1.xxyz, r0.yyzw //contribute vehicle collision 0 + +add r1.x, -r0.w, _vecVehColl1R.w +add r1.yz, r0.yyzy, -_vecVehColl1B.xxyx +dp2 r1.y, _vecVehColl1M.xyxx, r1.yzyy +mul_sat r1.y, r1.y, _vecVehColl1M.w +mad r1.yz, r1.yyyy, _vecVehColl1M.xxyx, _vecVehColl1B.xxyx +add r1.yz, r0.yyzy, -r1.yyzy +dp2 r1.w, r1.yzyy, r1.yzyy +add r2.w, -r1.w, _vecVehColl1R.y +mul_sat r2.w, r2.w, _vecVehColl1R.z +mad r1.x, r2.w, r1.x, r0.w +mul r2.w, r2.w, _vecVehColl1R.x +mul r3.x, _vecVehColl1R.x, l(0.500000) +mul r3.x, r3.x, r3.x +lt r3.x, r1.w, r3.x +rsq r1.w, r1.w +mul r1.yz, r1.wwww, r1.yyzy +mul r1.yz, r1.yyzy, r2.wwww +mad r4.xy, r1.yzyy, v3.zzzz, r0.yzyy +add r1.y, _vecVehColl1R.w, l(-0.250000) +movc r4.z, r3.x, r1.y, r1.x +add r1.x, r0.w, -_vecVehColl1R.w +ge r1.x, l(2.000000), |r1.x| +movc r1.xyz, r1.xxxx, r4.xyzx, r0.yzwy +movc r0.yzw, bVehColl1Enabled, r1.xxyz, r0.yyzw //contribute vehicle collision 1 + +add r1.x, -r0.w, _vecVehColl2R.w +add r1.yz, r0.yyzy, -_vecVehColl2B.xxyx +dp2 r1.y, _vecVehColl2M.xyxx, r1.yzyy +mul_sat r1.y, r1.y, _vecVehColl2M.w +mad r1.yz, r1.yyyy, _vecVehColl2M.xxyx, _vecVehColl2B.xxyx +add r1.yz, r0.yyzy, -r1.yyzy +dp2 r1.w, r1.yzyy, r1.yzyy +add r2.w, -r1.w, _vecVehColl2R.y +mul_sat r2.w, r2.w, _vecVehColl2R.z +mad r1.x, r2.w, r1.x, r0.w +mul r2.w, r2.w, _vecVehColl2R.x +mul r3.x, _vecVehColl2R.x, l(0.500000) +mul r3.x, r3.x, r3.x +lt r3.x, r1.w, r3.x +rsq r1.w, r1.w +mul r1.yz, r1.wwww, r1.yyzy +mul r1.yz, r1.yyzy, r2.wwww +mad r4.xy, r1.yzyy, v3.zzzz, r0.yzyy +add r1.y, _vecVehColl2R.w, l(-0.250000) +movc r4.z, r3.x, r1.y, r1.x +add r1.x, r0.w, -_vecVehColl2R.w +ge r1.x, l(2.000000), |r1.x| +movc r1.xyz, r1.xxxx, r4.xyzx, r0.yzwy +movc r0.yzw, bVehColl2Enabled, r1.xxyz, r0.yyzw //contribute vehicle collision 2 + +add r1.x, -r0.w, _vecVehColl3R.w +add r1.yz, r0.yyzy, -_vecVehColl3B.xxyx +dp2 r1.y, _vecVehColl3M.xyxx, r1.yzyy +mul_sat r1.y, r1.y, _vecVehColl3M.w +mad r1.yz, r1.yyyy, _vecVehColl3M.xxyx, _vecVehColl3B.xxyx +add r1.yz, r0.yyzy, -r1.yyzy +dp2 r1.w, r1.yzyy, r1.yzyy +add r2.w, -r1.w, _vecVehColl3R.y +mul_sat r2.w, r2.w, _vecVehColl3R.z +mad r1.x, r2.w, r1.x, r0.w +mul r2.w, r2.w, _vecVehColl3R.x +mul r3.x, _vecVehColl3R.x, l(0.500000) +mul r3.x, r3.x, r3.x +lt r3.x, r1.w, r3.x +rsq r1.w, r1.w +mul r1.yz, r1.wwww, r1.yyzy +mul r1.yz, r1.yyzy, r2.wwww +mad r4.xy, r1.yzyy, v3.zzzz, r0.yzyy +add r1.y, _vecVehColl3R.w, l(-0.250000) +movc r4.z, r3.x, r1.y, r1.x +add r1.x, r0.w, -_vecVehColl3R.w +ge r1.x, l(2.000000), |r1.x| +movc r1.xyz, r1.xxxx, r4.xyzx, r0.yzwy +movc r0.yzw, bVehColl3Enabled, r1.xxyz, r0.yyzw //contribute vehicle collision 3 + +mul r1.xyzw, r0.zzzz, gWorldViewProj[1].xyzw +mad r1.xyzw, r0.yyyy, gWorldViewProj[0].xyzw, r1.xyzw +mad r1.xyzw, r0.wwww, gWorldViewProj[2].xyzw, r1.xyzw //screen transform + +mov o3.xyz, r0.yzwy +add o0.xyzw, r1.xyzw, gWorldViewProj[3].xyzw //main position output +mov o1.w, v3.x + +mul r0.yzw, v1.yyyy, gInstanceVars[r0.x + 1].xxyz //rotate normals with instance matrix +mad r0.yzw, v1.xxxx, gInstanceVars[r0.x + 0].xxyz, r0.yyzw +mad r0.xyz, v1.zzzz, gInstanceVars[r0.x + 2].xyzx, r0.yzwy +dp3 r1.x, r0.xyzx, r5.xywx +dp3 r1.y, r0.zxyz, r3.yzwy +dp3 r1.z, r0.xyzx, r2.xyzx +dp3 r0.x, r1.xyzx, r1.xyzx +rsq r0.x, r0.x + +mul o2.xyz, r0.xxxx, r1.xyzx //lighting stuff +mov o2.w, v4.x //main texcoords +mov o3.w, v4.y + + +ret +*/ +// Approximately 224 instruction slots used + + + + + + + + + + + + + + diff --git a/Shaders/BasicVS_Box.cso b/Shaders/BasicVS_Box.cso new file mode 100644 index 0000000000000000000000000000000000000000..e71feed1d24a67cdd8d25a6bf441d36cb2947cea GIT binary patch literal 4548 zcmai1PiP!v6#sUUG@CTFu|+6SVX385C}o>Ss8!nO?qKhOQlu6t;-R32AVqrc&_fY#9+ZL}JeFDn#rpfres6cOozw^4eDC|c zzu$XrXOiM9>hX*1B*M zKZEmi;6@DRy_v(WxV+$W_kd17qgWBEV~k=aW@tRC@f>!>>&1@%{|Gp3BGUQ=?4J=} za8O<2P2y4%;GxDZ5@#Y>|B}W(CyvFQl5T4JHg?K-@gIR*Pr!cx_GJS82e7YW_&?xD zBXG=E;$QIR0DPN(?*YD^fKLFwm4KIk^A6Y|68|*-KP2F90Kb!f7p$ddq-tJ(()D49 zN2Ns8aO`smGt~!qe@tF+78b)u7;#0%heZj)xxu{WF9oXZxM2;`6NYx#ZQ84>?I9HnRA-)a@esQll-(e- z+&R0c{?d6Fz?tVQzRW>;CtLOsQc(rZcWocBISXAM1+V3;_>bo`*<7#>A!hIF5Fd+L zuE>s)9cONcm(ekIVb5Z*W;u;fQoOgqt(s&m9GJuLUL!3N`c(k-Wc@lTd?shEd z%N!GDt%<)W&cPE$**mz1h@&(eJRX;I690NUBR}}_q=VBZiGGH$M4vuM#J6G%vJQC&K9cGnW8FGE7cj)+MJr4%|O>cWztCI%#=!@pZ%o|vQe!VTh3skd&`-*vkq6e zEssX}2F|CDhCj*)?()3So5Z^IY}@yfVo_(aSocwn-g_aGnmFIK z0o$#azQ?t}whd~Qkvq#B8@ivICuEknpnG!pVz-BvVNaqx>p|Uz+jWlGp80~Jo>0#E z#CNGBu`P@QI;-;&UGdL(mYDnA@8$s?TN$4e&+qr4HU>Y@e9>NfQJ4Nn4?o=CYeamB zJZ(@*@hPiw4`9*Vv3LB*{1cnNYml`gr3^mTj^W>_%#N(iP40^KiV)>{Hj%TQl;<~* za|S5Cu!)>?M&v=siFcHl;$Dp9dxV-G)U5NHVt+|u$NTZU5cdHr!}kw!NgH@5bu7Lp zAA_8^qzyc}^5{VMJ;>Rww1LOt)R{Nw5o^vINRkuZRU#+GJ2Pg=z$4ZN#wno>l*#*@ zy!46hx?VXk=~I%N?^x+mlAP~d=~I%N@8Z``_dUp&b;LU|+L^n^@(D6_hjzScuiY-l zP@`eKD@eSP^ym@J@zp@R;(FA_91OFsyc=yvX+x=Z*VbN+FZPdmyd&kHSpV0KiJbRH z8+i1P$oUOQ8+i2CGY|QV?!#}KeNP*BY|v8*?}cqX^5FODNqUfVzCVaPz~2sS+H<1R uQLtvIoQv{h6p&dzUJtP&m+0>tVywvXWI&uLna2o7cu*%!oLAES+5HEK@5o*N literal 0 HcmV?d00001 diff --git a/Shaders/BasicVS_Box.hlsl b/Shaders/BasicVS_Box.hlsl new file mode 100644 index 0000000..7ffee18 --- /dev/null +++ b/Shaders/BasicVS_Box.hlsl @@ -0,0 +1,68 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; +}; + +struct RenderableBox +{ + float3 Corner; + uint Colour; + float3 Edge1; + float Pad1; + float3 Edge2; + float Pad2; + float3 Edge3; + float Pad3; +}; + +StructuredBuffer Boxes : register(t1); + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + + RenderableBox box = Boxes[iid]; + + //float3 mpos = input.Position.xyz * box.Size; + //float3 ipos = mulvq(mpos, box.Orientation); + //float3 inorm = mulvq(input.Normal, box.Orientation); + + float3 p = input.Position.xyz; + float3 n = input.Normal; + //float3 s = float3(box.Length1, box.Length2, box.Length3); + float3 ipos = (p.x*box.Edge1 + p.y*box.Edge2 + p.z*box.Edge3);// *s; + float3 inorm = normalize(n.x*box.Edge1 + n.y*box.Edge2 + n.z*box.Edge3); + + float3 spos = (box.Corner + ipos) * Scale; + float3 rpos = mulvq(spos, Orientation); + float3 opos = CamRel.xyz + rpos;// bpos ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = inorm;// mulvq(inorm, Orientation));// NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 c = Unpack4x8UNF(box.Colour).abgr; + //c = float4(abs(input.Normal),1); + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = 0.5;// input.Texcoord0; + output.Texcoord1 = 0.5;// input.Texcoord; + output.Texcoord2 = 0.5;// input.Texcoord; + output.Colour0 = c;// float4(0.5, 0.5, 0.5, 1); //input.Colour0; + output.Colour1 = float4(0.5,0.5,0.5,1); //input.Colour1 + output.Tint = 0; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} + diff --git a/Shaders/BasicVS_Capsule.cso b/Shaders/BasicVS_Capsule.cso new file mode 100644 index 0000000000000000000000000000000000000000..aff28b39705738952d721c8b99a4bb5e163b1948 GIT binary patch literal 5208 zcmbtWU1%It6u!Gjnlwpm`h!$aSc8NLrKG8ZHj15OlWi6@-8H+e5ruZhPLi#gnJ_!C zRYB5FioU21rSw6eh}J@Us37V?!6HR`$b*QFf-XKcXLqtr>feDo_uTK? z^K;KRcV@>+1fV+vg5H-GAqigi>l|uTtAEAHlFXmAZ`4zFn#HJxYC# zF+Dz!QN$o$$Kd=BhHC%gu7ZJeD8GYc2L|oX=AfC$b9{giMel!NZ3VeSI{u%HCG58JOgTQ++7|$)NN#9|95_79x^wqReQ+dDY zxPcv1Jy%WI_2P?8%?ZGx7JD|;0>YASyY)HGU#zQA)eQ>ho*;0tZpAsv+#XW8p&I>U zk_X?}de*H6wma)o)Ndv(#>zNv@MR8qbfV@gA{15dVEYh!vlp5+rtL~~8O_+*BhuTU z6{T{HJ0C2lv{&<%eZN~c-?HdUSVy}CCSr1nogmYU2Jb18l;96y!z7MH3uFvABAA3QodIC${T z@ZlqmBi?NB_=y7SFgN@b@OvpF+1R;LsZj%R4{wYfcog!*Y$=;Rp^D{`lJ)GkTFb+3 z1@ax(OC5^}AWjXt;ByA2j5wE_P$;(GjIRv|BQ7HDC*BK&IC&CrJX~ z89Vdv9;c-~y`OjGB*NI}V^=D53bNhcd48U69_x)%C?n=zuaC9xL*Qwb_?Ho$IL}6$ z`t&P&M}%j71ZPf!r*GkTCgGVw@{ECbTR~CHt{Dc2tb+F!g$f|oj&$3 z_B%Vny_wzNO#LCqc$TPs3hVn#u7pR9?B$EKstWPGRZKfGDmF^qkowZcenT(fnUlZ^U5gJB%Y7?p?&fBX>S;p z_>mlTV9!8LQ%0NgBl#WJ9{TwTu`n;t*M6ucHlz*`E7!2mD>mqpSkl6SE#DlC^8?d4 z!L0MeS@htii?#&geCd2j*O)#b>DrAaeF#pT`XtdOw$1FztcLo;K#hJ9pEAQjqgSFj zQJ!aQ^wUby?nsnZVczIZ>O-FO;mkaf#IM9GJwn;Q8%^7=(IYvDo|(Nyf*oBa>WeLd zb5eKS+GI=DDk@J}T>Z6Hj1{Eo5sgjqLE$i7&CCbo35&?ev0bcD%EWe`>3O{CgedRd zLQbEQk8L66U8j6?3pslPIcW43b4+aDfiNEAQujL`T?fkKeIj|JENX*w)B8-1!BVI6 zpx751qQ`T{yFmI7(3ZW|+9!Cpmzp5RyyW|}b?Hk5Sl3rn~^6rq@n%e*4 zc)5S8zK-VZzw|ZrC04MFyZ(Rrnl+T%NIqm9H$6>XeCLv+uH+lJGI``3;J1xA5F5a{ z_zh*hCM`UaIu;$24?)heB`rLfa=pMq-#f9X@84?pzrYRRliySNq@0+%n-Ug)$X(R> zxQp7J`R|}_#_==apgd{e(L!>U`3=al=o6E>94F^DUhZ<7oc|7Tm*eF8pLhm!>R09) zZ)ToNWMeThR*ZVg1@qq>(c6bLa?rg2Oy>e;k{aEGEIP`_XLKL;qYt`SSDsDsk+hUL zx3cm?bTF^n$1_q6iqwDQn8G3cKC>c z|6upp2bunc&>nnu@cl}iu#c2_3T!cx9n|pxClyPhr2z932J=DUzw%Mdh5xOzcQ0ZO MMv47Q`a8Wp0q3XfC;$Ke literal 0 HcmV?d00001 diff --git a/Shaders/BasicVS_Capsule.hlsl b/Shaders/BasicVS_Capsule.hlsl new file mode 100644 index 0000000..1221568 --- /dev/null +++ b/Shaders/BasicVS_Capsule.hlsl @@ -0,0 +1,62 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + //float3 Normal : NORMAL; +}; + +struct RenderableCapsule +{ + float3 Point1; + float Radius; + float4 Orientation; + float Length; + uint Colour; + float Pad0; + float Pad1; +}; + +StructuredBuffer Capsules : register(t1); + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + + RenderableCapsule cap = Capsules[iid]; + + float3 mpos = input.Position.xyz*cap.Radius; + mpos.y += input.Position.w*cap.Length; + + float3 ipos = mulvq(mpos, cap.Orientation); + float3 inorm = mulvq(input.Position.xyz, cap.Orientation);// input.Normal; + + float3 spos = (ipos + cap.Point1) * Scale; + float3 rpos = mulvq(spos, Orientation); + float3 opos = CamRel.xyz + rpos;// bpos ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = normalize(mulvq(inorm, Orientation));// NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 c = Unpack4x8UNF(cap.Colour).abgr; + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = 0.5;// input.Texcoord0; + output.Texcoord1 = 0.5;// input.Texcoord; + output.Texcoord2 = 0.5;// input.Texcoord; + output.Colour0 = c;// float4(0.5, 0.5, 0.5, 1); //input.Colour0; + output.Colour1 = float4(0.5,0.5,0.5,1); //input.Colour1 + output.Tint = 0; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} + diff --git a/Shaders/BasicVS_Cylinder.cso b/Shaders/BasicVS_Cylinder.cso new file mode 100644 index 0000000000000000000000000000000000000000..fafd522a4ef2ec0e7ea1c3b3de98ee78e02aa9e9 GIT binary patch literal 5256 zcmbtWPiz!b7=OEM*;0yBAVv*`l{6I-LrNiyR0BhIyL5HSZo2DQ6BF2Ur|sZ&rvU!1E{-81u*1-&X4$LhZ0pVf=2SFbWAwy0QyyB)0n%$2_9 zu+c&b);V-zeGRx3!nt?m@hb|zeUs?!cRB&}VUX=KF?M4nW*NNS;D<0XUORpS_n2b`BI=B?_19F%Ub1UN=XJZq zO(}#L8f3ngO?fTEV7tow_z*ZTsgv9Tmbc)!r`1b%1(fY+-}O|DFC(K%AEMg;PJ50p z{wDAw^)N^mjr|qO{aCl-p99|)fqx79=?Huk_#p6J492~UHR&hJ&tY!&kG`6;Ybx(K zcHOV|j$2pbl}7PZyJq{~aTdGQodtv?uTpQ!xZZq2m7Ka?K==5*oyA*miM2hTbVD`! z4UKLn+sM`%ex*KbSJi!!7jtEvt6Ku4{;`@pk5p8_h3^B1&0c8vn5xglN zeDIk=$TwR&eqsTBxO09B3K&9CjU79bdRais#CdBH_=cXsOrk9@);I>HkS}IS+58E0 zB0o8CET@X)lX588G~(tFw+g-O#@3=Sh*L8z_?*EhYsN*eVjIr59VjSq5mBFbFBszF zNyPOq`s7KR*|*rP)|Vb8&RP?HMVx~tjm>f^lSF;|o-}d#BoXhy z5PkY25#NT9U>(XQ+e=*JA)PsLWSL=JdFV;XFGt?<94t z7+cn0bq!?A+*yZ@I4$&Pecq*$NMo&!T^sNoc<%oc^mc-$9rrqm^;$B}quhp_hqdrS z;HgXeyAV&D`y@_#<{*4mh-a+?XMKccY~i^-;aN}e%z-tWLtD_tr#ON&73A4t@{d^% zfHH3c`Qm>v;X#MF-`f%BW_AWM?S~-aUc&ZCtRGnjY=)q-V(do{gY>wu;Y`1h2lpQK zLv6_ee1d*R=VC#f&ULKMk@dRN8OS78KstZQGV!3MGKYN1l`O@1-ea4IlN%u}X8AEXLv?qx@u`Na~vl7@7 z12y|eV#*8;&0Y!Hgn90@*-y(YzawE@1$ARQIUn*oAI_{ZN#aV*(j$}&Txj`*k8M(u z@SfRgB>2(iM0@dNa8BypyX$=EvkJ@O7FT~gE9MH)=Mm0L>OtW!Uel}xsH?*?+lqj9XBkuseZLER#0M^ZKDEl>T;i1&g@SuDMa_%i|;n9-o1s?j|iBEn1R)T*ADo9Lz zPZ^VPV)AZ^SpY(JQQPA#YJcV*gt3{&&&Y%FxP?a>$zA3*Ak$_~Ozv`&oZoo4%TaRv zJIGy*lJkG!MV!-KWxnxd=H5g$8X@C}(T=rX{d+=ok7A7)^sE8XwZNX_j2=K19%a-s ztVezHK@ZQBdy{&^Ev4RCUVb(_SXb(CkCcN#=f8YZ2C=AA$Awvue1sJNU0-Wi<#`8&KEeTSUOhnF;8Hy Z9wgTOu;zk)So+(H*n?qWKa>8>?oY!+?V|ty literal 0 HcmV?d00001 diff --git a/Shaders/BasicVS_Cylinder.hlsl b/Shaders/BasicVS_Cylinder.hlsl new file mode 100644 index 0000000..9d39f61 --- /dev/null +++ b/Shaders/BasicVS_Cylinder.hlsl @@ -0,0 +1,62 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; +}; + +struct RenderableCylinder +{ + float3 Point1; + float Radius; + float4 Orientation; + float Length; + uint Colour; + float Pad0; + float Pad1; +}; + +StructuredBuffer Cylinders : register(t1); + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + + RenderableCylinder cyl = Cylinders[iid]; + + float3 mpos = input.Position.xyz*cyl.Radius; + mpos.y += input.Position.w*cyl.Length; + + float3 ipos = mulvq(mpos, cyl.Orientation); + float3 inorm = mulvq(input.Normal, cyl.Orientation);// input.Normal; + + float3 spos = (ipos + cyl.Point1) * Scale; + float3 rpos = mulvq(spos, Orientation); + float3 opos = CamRel.xyz + rpos;// bpos ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = normalize(mulvq(inorm, Orientation));// NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 c = Unpack4x8UNF(cyl.Colour).abgr; + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = 0.5;// input.Texcoord0; + output.Texcoord1 = 0.5;// input.Texcoord; + output.Texcoord2 = 0.5;// input.Texcoord; + output.Colour0 = c;// float4(0.5, 0.5, 0.5, 1); //input.Colour0; + output.Colour1 = float4(0.5,0.5,0.5,1); //input.Colour1 + output.Tint = 0; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} + diff --git a/Shaders/BasicVS_PNCCT.cso b/Shaders/BasicVS_PNCCT.cso new file mode 100644 index 0000000000000000000000000000000000000000..c047c7e092ad963c46b73d867b4e95c57860d1d4 GIT binary patch literal 9960 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 a{}+8r5Bj2~;TmQ(_DeU`vj?&NwDvzk0k69N literal 0 HcmV?d00001 diff --git a/Shaders/BasicVS_PNCCT.hlsl b/Shaders/BasicVS_PNCCT.hlsl new file mode 100644 index 0000000..e340406 --- /dev/null +++ b/Shaders/BasicVS_PNCCT.hlsl @@ -0,0 +1,40 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; +}; + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz, input.Colour0.xyz, input.Colour1.xyz, iid); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 tnt = ColourTint(input.Colour0.b, input.Colour1.b, iid); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = 0.5;// input.Texcoord; + output.Texcoord2 = 0.5;// input.Texcoord; + output.Colour0 = input.Colour0; + output.Colour1 = input.Colour1; + output.Tint = tnt; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} \ No newline at end of file diff --git a/Shaders/BasicVS_PNCCTT.cso b/Shaders/BasicVS_PNCCTT.cso new file mode 100644 index 0000000000000000000000000000000000000000..2956bf79cbfe0269baaa67f7724526d2be234457 GIT binary patch literal 9984 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 literal 0 HcmV?d00001 diff --git a/Shaders/BasicVS_PNCCTTT.hlsl b/Shaders/BasicVS_PNCCTTT.hlsl new file mode 100644 index 0000000..75ccc15 --- /dev/null +++ b/Shaders/BasicVS_PNCCTTT.hlsl @@ -0,0 +1,42 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; +}; + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz, input.Colour0.xyz, input.Colour1.xyz, iid); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 tnt = ColourTint(input.Colour0.b, input.Colour1.b, iid); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = input.Texcoord1; + output.Texcoord2 = input.Texcoord2; + output.Colour0 = input.Colour0; + output.Colour1 = input.Colour1; + output.Tint = tnt; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} \ No newline at end of file diff --git a/Shaders/BasicVS_PNCCTTTX.cso b/Shaders/BasicVS_PNCCTTTX.cso new file mode 100644 index 0000000000000000000000000000000000000000..7e635403e5d4974caad2e8d17aa268ab922bce2d GIT binary patch literal 10556 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 literal 0 HcmV?d00001 diff --git a/Shaders/BasicVS_PNCCTTX.hlsl b/Shaders/BasicVS_PNCCTTX.hlsl new file mode 100644 index 0000000..84f5bf6 --- /dev/null +++ b/Shaders/BasicVS_PNCCTTX.hlsl @@ -0,0 +1,42 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float4 Tangent : TANGENT; +}; + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz, input.Colour0.xyz, input.Colour1.xyz, iid); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = NormalTransform(input.Tangent.xyz); + + float4 tnt = ColourTint(input.Colour0.b, input.Colour1.b, iid); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = input.Texcoord1; + output.Texcoord2 = 0.5;// input.Texcoord; + output.Colour0 = input.Colour0; + output.Colour1 = input.Colour1; + output.Tint = tnt; + output.Tangent = float4(btang, input.Tangent.w); + output.Bitangent = float4(cross(btang, bnorm) * input.Tangent.w, 0); + return output; +} \ No newline at end of file diff --git a/Shaders/BasicVS_PNCCTX.cso b/Shaders/BasicVS_PNCCTX.cso new file mode 100644 index 0000000000000000000000000000000000000000..8f93137f55ce82530412ffd491f73fd61605f2cf GIT binary patch literal 10508 zcmeI1?~7d38OP7gZZ_+h7#pqFAUYI@QACnWh-tLVWOp;k(oJ@|v)LxnvYG7O-5s5s zS!QOFSforskXBJcUj*CQ5=x2E_#(7YEJzJvX{AbiA=FBtAf;IBD=BGTl-lp--1FSM zJKpF&(8Jz2=X{?Z=lONcxidR_WN>Krd;j@+>D2J6XHPz{ZnXS^N|$qP-QCXhs^6vO z8|$1KUGLn>H#pbc;@mks6T|z8w+ZhP{m&BUSAUxx*Yn?xo#r20FFEzyU>yzpJahWU zsb8a~N6*J<>O4)$xrXS_umk=Z^}x@V=QJM~&FD{M(2Yj_!wh;_{|gy({4pIbWzg}% z=&xqb@yF$6ccjQ2% zn`Fmx3d-B5L=t!6^p2bvS8t7YQV+MviGqRZiKG79_}bMt@gp8B;d%Aeh#UM{q^!*# zG~%^U<72`v8>pT-f$c%n95q72+*y*LW_7a^=56(01wHt2F5nl`k7wXN6MjxOGBnfk z3*i?4f{m{SJ@0^n1^ll8|0g&L2D}I7)oxaQK?VmlcW1zNsQ+mOJ}CT!417%Ziy8Ps z!Y`-rs^+xE)W4L0KPCL-4E%e-U&+8P3cr$p|5Ett8Tb|9zstaXFZ|66e5kzWYka)k zROq_(SfrdY+EgVvsgk|aEqYIiK3bVyXnCR^4ObcxY0i{qqp`WUX4In2O{e8IFqE_n zw85@PAC8t<3!g$CsxQ}C*hH0eS<)5vpns~;TrOAL_)u}QUSBG;%8iyy_SI(HV7)OL zHO9-cvz6NX!Ai|Z559-uk)G8YT+W+YMqRtT3D!QD|(AYY9}~ZqH3w~ zt!QO*#A&I4t=QYcA*5E&linZe!@ed?;IXv{2CAQdArH{ zb+oeAZuQ)GL*#~zyPo7;uIsJYo=wR0kx87#ME7WS5pALr1j=!HVX zztyD)!%?+WHqtgoM1d3iF4X(NKMHX}J~gZWcAhmRp((F3-)$ z+DXNbX1RMe%_9%~k zm1@+;@4RpOeP7zSb?bfGc5dIbLwkOtwExft(!gyr-+3B}I#9tYx9-JF)t?(=A zt$|Yo-5R`MAoK8S*bw8$(!jAE{0{)3f#Vza9|MMM$Z_R#X)r!k8krm!JLC?HO&r`i z>L&Lc85$d#7zw#?Y}YP0PB` zfHMbYx>f?E4&3{zWPlq9e(-e~fZNUh_fOzwOr!U4P!B(28n};xdcLPw11ApH32r2C z@@RN^U3>*cKRRjfU#G|LaGiTxM@@pGlLo)aERMs}^k<~t(xuXYeMhc*K{1wvOH%&u z0oQd@?iHWTdz)F?<{EmtY>w^3!RD;ZV{>Tm9PNws;S=|f(eVWz9zyIGyVtoRw@T$w zJU)Ebxu39v=I8;P7H{Lmm~LZY%XmOIe2hQR7+Y+NEjGrEW74}(JlH_o=QaN*AL~V5 z#5$VWctB%xgTIy4e@~mUyHK{S{7*4Ki%-S|4);1e?@_v26t|%VXL}#v`kB)}iYZ-FAXJa|+$`$m{(VmyehUAD#e~4dK zA!aHz;utAyYq5!V6$39kSP6}Fp-o*E>w!jHNaxzYz`rT*K>HY8mEJ~S-5TE$c);Ed zSnmz7PQ6nkI(7#dI@;~_0|VMFX4m6^mJ{uC+dar5)xPBlbnRE;hq2#hYtMvr@yUFn zSL-vH)@<(;KzvwNI`({3cH$Sj*aS_sTxT-)0}cLX7Qg=r{av>_`{gu`$)$N8-f{HT zpT%=={Tq9v+S|t(lK1x6dS)NCn0@rpyN*0FzStl4xq>E1BR0Rt~b8TpNQiMuWHKYg&63pU-8-O3_Z2f>9c-L^!p82 zYLni4*D#5FR_-lt`UL04PJ-;HsNbPG(yp^qG~m&lE` zBkV2YWnbSwp!Wv*dRNo^eu0;`SdTuneyg?qcHY+~IQP(|po6je?8gSyHXFznbIEzz z;FB%MnU|KoC&eR~q-N6h3-X)g3$ei_s~37=K}@u768*Xh{m+8f1CPa7wyrauWWy?- z(sr015?ytl;FI~bBSkYT&P#m0TRw{$x%uLA6nTrY)i5!g(i!4oe zfZN$r{LX6sihXen;GeC_xt-RTj#)9(wAS(Gn71qBELY%v2=SvOedDg35S=*pcE!1+ zwph!2f>t~e=NnA6tWVRyas}-)*S_B#L5U3G&hy@M)3Zk`|I95%S|`c7VIdEDtcT}| zXiv#)3iFt!y+{7|dkCKXKrlD>)%$fUUg%Nt=a0wE#Cf3xas_=jr9sbIZ;pP2 ziQ1}M0?2N^Kaj_UGknH)l5=SGe#4mf({v{#XF{$3!g;y!*nSbg=ME0Z`t=ywxq%{n(SH=L%wSj!%1%n3z7~dv(vSM(^poKKbIj zvL1AcBXnr2fjs+~vEE8nTQ{hsDj_Vc@lQ7{=)sV*{AkLeJW& zJ^wz(c-8mVR1H8=^XC);lePSVeO{*9-eKNV;4|Jk8}nh0YH!fkJJ$T(xCWhd{ocC< zo!CM@a}7HF=0lt{%sd0wH|%ZJ;tcTpnU%c_oxPn!2ZPSu&Z1*qdT%FZU5Gt<+jLkh zr0dw?oUS#?xy2rNwg2y3%Rz{3u0U8EpY|lRublaJ1oC4swtiT50{MoP^mz0dD8kv-k?QD14g<(~SA8ZK zoa57;#5Qtmu`%1MC)Y-^_ZQ2xU)SDEf=`{l0Y0xgjNB5N^mitH!|Pp&eN()W^{FR# zyJV$a^Zjpf-CzcdEK8^V?tmP>fzam)u}<__n+ml|T+KhQ zb3ea#vM#ZKmMiEt&$I0Z>=6{dZwJ0E(K+8Y${gatdn0nRe5xMPI5M)`*R;jW?7Am> zN2W)Q?vh@M4exHI`+)9ze(&|R$`9->emkyx`z<@REq(`-o<8Hx6~vr+7iP@8#Up~h z-@HD>fW{dMfhIk^R-niFSMD~yr**e^S>0{OfZ5%aMd!Px-ECQPzIWT*mPN;Z=-jQu zhWE8AeRNLVc{^-sgAr-CCO%!H2D2w#UKX z!~U*78@V_xC%$|L5GZHyt@PG+aJ+X?(1&|McIdUi!{wfANLib~)!>+vZ%a`aOES zzR|hsH#yh7#<{)1$MsB&92mVxc)#d>(t-i?H|cRb|NYQu{8I$x=0HwIX-0QEE2FYRy)uHWxMBOtCl@)uNeF zqv?vLO6B^4i=`z$n<*ZswJNQL!sKwh996^kU{qfWLnIxn)=!qI$YM5LpJTGRO8l;q z9nUBzZ>17R+=cI+n@Z-sVUr;}pf&X0ilfqd;GdaH! zegPoZ_-c^zHaJ+o{}S+jfuk_sJvgs+z4{9>IIy`}0=`TA&ob~K;g>S-3E|IW;P(l? zoWiS`(;im;d&s3VrrK+189v!dOmx`@Yqh*r=wXz$kH_B0C zvQ#ctY72)eH77av9*ReD)^n83xS>j^>4vJyjiIRZU=-DYqNZu|7LChxbmf8P=_5C^o{1)5mglFaGK&^DL z8u2dj4j!LT^^P@1BJC3w(pE0nGD1&$QyL?I>Pr?mrj*ND$Ul>#p%jo z)Nsp(>!+hd?bxt-cE0pLRQ5NfBifj%(*?f?r%JVj$PC!&7O2~ysK!ZaccBFH3sjwM z!K<5&nk^gFho!DjT8QGEy)a%ckIF1cI@Yjov>6T87nhb>5qGnwF|pjzWN3MQUe-=4 zhBV9FJ7IpyfvR`HDIUj;&o1xS{n7JAr2C-E;ulPNoT655OdTAW_11vwug@y>I~jgM zvQGv1XTq4=Jr>5)$&bRATlPYK5%S!Vq$8<4Nr_uOu6FB ztQ|sQBQkq+LUxz6j=w>WRX~^;9r|ce=f(rh9Gq#N78E;hZ?}R9ZY21@H);TG6%Ov7 zz|WXQk3Z;zpD_)bT!HiVmNjr*p@tg?oY#lpX}$Pr@{vh{|0+F(hu5;lbz~$sGHLLu zT;e#)%zi@XS67RN4jg;_Gm5by^G_+g|B&lCF84;C$op8K+vXa2Uu}-<#KGq1=CL_6 zc#ikS^6-iGiqY`}AMRt>33j1#$8MC!rFeYwsB=F>h33csofU86+L&%*V#|0?IDCxX z*BDz)X#EzAv4!|9X#RdaUeCG+d79gJP-A3(zmgh*BM+SQ$g}Z=)EJ)(Cnq*Ww~dLZ zjq#r`HjuYd3K{D@=X!eXY3IEy=)K#yYX)6x_Xpq4d;NmlsCdwc%v?b~9gTIbWUT8w z7q7#vTtPn_?OBOzXdQ7G2=VJG#7v`&I7UiOA2t!M(ZCB2RzgEBw3(}7IncJE^|xF^t%(Qdcz9n`ikyB-O&oM>m;ZZD5S z`<5%vwO@)K#(qEbtpvUJWWLd>^&3q(+xrC&AM{GbzOTqm{DK#opvji2Yz_WEga7-B zPrpci>kUtRDa~W+(!BTYI{uqa;<>o#^?efU?L&vwd;3hE*@rD=AHC#mB+ra54#a(~ zph?n*kMf&~X~f<9F4lcAbPG;HawoGz28Q->##Bq&RHRba{ z40NWi`D}KEo?7bkS)c#>eq$}QNpHSun8ZFS_m(&EU@;#EGN27w<@xyYR)^F=~q~c(h?J3zdV0pG2<_c1j?AtiDI_Hu)wwSEvXANyV ze>#Sbbf@dVau)X%Klb$2@NU7zKW=`#ARn*BMtr>Zy|~_yd-1V&3~n}Q5A+(Zdn>Lp z=xS^EyEd+oZh@&d^phj@61nkqguTUj+1Ec9=)J+d-t~09U*IJ!)+0}Cz-n!vo%i(# z&UB#d(R(cgyGK7T$dEIm&vA zv(+#$ozWTMW51H`rH9XKr;dIpKfvv58vX8i|3>@c8o)o(%ekGFnU2|LsA=i(=a{!E z z+4SrY%Rh6=k@O^aH!S2~pY`y39_gudTf;o&Y44Li{yhZGK%f~9w84P=RdJ<}3)=2* zCbPF~9e!*Py<3>&o0!7`|0`iFcOWqMu@C-j!pPhCzF0oAp-x%hy(>1qf7N?E7BA$e z`SZtPD{)?^fm}g9PHE8d<{RT*W}>z(mjJTc?+?~v!wSDKp5z>w-ESBZf12J&$(fKV zfN)-}J+@y&@VSFSYrQ_kc5dLuo_u@;f}4ChKRi8Uo6)-pa66w<@`i2f2YTL-^p;b` zoDVdkQ7@Kn!!B+O`3yda-QR`%I_1OnD{E&8vEHJsoL6kA1@vII&w<9+2u3|LLSMt6x+~m;Pdi2?u%$ec+6sDHk-_Q+iy<{i*JiR78R^F2H{hs!k+;!vB z9i2Q|?9CqbpV^Flv)RX0HbL9==$dTFNcLIU=kq;@9ADS0H(4g1p1<47f9%JeG(A@k zlXLvqlf=a2vA$RD8FciX&Fhyxkk|AUzFh7Q)VuNmw9(mtym8C`|-cNj44Ei~3L zHW?N-yTib1cNoU$7+XD=E%fMC?fLs0<8^<>rfLA1nm?x)*jmd!*r#Q>?H%U$;dJi! zy^#-lRC|NQ-m&KQ#ue!3g+6ozI~n15g= z1I8T_8S;66Z(!)fSNL-UeFr<&zSkZ>@f|Gib&1ZN-y(B}3wH_5Dq23Z57RhnWIK<) zx1rnYx+DDEq;sX$V#0geWFFG_&$mBsqwHtx=(pp2WZy4io8tR`ry@)Yq z7>@}4tn>2ZJB_^qfhIZrTL5(P+0HqC?@!$USOaF~To#?bL+qT(qVqSHopV`q{5So? zCVj_1f43f=&k!TqtGR**x~rw0_-_Zrl<%M)$0wS9w-N*5F{m{@Udma(`t5sdt{|qh z=Jk<_ceMt4a|Qi$G-Q%1Vl#SkTz{+qBObYee%9IE-e>gGx7U zIN6>y?COB2!^eJnB$l~?e%5sRi7xY9#nG|t=i5o@S}k8A$}yeg~e literal 0 HcmV?d00001 diff --git a/Shaders/BasicVS_PNCT.hlsl b/Shaders/BasicVS_PNCT.hlsl new file mode 100644 index 0000000..2dcd791 --- /dev/null +++ b/Shaders/BasicVS_PNCT.hlsl @@ -0,0 +1,39 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float4 Colour0 : COLOR0; +}; + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz, input.Colour0.xyz, input.Colour0.xyz, iid); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 tnt = ColourTint(input.Colour0.b, 0, iid); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = 0.5;// input.Texcoord; + output.Texcoord2 = 0.5;// input.Texcoord; + output.Colour0 = input.Colour0; + output.Colour1 = float4(0.5,0.5,0.5,1); //input.Colour + output.Tint = tnt; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} \ No newline at end of file diff --git a/Shaders/BasicVS_PNCTTTX.cso b/Shaders/BasicVS_PNCTTTX.cso new file mode 100644 index 0000000000000000000000000000000000000000..d0d01cfae1e3e83ce41b25744c7fb8f693aec48e GIT binary patch literal 10524 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 Kapp Spheres : register(t1); + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + + RenderableSphere sph = Spheres[iid]; + + float3 ipos = (input.Position.xyz) * sph.Radius;// *0.5; + float3 inorm = input.Position.xyz;// input.Normal; //unit sphere pos == normal + + float3 spos = (ipos + sph.Center) * Scale; + float3 rpos = mulvq(spos, Orientation); + float3 opos = CamRel.xyz + rpos;// bpos ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = normalize(mulvq(inorm, Orientation));// NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 c = Unpack4x8UNF(sph.Colour).abgr; + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = 0.5;// input.Texcoord0; + output.Texcoord1 = 0.5;// input.Texcoord; + output.Texcoord2 = 0.5;// input.Texcoord; + output.Colour0 = c;// float4(0.5, 0.5, 0.5, 1); //input.Colour0;//float4(abs(input.Position.xyz), 1);// + output.Colour1 = float4(0.5,0.5,0.5,1); //input.Colour1 + output.Tint = 0; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} + diff --git a/Shaders/BoundingBoxVS.cso b/Shaders/BoundingBoxVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..3d6b742201e7864dcf74a9329c99670d6aefc447 GIT binary patch literal 1536 zcma)6O>0w85S=8oX|!mp8y7AfE<{0M`ax(#^figGfwT#EAt(stnLgV{n#gNVR}w-O z3ZlENbR&X7HpO)p1vmW(UAa*32e^=~tmnLUZ<3Zoon$g|XU?3N`$5uolc{%sgTv?T zkD1Tc=Dr*}Fd_kgjEbCqnSqvqA}^pj&`ku3>D!s}@bQ%Rh+t0w%rZ*$;LC!>vYJ={0FEB)k3~7bRSyKLD(JTo3Na7Pp!*U=V`%h zJd#eQ6OxdO;G?C*29PL}HLukAEi7Zl8MV zaHN^n20Z_4^_m=f%gdm0qr5$lRX~0kzRx_~Pmp~OiA;DmERty(-X4hW_or}08gsqX z!}R+nCEA*2Aq4nS-xOzg!tYsD+=Nz**vM%=YQ7ms4kumlrc5AcOdn@c?S?{X+ zsIvXDqb#iRnV`?3E#{2q9BV00)C?M<`8l`ldFf?u4(^p4l>YgCMEn?dymMi_<|3B- zlwWU-aE)s&oe!Es;mUjJ)$%+b-rnhGyxu$SHi2i*RLqsrt uaY&v$nNJSMbC1lohvYfaO_6|AnlJHx^c<8iimLS&_*MJsuK(ryFa8f?$d4lc literal 0 HcmV?d00001 diff --git a/Shaders/BoundingBoxVS.hlsl b/Shaders/BoundingBoxVS.hlsl new file mode 100644 index 0000000..42d7215 --- /dev/null +++ b/Shaders/BoundingBoxVS.hlsl @@ -0,0 +1,27 @@ +#include "Common.hlsli" +#include "Quaternion.hlsli" + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; +} +cbuffer VSBoxVars : register(b1) +{ + float4 Orientation; + float4 BBMin; + float4 BBRng; //max-min + float3 CamRel; + float Pad1; + float3 Scale; + float Pad2; +} + +float4 main(float4 pos: POSITION) : SV_POSITION +{ + float3 bpos = (BBMin.xyz + pos.xyz*BBRng.xyz) * Scale; + float3 opos = mulvq(bpos, Orientation); + float3 f = CamRel + opos; + float4 cpos = mul(float4(f,1), ViewProj); + cpos.z = DepthFunc(cpos.zw); + return cpos; +} diff --git a/Shaders/BoundingSphereVS.cso b/Shaders/BoundingSphereVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..88dd121b6a576a995f31a13f64e722df6c6ece81 GIT binary patch literal 1364 zcmah|&ubG=5S}DeYml}U4+|S3_91(i zsvI4E&BR2cc1i?~EK`q*48U)}AE!jB#XF^o(DBFtnDR1MrhfevB!2;K(w;!9O>X`J zBknrRmTD`v?sci}HI)|{!{Ly%PlMlpUxN*?CVM$TfjQ%Z%(5UT2PR(Bb`6p~@~D3k z{vLc7HSq7~_-ByMwI4!^e*phrg8vZymlOPMOFgZ4oyUS%5|Y3pK0v{bjJLzQ(x^k>0KI?8(xxGg|6(aojD{*{sV^0j*b04Y2uBHivI)5RD)>% literal 0 HcmV?d00001 diff --git a/Shaders/BoundingSphereVS.hlsl b/Shaders/BoundingSphereVS.hlsl new file mode 100644 index 0000000..337a35f --- /dev/null +++ b/Shaders/BoundingSphereVS.hlsl @@ -0,0 +1,32 @@ +#include "Common.hlsli" + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4x4 ViewInv; + float SegmentCount; + float VertexCount; + float Pad1; + float Pad2; +} +cbuffer VSSphereVars : register(b1) +{ + float3 Center; + float Radius; +} + + +float4 main(uint id : SV_VertexID) : SV_POSITION +{ + static const float twopi = 6.283185307179586476925286766559; + uint seg = id; + float t = twopi*((float)seg)/SegmentCount; + float ct = cos(t); + float st = sin(t); + float r = Radius; + float3 o = float3(ct*r, st*r, 0); + float3 f = Center.xyz + mul(o, (float3x3)ViewInv); + float4 cpos = mul(float4(f,1), ViewProj); + cpos.z = DepthFunc(cpos.zw); + return cpos; +} diff --git a/Shaders/BoundsPS.cso b/Shaders/BoundsPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..aa0a9daada5baa08cd756ea42a5a85215934f878 GIT binary patch literal 516 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 literal 0 HcmV?d00001 diff --git a/Shaders/CablePS.hlsl b/Shaders/CablePS.hlsl new file mode 100644 index 0000000..7cc16d5 --- /dev/null +++ b/Shaders/CablePS.hlsl @@ -0,0 +1,102 @@ +#include "Shadowmap.hlsli" + +Texture2D Colourmap : register(t0); +SamplerState TextureSS : register(s0); + + +cbuffer PSSceneVars : register(b0) +{ + ShaderGlobalLightParams GlobalLights; + uint EnableShadows; + uint RenderMode;//0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct + uint RenderModeIndex; + uint RenderSamplerCoord; +} +cbuffer PSGeomVars : register(b2) +{ + uint EnableTexture; + uint EnableTint; + uint Pad100; + uint Pad101; +} + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float4 Shadows : TEXCOORD3; + float4 LightShadow : TEXCOORD4; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float4 Tint : COLOR2; + float4 Tangent : TANGENT; +}; + + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + float4 c = float4(0.2, 0.2, 0.2, 1); + if (EnableTexture == 1) + { + float2 texc = input.Texcoord0; + if (RenderMode >= 5) + { + if (RenderSamplerCoord == 2) texc = input.Texcoord1; + else if (RenderSamplerCoord == 3) texc = input.Texcoord2; + } + + c = Colourmap.Sample(TextureSS, texc); + //c = Depthmap.SampleLevel(DepthmapSS, input.Texcoord, 0); c.a = 1; + //if ((IsDecal == 0) && (c.a <= 0.33)) discard; + //if ((IsDecal == 1) && (c.a <= 0.0)) discard; + //if(IsDecal==0) c.a = 1; + c.a = 1; + } + //else //if(RenderMode!=8)// + //{ + // c = float4(input.Colour0.rgb, 1); + //} + if (EnableTint > 0) + { + c.rgb *= input.Tint.rgb; + } + //if (IsDecal == 1) + //{ + // c.a *= input.Colour0.a; + //} + + float3 norm = normalize(input.Normal); + + if (RenderMode == 1) //normals + { + c.rgb = norm*0.5+0.5; + } + else if (RenderMode == 2) //tangents + { + c.rgb = normalize(input.Tangent.rgb)*0.5+0.5; + } + else if (RenderMode == 3) //colours + { + c.rgb = input.Colour0.rgb; + if (RenderModeIndex == 2) c.rgb = input.Colour1.rgb; + } + else if (RenderMode == 4) //texcoords + { + c.rgb = float3(input.Texcoord0, 0); + if (RenderModeIndex == 2) c.rgb = float3(input.Texcoord1, 0); + if (RenderModeIndex == 3) c.rgb = float3(input.Texcoord2, 0); + } + + + + c.rgb = FullLighting(c.rgb, 0, norm, input.Colour0, GlobalLights, EnableShadows, input.Shadows.x, input.LightShadow); + + c.a = saturate(c.a); + + return c; +} \ No newline at end of file diff --git a/Shaders/CableVS.cso b/Shaders/CableVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..6077bacf00078d85ee93a5883e7975a1ed229695 GIT binary patch literal 9788 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 I4nD5@4?2OO4*&oF literal 0 HcmV?d00001 diff --git a/Shaders/CableVS.hlsl b/Shaders/CableVS.hlsl new file mode 100644 index 0000000..85b1efe --- /dev/null +++ b/Shaders/CableVS.hlsl @@ -0,0 +1,39 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float4 Colour0 : COLOR0; +}; + + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz, input.Colour0.xyz, input.Colour0.xyz, 0); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 tnt = ColourTint(input.Colour0.b, 0, 0); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = 0.5;// input.Texcoord; + output.Texcoord2 = 0.5;// input.Texcoord; + output.Colour0 = input.Colour0; + output.Colour1 = float4(0.5,0.5,0.5,1); //input.Colour + output.Tint = tnt; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} \ No newline at end of file diff --git a/Shaders/Clouds.hlsli b/Shaders/Clouds.hlsli new file mode 100644 index 0000000..fee5f8a --- /dev/null +++ b/Shaders/Clouds.hlsli @@ -0,0 +1,49 @@ + + +cbuffer clouds_locals : register(b0) +{ + float3 gSkyColor; // Offset: 0 Size: 12 [unused] + float gPad00; + float3 gEastMinusWestColor; // Offset: 16 Size: 12 [unused] + float gPad01; + float3 gWestColor; // Offset: 32 Size: 12 [unused] + float gPad02; + float3 gSunDirection; // Offset: 48 Size: 12 + float gPad03; + float3 gSunColor; // Offset: 64 Size: 12 + float gPad04; + float3 gCloudColor; // Offset: 80 Size: 12 [unused] + float gPad05; + float3 gAmbientColor; // Offset: 96 Size: 12 [unused] + float gPad06; + float3 gBounceColor; // Offset: 112 Size: 12 [unused] + float gPad07; + float4 gDensityShiftScale; // Offset: 128 Size: 16 [unused] + float4 gScatterG_GSquared_PhaseMult_Scale;// Offset: 144 Size: 16 + float4 gPiercingLightPower_Strength_NormalStrength_Thickness;// Offset: 160 Size: 16 + float3 gScaleDiffuseFillAmbient; // Offset: 176 Size: 12 [unused] + float gPad08; + float3 gWrapLighting_MSAARef; // Offset: 192 Size: 12 [unused] + float gPad09; + float4 gNearFarQMult; // Offset: 208 Size: 16 [unused] + float3 gAnimCombine; // Offset: 224 Size: 12 [unused] + float gPad10; + float3 gAnimSculpt; // Offset: 240 Size: 12 [unused] + float gPad11; + float3 gAnimBlendWeights; // Offset: 256 Size: 12 [unused] + float gPad12; + float4 gUVOffset[2]; // Offset: 272 Size: 32 + row_major float4x4 gCloudViewProj; // Offset: 304 Size: 64 + float4 gCameraPos; // Offset: 368 Size: 16 + float2 gUVOffset1; // Offset: 384 Size: 8 + float2 gUVOffset2; // Offset: 392 Size: 8 + float2 gUVOffset3; // Offset: 400 Size: 8 + float2 gRescaleUV1; // Offset: 408 Size: 8 + float2 gRescaleUV2; // Offset: 416 Size: 8 + float2 gRescaleUV3; // Offset: 424 Size: 8 + float gSoftParticleRange; // Offset: 432 Size: 4 [unused] + float gEnvMapAlphaScale; // Offset: 436 Size: 4 [unused] + float2 cloudLayerAnimScale1; // Offset: 440 Size: 8 + float2 cloudLayerAnimScale2; // Offset: 448 Size: 8 + float2 cloudLayerAnimScale3; // Offset: 456 Size: 8 +}; diff --git a/Shaders/CloudsPS.cso b/Shaders/CloudsPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..bb9cdf7c2f80c8e652c9030b4457412df5fdca17 GIT binary patch literal 2780 zcmZveO>7%Q6vrn`prHiS;zEUrv_c3KQCW5p+_d5&jz5wJCpKOuO{+@Ic0FD%S?`+t zXo(b%6#=S*1ie)BMvypE_|iiT9C|2H4q0XU!>I3Upj5~wE*mBRn+?zm=|7foj7 zH~)Dv@9pfYiyI4tj~|Tx(EV=jA>plpKI zi>30xQN~F3HOe^3Nfb75cu4RYjP1mn@Tk!oDxaVnL7_D!P!3_J!m(#i-=L1f#QX+- z-w#}_s;tOu&-Axdt=qG>%XG^LT3*v~bj|YEfc%_Bxr1__CdYO_i^8U&iam(?|DYxo zccTrWpTb5{68%fy6nj$tD!3xi=fG({N&Oq(8HxUF@Yf~!I{197r#y=NUjna4^g4Jg z)}tEg9q>yM{T1*{@ML~I0=FdkPr-W<{Y~&4iT+FQJ~-u+Y#)8Hd#JCYPVzs%_ayv< zCmFj9p4?{+{0{j4@(g}gqF2Fxl;|&l-v>|brvv_*#7_YJr^L?=_}>!!HSk9g{paBH zG9=^r3VaGY8P_fF6u5$EWcxH9b`Nz1d_L?k_EXG%N8JNY#`PC?9~`fIXpdt36yE7; z68;?cbqRkF{HBDb!S^Km9QZ8>FN5C(PsV!zd|$%1z`vFF>4V>u@EhRYOSqwKZ5JHN zaoJ!nh8vEGFr%imG8s0Yn{Nz%!iAwU-*jvi z%4R}1GH;d{1-i~g&}+=dcQ2dV9`&DN#)1>rIv)|9VTQOFJ7(KgaUJquEW>PKMP2iK z?k+YL)%OC;<*jC|qj`KKu>58;$*7s!)lJ)|m`2C1Iaj&cRDGA*hTmzfI&N39hTTTT z)VFNzd7)#A7tMA%@Oas@ta#f|sB_4OtMx*U@Z4Nc^Z7b&M}udXvC1{Kthw*dHW0CG zb_))|wt1+?W+JBQfz`t}o<|lrCfS0;?bdltJH;Mo0I6PEueRGB_ebKVJCiI*@Vd#b z)?DXZHaLQ3I`R0lVO;BSSF1VjCfsC)euNkJ5rZSk;d$1%M~Pos$M%M8NQP}_RHyCN zG}kwEi`O;VK#V2(%8J&@TfL4JJ%jM8R?)V(OF@P#8-42j3#VmphOL;o>v&j4IaPl} zS*oZNMeS%U?kY%Y&%}3A$)#t~XLFfMI-8rBn`O)D;_4|J?Wd6=x(ibAF{etr3CGbs z`S|#UoVtRGA<|Q(j>8e@Mb?N@5qja5YC55Ui_=P+J`>|;kRNK35vOZP=;JFZFeh%q(&RjeNsLpY}$3A)|bVGeCX8shu?0 Kn2aUoQU70C5P DensitySampler : register(t0); +Texture2D NormalSampler : register(t1); +Texture2D DetailDensitySampler : register(t2); +Texture2D DetailNormalSampler : register(t3); +Texture2D DetailDensity2Sampler : register(t4); +Texture2D DetailNormal2Sampler : register(t5); +Texture2D DepthMapTexSampler : register(t6); +SamplerState TextureSS : register(s0); + +cbuffer PSSceneVars : register(b1) +{ + float4 LightDirection; + uint EnableHDR; + uint Pad0; + uint Pad1; + uint Pad2; +} + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; // 0 xyzw 0 POS float xyzw + float4 o0 : TEXCOORD0; // 0 xyzw 0 NONE float + float4 o1 : TEXCOORD1; // 1 xyzw 1 NONE float xyzw + float4 o2 : TEXCOORD2; // 2 xyzw 2 NONE float xyzw + float4 o3 : TEXCOORD3; // 3 xyzw 3 NONE float xyzw + float2 o4 : TEXCOORD4; // 4 xy 4 NONE float xy + float4 o5 : TEXCOORD5; // 5 xyzw 5 NONE float xyzw + float4 o6 : TEXCOORD6; // 6 xyzw 6 NONE float xy w + float4 o7 : TEXCOORD7; // 7 xyzw 7 NONE float xyzw + float3 o8 : TEXCOORD8; // 8 xyz 8 NONE float xyz + float4 o9 : TEXCOORD9; // 9 xyzw 9 NONE float xyzw +}; + + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + float2 texc = input.o4; + + float4 d = DensitySampler.Sample(TextureSS, texc); + float4 n = NormalSampler.Sample(TextureSS, texc); + + float dv = saturate((1.0 - d.g) * input.o1.w); + + + float3 dc = gSunColor; + return float4(dc, saturate(dv)); +} + + + + + + + + + + + + + + + + +/* +//clouds_animsoft.fxc_PSCloudsVertScatterPiercing_AnimSoft + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer misc_globals +// { +// +// float4 globalFade; // Offset: 0 Size: 16 [unused] +// float globalHeightScale; // Offset: 16 Size: 4 [unused] +// float4 g_Rage_Tessellation_CameraPosition;// Offset: 32 Size: 16 [unused] +// float4 g_Rage_Tessellation_CameraZAxis;// Offset: 48 Size: 16 [unused] +// float4 g_Rage_Tessellation_ScreenSpaceErrorParams;// Offset: 64 Size: 16 [unused] +// float4 g_Rage_Tessellation_LinearScale;// Offset: 80 Size: 16 [unused] +// float4 g_Rage_Tessellation_Frustum[4];// Offset: 96 Size: 64 [unused] +// float4 g_Rage_Tessellation_Epsilons;// Offset: 160 Size: 16 [unused] +// float4 globalScalars; // Offset: 176 Size: 16 [unused] +// float4 globalScalars2; // Offset: 192 Size: 16 [unused] +// float4 globalScalars3; // Offset: 208 Size: 16 +// float4 globalScreenSize; // Offset: 224 Size: 16 [unused] +// uint4 gTargetAAParams; // Offset: 240 Size: 16 [unused] +// float4 colorize; // Offset: 256 Size: 16 [unused] +// float4 gGlobalParticleShadowBias; // Offset: 272 Size: 16 [unused] +// float gGlobalParticleDofAlphaScale;// Offset: 288 Size: 4 [unused] +// float gGlobalFogIntensity; // Offset: 292 Size: 4 [unused] +// float4 gPlayerLFootPos; // Offset: 304 Size: 16 [unused] +// float4 gPlayerRFootPos; // Offset: 320 Size: 16 [unused] +// +// } +// +// cbuffer clouds_locals +// { +// +// float3 gSkyColor; // Offset: 0 Size: 12 +// float3 gEastMinusWestColor; // Offset: 16 Size: 12 +// float3 gWestColor; // Offset: 32 Size: 12 +// float3 gSunDirection; // Offset: 48 Size: 12 +// float3 gSunColor; // Offset: 64 Size: 12 +// float3 gCloudColor; // Offset: 80 Size: 12 +// float3 gAmbientColor; // Offset: 96 Size: 12 +// float3 gBounceColor; // Offset: 112 Size: 12 +// float4 gDensityShiftScale; // Offset: 128 Size: 16 +// float4 gScatterG_GSquared_PhaseMult_Scale;// Offset: 144 Size: 16 [unused] +// float4 gPiercingLightPower_Strength_NormalStrength_Thickness;// Offset: 160 Size: 16 +// float3 gScaleDiffuseFillAmbient; // Offset: 176 Size: 12 +// float3 gWrapLighting_MSAARef; // Offset: 192 Size: 12 +// float4 gNearFarQMult; // Offset: 208 Size: 16 +// float3 gAnimCombine; // Offset: 224 Size: 12 +// float3 gAnimSculpt; // Offset: 240 Size: 12 +// float3 gAnimBlendWeights; // Offset: 256 Size: 12 +// float4 gUVOffset[2]; // Offset: 272 Size: 32 [unused] +// row_major float4x4 gCloudViewProj; // Offset: 304 Size: 64 [unused] +// float4 gCameraPos; // Offset: 368 Size: 16 [unused] +// float2 gUVOffset1; // Offset: 384 Size: 8 [unused] +// float2 gUVOffset2; // Offset: 392 Size: 8 [unused] +// float2 gUVOffset3; // Offset: 400 Size: 8 [unused] +// float2 gRescaleUV1; // Offset: 408 Size: 8 [unused] +// float2 gRescaleUV2; // Offset: 416 Size: 8 [unused] +// float2 gRescaleUV3; // Offset: 424 Size: 8 [unused] +// float gSoftParticleRange; // Offset: 432 Size: 4 +// float gEnvMapAlphaScale; // Offset: 436 Size: 4 [unused] +// float2 cloudLayerAnimScale1; // Offset: 440 Size: 8 [unused] +// float2 cloudLayerAnimScale2; // Offset: 448 Size: 8 [unused] +// float2 cloudLayerAnimScale3; // Offset: 456 Size: 8 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// DensitySampler sampler NA NA s2 1 +// NormalSampler sampler NA NA s3 1 +// DetailDensitySampler sampler NA NA s4 1 +// DetailNormalSampler sampler NA NA s5 1 +// DetailDensity2Sampler sampler NA NA s6 1 +// DetailNormal2Sampler sampler NA NA s7 1 +// DepthMapTexSampler sampler NA NA s10 1 +// DensitySampler texture float4 2d t2 1 +// NormalSampler texture float4 2d t3 1 +// DetailDensitySampler texture float4 2d t4 1 +// DetailNormalSampler texture float4 2d t5 1 +// DetailDensity2Sampler texture float4 2d t6 1 +// DetailNormal2Sampler texture float4 2d t7 1 +// DepthMapTexSampler texture float4 2d t10 1 +// misc_globals cbuffer NA NA cb2 1 +// clouds_locals cbuffer NA NA cb12 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xyzw 0 NONE float +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyzw 2 NONE float xyzw +// TEXCOORD 3 xyzw 3 NONE float xyzw +// TEXCOORD 4 xy 4 NONE float xy +// TEXCOORD 5 xyzw 5 NONE float xyzw +// TEXCOORD 6 xyzw 6 NONE float xy w +// TEXCOORD 7 xyzw 7 NONE float xyzw +// TEXCOORD 8 xyz 8 NONE float xyz +// TEXCOORD 9 xyzw 9 NONE float xyzw +// SV_Position 0 xyzw 10 POS float +// SV_ClipDistance 0 xyzw 11 CLIPDST float +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_4_0 +dcl_constantbuffer CB2[14], immediateIndexed +dcl_constantbuffer CB12[28], immediateIndexed +dcl_sampler s2, mode_default +dcl_sampler s3, mode_default +dcl_sampler s4, mode_default +dcl_sampler s5, mode_default +dcl_sampler s6, mode_default +dcl_sampler s7, mode_default +dcl_sampler s10, mode_default +dcl_resource_texture2d (float,float,float,float) t2 +dcl_resource_texture2d (float,float,float,float) t3 +dcl_resource_texture2d (float,float,float,float) t4 +dcl_resource_texture2d (float,float,float,float) t5 +dcl_resource_texture2d (float,float,float,float) t6 +dcl_resource_texture2d (float,float,float,float) t7 +dcl_resource_texture2d (float,float,float,float) t10 +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xyzw +dcl_input_ps linear v3.xyzw +dcl_input_ps linear v4.xy +dcl_input_ps linear v5.xyzw +dcl_input_ps linear v6.xyw +dcl_input_ps linear v7.xyzw +dcl_input_ps linear v8.xyz +dcl_input_ps linear v9.xyzw +dcl_output o0.xyzw +dcl_temps 5 +sample r0.xyzw, v5.zwzz, t7.xyzw, s7 +mad r0.xy, r0.xyxx, l(2.000000, 2.000000, 0.000000, 0.000000), l(-1.000000, -1.000000, 0.000000, 0.000000) +dp2 r0.w, r0.xyxx, r0.xyxx +add r0.w, -r0.w, l(1.000000) +max r0.w, r0.w, l(0.000000) +sqrt r0.z, r0.w +sample r1.xyzw, v4.xyxx, t3.xyzw, s3 +mad r1.xy, r1.xyxx, l(2.000000, 2.000000, 0.000000, 0.000000), l(-1.000000, -1.000000, 0.000000, 0.000000) +dp2 r0.w, r1.xyxx, r1.xyxx +add r0.w, -r0.w, l(1.000000) +max r0.w, r0.w, l(0.000000) +sqrt r1.z, r0.w +sample r2.xyzw, v5.xyxx, t5.xyzw, s5 +mad r2.xy, r2.xyxx, l(2.000000, 2.000000, 0.000000, 0.000000), l(-1.000000, -1.000000, 0.000000, 0.000000) +dp2 r0.w, r2.xyxx, r2.xyxx +add r0.w, -r0.w, l(1.000000) +max r0.w, r0.w, l(0.000000) +sqrt r2.z, r0.w +sample r3.xyzw, v4.xyxx, t2.yxzw, s2 +sample r4.xyzw, v5.xyxx, t4.xyzw, s4 +mov r3.y, r4.y +sample r4.xyzw, v5.zwzz, t6.xyzw, s6 +mov r3.z, r4.y +mad r3.xyz, -r3.xyzx, r3.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000) +mul r3.xyz, r3.xyzx, cb12[16].xyzx +mul r4.xyz, r3.xyzx, cb12[14].xyzx +mul r2.xyz, r2.xyzx, r4.yyyy +mad r1.xyz, r1.xyzx, r4.xxxx, r2.xyzx +mad r0.xyz, r0.xyzx, r4.zzzz, r1.xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul r0.xyz, r0.wwww, r0.xyzx +mul r1.xyz, r0.yyyy, v3.xyzx +mad r0.xyw, r0.xxxx, v2.xyxz, r1.xyxz +mad r0.xyz, r0.zzzz, v1.xyzx, r0.xywx +mad_sat r1.xyz, r0.xzzx, l(0.500000, -0.800000, 0.571429, 0.000000), l(0.500000, 0.200000, 0.428571, 0.000000) +mad r2.xyz, r1.xxxx, cb12[1].xyzx, cb12[2].xyzx +mad r1.xyw, cb12[7].xyxz, r1.yyyy, r2.xyxz +mad r1.xyz, cb12[0].xyzx, r1.zzzz, r1.xywx +dp3 r0.w, r0.xyzx, cb12[3].xyzx +dp3_sat r0.x, r0.xyzx, v7.xyzx +mul r0.x, r0.x, cb12[10].z +mad_sat r0.y, r0.w, cb12[12].x, cb12[12].y +mul r0.yzw, r0.yyyy, cb12[4].xxyz +mul r0.yzw, r0.yyzw, cb12[11].xxxx +mad r0.yzw, cb12[11].yyyy, r1.xxyz, r0.yyzw +mad r0.yzw, cb12[6].xxyz, cb12[11].zzzz, r0.yyzw +mad r1.x, r3.x, cb12[15].x, v3.w +mad r1.x, r3.y, cb12[15].y, r1.x +mad r1.x, r3.z, cb12[15].z, r1.x +max r1.y, r4.z, r4.y +max r1.y, r1.y, r4.x +mul r1.z, r1.y, v2.w +mad r1.y, -v2.w, r1.y, l(1.000000) +mad r1.x, -r1.y, r1.x, r1.z +add r1.x, r1.x, -cb12[8].x +mul_sat r1.x, r1.x, cb12[8].y +add r1.y, -r1.x, l(1.000000) +mul r1.x, r1.x, v1.w +add r1.z, -cb12[10].w, l(1.000000) +mad_sat r1.y, r1.y, cb12[10].w, r1.z +mul r2.xyz, r1.yyyy, v8.xyzx +mad r0.yzw, cb12[5].xxyz, r0.yyzw, r2.xxyz +mul r1.z, r0.x, v7.w +mad r0.x, -r0.x, v7.w, v7.w +mad r0.x, v7.w, r0.x, r1.z +mul r0.x, r1.y, r0.x +mul r1.yzw, r0.xxxx, cb12[4].xxyz +mad r0.xyz, r1.yzwy, cb12[10].yyyy, r0.yzwy +mad r0.xyz, r0.xyzx, v9.wwww, v9.xyzx +mul o0.xyz, r0.xyzx, cb2[13].zzzz +div r0.xy, v6.xyxx, v6.wwww +sample r0.xyzw, r0.xyxx, t10.xyzw, s10 +add r0.x, -r0.x, l(1.000000) +add r0.y, r0.x, -cb12[13].z +ge r0.x, r0.x, l(1.000000) +div r0.y, cb12[13].w, r0.y +add r0.y, r0.y, -v6.w +movc r0.x, r0.x, cb12[27].x, r0.y +div_sat r0.x, r0.x, cb12[27].x +mul o0.w, r0.x, r1.x +ret +// Approximately 82 instruction slots used + + + +*/ \ No newline at end of file diff --git a/Shaders/CloudsVS.cso b/Shaders/CloudsVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..db4431fb46a86464bb6fe95595d78fba2d2df8ef GIT binary patch literal 4724 zcmb7{UuYaf9LJ~EKS^z{F%)dI;vrJ1lyXUHY)jQklUyt$x$`!S6~%MC>|M6K?8Uvk zYEdv$A8Zw^2vzZ+eb8Dt!94V#prD9CA1c;25g&?_KJ`J0h={1)@9z9I+htnxS7vAS z^ZPTu`OVH;I4`eEUcYZfPqsqyoaTA-y$1U!aMmhq|0Hm>bKv>#4SqNuly&Im!PD!yo971{ z$0dxjMceO2|C)i1fgd;UGWdH2{xtY013v(M#=sAOFM_AndldYvfqwvg&Jbr2{3`?h z7W}+{*R6wxhntP2uR5J&xIx%N>Lq(7ms1_yEX(juq&{l5f(h4aw;p#|LF66U_N#h| z45+%*_C{RasRnM-Q=!?m5GMS#tNJkS#RPgl)raPubsaAme^Ax;G}~U)NfLZTV z!o_LLy0yTQPsa;leH$FI6xecY|j z2Bqfnj$g3?-|_0fY-O_P&)JRmb!yhF9`u}6D-7IlM%-Gh-Es4RejR2{eta3#x$^E&z&1?V%eS(TJ+~4W>wpbdFZhp{ird`_B0%C z=5dFaA_po^>V4D2TCL>-iS_f0P@)1)yUz0^zj;7)GT74<@z+MZJ?Hp#sflP3raz7& zQD7&^#B|utveRPW_e~?ccnp(x3>&Li3re;hxYdSJw!J#mIO-jmu;+&w^Rsre2jS1- zxP931xyX?9D+3%b!EMO5hX)#xM`PCO_4{V@WNZ}SOBLyKmZxe$-CpmIdO^qF9m1G$ zhrbL?mgcX6XAK-BE;|iX^!Zua;dzKwJ>gdUW((!XZZ6-KeRSL!&swwgjN@nVHO#vW z3ZHwRdW7aZ*hd%M(N6YHD=MMZn&E1Y8rd6+MH+Dlyak}tX33goQca{Ty^ zb4(%U&x*v?KQSRk>0-_?h4x&N*mF!F$Dg073xM%CrjX-L($Lx(iL-p$gX{@8LdzRWOa;%P(_jOk45+aN2SF3&zZ+jxg7< zkv;7k==h!-(?>XcWXyVUJOKNZ3C_BS4QnN1)`w#s_N<9;)?^l2%h)?mQeQ>+oLHy( zSF>T>%meycL|@26`b=J_?=Fl#Bn@Va(0xSWXn(Frd}JQ7-`7TQ3P+-O$RJ&uM|_e! ztXE6yq)&1@fInlzX4k?}-0Q}wcVQ@+OTm7%%qRJ5TCMZKIyt}O%sR+AHXU7xjTmdB zHYXBmKCvQ>6V9jW7}r^1{r=W!ZK&UK13lMB{gE5!`K=+RZu!#q3y5##7CjE%sYdY`Jb;0~yJons}c)hw7;kTi6yY#)p zy`eq#DU-(|CE`Q<9Vs8)OPM?#DG?v)@7F%8%Ye?Y0LJ{T9Lt8D8}Q_riuDT-$9EOm z+=+2P`(xNWfSgw*SV8-&2jg7VWG?I{=aReq4vdp?Ne-M#Vr=AC`_uMoJzj;qr}Uwn z*1r|BJ&iM^rTc5-#d}$p_;8JoFmLK5zRb_OxfeVqyvs9rJW?Wh-tU<_9x0)od&xUL ulgA?^;?LiKOdgMvJd7*Dni`r4z;kHaa|(ZV?+r)MgWv4`5&li`U*uosZVQJ1 literal 0 HcmV?d00001 diff --git a/Shaders/CloudsVS.hlsl b/Shaders/CloudsVS.hlsl new file mode 100644 index 0000000..1840857 --- /dev/null +++ b/Shaders/CloudsVS.hlsl @@ -0,0 +1,398 @@ +#include "Common.hlsli" +#include "Quaternion.hlsli" +#include "Clouds.hlsli" + +cbuffer VSSceneVars : register(b1) +{ + float4x4 ViewProj; + float4x4 ViewInv; +} +cbuffer VSEntityVars : register(b2) +{ + float4 CamRel; + float4 Orientation; + float4 Scale; +} +cbuffer VSModelVars : register(b3) +{ + float4x4 Transform; +} + + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float4 Colour0 : COLOR0; + float4 Tangent : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; // 0 xyzw 0 POS float xyzw + float4 o0 : TEXCOORD0; // 0 xyzw 0 NONE float + float4 o1 : TEXCOORD1; // 1 xyzw 1 NONE float xyzw + float4 o2 : TEXCOORD2; // 2 xyzw 2 NONE float xyzw + float4 o3 : TEXCOORD3; // 3 xyzw 3 NONE float xyzw + float2 o4 : TEXCOORD4; // 4 xy 4 NONE float xy + float4 o5 : TEXCOORD5; // 5 xyzw 5 NONE float xyzw + float4 o6 : TEXCOORD6; // 6 xyzw 6 NONE float xy w + float4 o7 : TEXCOORD7; // 7 xyzw 7 NONE float xyzw + float3 o8 : TEXCOORD8; // 8 xyz 8 NONE float xyz + float4 o9 : TEXCOORD9; // 9 xyzw 9 NONE float xyzw +}; + + + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + + + float3 spos = input.Position.xyz * Scale.xyz*0.05; + float3 bpos = mulvq(spos, Orientation); + float3 opos = CamRel.xyz + bpos; + float4 cpos = mul(float4(opos, 1), ViewProj); + + float3 tnorm = input.Normal; + float3 bnorm = normalize(mulvq(tnorm, Orientation)); + + float4 vc = input.Colour0; + float2 tc = input.Texcoord0; + + float2 o4xy = (gUVOffset[0].xy * cloudLayerAnimScale1) + (tc * gRescaleUV1) + gUVOffset1; + float2 o5xy = (gUVOffset[0].zw * cloudLayerAnimScale2) + (tc * gRescaleUV2) + gUVOffset2; + float2 o5zw = (gUVOffset[1].xy * cloudLayerAnimScale3) + (tc * gRescaleUV3) + gUVOffset3; + + + output.Position = cpos; + output.o0 = 0; + output.o1 = float4(bnorm, vc.w); + output.o2 = float4(0, 0, 0, vc.y); + output.o3 = float4(0, 0, 0, vc.z); + output.o4 = o4xy; + output.o5 = float4(o5xy, o5zw); + output.o6 = 0; + output.o7 = 0; + output.o8 = 0; + output.o9 = 0; + + return output; +} + + + + + + + + + +/* +//clouds_animsoft.fxc_VSCloudsVertScatterPiercing + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer rage_matrices +// { +// +// row_major float4x4 gWorld; // Offset: 0 Size: 64 +// row_major float4x4 gWorldView; // Offset: 64 Size: 64 [unused] +// row_major float4x4 gWorldViewProj; // Offset: 128 Size: 64 +// row_major float4x4 gViewInverse; // Offset: 192 Size: 64 [unused] +// +// } +// +// cbuffer rage_clipplanes +// { +// +// float4 ClipPlanes; // Offset: 0 Size: 16 +// +// } +// +// cbuffer lighting_globals +// { +// +// float4 gDirectionalLight; // Offset: 0 Size: 16 [unused] +// float4 gDirectionalColour; // Offset: 16 Size: 16 [unused] +// int gNumForwardLights; // Offset: 32 Size: 4 [unused] +// float4 gLightPositionAndInvDistSqr[8];// Offset: 48 Size: 128 [unused] +// float4 gLightDirectionAndFalloffExponent[8];// Offset: 176 Size: 128 [unused] +// float4 gLightColourAndCapsuleExtent[8];// Offset: 304 Size: 128 [unused] +// float gLightConeScale[8]; // Offset: 432 Size: 116 [unused] +// float gLightConeOffset[8]; // Offset: 560 Size: 116 [unused] +// float4 gLightNaturalAmbient0; // Offset: 688 Size: 16 [unused] +// float4 gLightNaturalAmbient1; // Offset: 704 Size: 16 [unused] +// float4 gLightArtificialIntAmbient0;// Offset: 720 Size: 16 [unused] +// float4 gLightArtificialIntAmbient1;// Offset: 736 Size: 16 [unused] +// float4 gLightArtificialExtAmbient0;// Offset: 752 Size: 16 [unused] +// float4 gLightArtificialExtAmbient1;// Offset: 768 Size: 16 [unused] +// float4 gDirectionalAmbientColour; // Offset: 784 Size: 16 [unused] +// float4 globalFogParams[5]; // Offset: 800 Size: 80 +// float4 globalFogColor; // Offset: 880 Size: 16 +// float4 globalFogColorE; // Offset: 896 Size: 16 +// float4 globalFogColorN; // Offset: 912 Size: 16 +// float4 globalFogColorMoon; // Offset: 928 Size: 16 +// float4 gReflectionTweaks; // Offset: 944 Size: 16 [unused] +// +// } +// +// cbuffer clouds_locals +// { +// +// float3 gSkyColor; // Offset: 0 Size: 12 [unused] +// float3 gEastMinusWestColor; // Offset: 16 Size: 12 [unused] +// float3 gWestColor; // Offset: 32 Size: 12 [unused] +// float3 gSunDirection; // Offset: 48 Size: 12 +// float3 gSunColor; // Offset: 64 Size: 12 +// float3 gCloudColor; // Offset: 80 Size: 12 [unused] +// float3 gAmbientColor; // Offset: 96 Size: 12 [unused] +// float3 gBounceColor; // Offset: 112 Size: 12 [unused] +// float4 gDensityShiftScale; // Offset: 128 Size: 16 [unused] +// float4 gScatterG_GSquared_PhaseMult_Scale;// Offset: 144 Size: 16 +// float4 gPiercingLightPower_Strength_NormalStrength_Thickness;// Offset: 160 Size: 16 +// float3 gScaleDiffuseFillAmbient; // Offset: 176 Size: 12 [unused] +// float3 gWrapLighting_MSAARef; // Offset: 192 Size: 12 [unused] +// float4 gNearFarQMult; // Offset: 208 Size: 16 [unused] +// float3 gAnimCombine; // Offset: 224 Size: 12 [unused] +// float3 gAnimSculpt; // Offset: 240 Size: 12 [unused] +// float3 gAnimBlendWeights; // Offset: 256 Size: 12 [unused] +// float4 gUVOffset[2]; // Offset: 272 Size: 32 +// row_major float4x4 gCloudViewProj; // Offset: 304 Size: 64 +// float4 gCameraPos; // Offset: 368 Size: 16 +// float2 gUVOffset1; // Offset: 384 Size: 8 +// float2 gUVOffset2; // Offset: 392 Size: 8 +// float2 gUVOffset3; // Offset: 400 Size: 8 +// float2 gRescaleUV1; // Offset: 408 Size: 8 +// float2 gRescaleUV2; // Offset: 416 Size: 8 +// float2 gRescaleUV3; // Offset: 424 Size: 8 +// float gSoftParticleRange; // Offset: 432 Size: 4 [unused] +// float gEnvMapAlphaScale; // Offset: 436 Size: 4 [unused] +// float2 cloudLayerAnimScale1; // Offset: 440 Size: 8 +// float2 cloudLayerAnimScale2; // Offset: 448 Size: 8 +// float2 cloudLayerAnimScale3; // Offset: 456 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// rage_clipplanes cbuffer NA NA cb0 1 +// rage_matrices cbuffer NA NA cb1 1 +// lighting_globals cbuffer NA NA cb3 1 +// clouds_locals cbuffer NA NA cb12 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyzw 0 NONE float xyzw +// COLOR 0 xyzw 1 NONE float xyzw +// NORMAL 0 xyz 2 NONE float xyz +// TEXCOORD 0 xy 3 NONE float xy +// TANGENT 0 xyzw 4 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xyzw 0 NONE float xyzw +// TEXCOORD 1 xyzw 1 NONE float xyzw +// TEXCOORD 2 xyzw 2 NONE float xyzw +// TEXCOORD 3 xyzw 3 NONE float xyzw +// TEXCOORD 4 xy 4 NONE float xy +// TEXCOORD 5 xyzw 5 NONE float xyzw +// TEXCOORD 6 xyzw 6 NONE float xyzw +// TEXCOORD 7 xyzw 7 NONE float xyzw +// TEXCOORD 8 xyz 8 NONE float xyz +// TEXCOORD 9 xyzw 9 NONE float xyzw +// SV_Position 0 xyzw 10 POS float xyzw +// SV_ClipDistance 0 xyzw 11 CLIPDST float xyzw +// +vs_4_0 +dcl_constantbuffer CB1[12], immediateIndexed +dcl_constantbuffer CB0[1], immediateIndexed +dcl_constantbuffer CB3[59], immediateIndexed +dcl_constantbuffer CB12[29], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xyzw +dcl_input v2.xyz +dcl_input v3.xy +dcl_input v4.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xyzw +dcl_output o3.xyzw +dcl_output o4.xy +dcl_output o5.xyzw +dcl_output o6.xyzw +dcl_output o7.xyzw +dcl_output o8.xyz +dcl_output o9.xyzw +dcl_output_siv o10.xyzw, position +dcl_output_siv o11.xyzw, clip_distance +dcl_temps 5 +mul r0.xyz, v0.yyyy, gWorld[1].xyzx +mad r0.xyz, v0.xxxx, gWorld[0].xyzx, r0.xyzx +mad r0.xyz, v0.zzzz, gWorld[2].xyzx, r0.xyzx +mad r0.xyz, v0.wwww, gWorld[3].xyzx, r0.xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +sqrt r1.w, r0.w +rsq r0.w, r0.w +mul r2.xyz, r0.wwww, r0.xyzx +div r1.xyz, r0.xyzx, r1.wwww +mov o0.xyzw, r1.xyzw + +mul r3.xyz, v2.yyyy, gWorld[1].xyzx +mad r3.xyz, v2.xxxx, gWorld[0].xyzx, r3.xyzx +mad r3.xyz, v2.zzzz, gWorld[2].xyzx, r3.xyzx +dp3 r0.w, r3.xyzx, r3.xyzx +rsq r0.w, r0.w +mul o1.xyz, r0.wwww, r3.xyzx +mov o1.w, v1.w + +mul r3.xyz, v4.yyyy, gWorld[1].xyzx +mad r3.xyz, v4.xxxx, gWorld[0].xyzx, r3.xyzx +mad r3.xyz, v4.zzzz, gWorld[2].xyzx, r3.xyzx +dp3 r0.w, r3.xyzx, r3.xyzx +rsq r0.w, r0.w +mul o2.xyz, r0.wwww, r3.xyzx +mov o2.w, v1.y + +mul r3.xyz, v2.yzxy, v4.zxyz +mad r3.xyz, v4.yzxy, v2.zxyz, -r3.xyzx +mul r3.xyz, r3.xyzx, v4.wwww +mul r4.xyz, r3.yyyy, gWorld[1].xyzx +mad r3.xyw, r3.xxxx, gWorld[0].xyxz, r4.xyxz +mad r3.xyz, r3.zzzz, gWorld[2].xyzx, r3.xywx +dp3 r0.w, r3.xyzx, r3.xyzx +rsq r0.w, r0.w +mul o3.xyz, r0.wwww, r3.xyzx +mov o3.w, v1.z + +mad r3.xy, v3.xyxx, gRescaleUV1.xyxx, gUVOffset1.xyxx +mad o4.xy, gUVOffset[0].xyxx, cloudLayerAnimScale1.xyxx, r3.xyxx + +mad r3.xy, v3.xyxx, gRescaleUV2.xyxx, gUVOffset2.xyxx +mad o5.xy, gUVOffset[0].zwzz, cloudLayerAnimScale2.xyxx, r3.xyxx + +mad r3.xy, v3.xyxx, gRescaleUV3.xyxx, gUVOffset3.xyxx +mad o5.zw, gUVOffset[1].xxxy, cloudLayerAnimScale3.xxxy, r3.xxxy + +mul r3.xyzw, r0.yyyy, gCloudViewProj[1].xyzw +mad r3.xyzw, r0.xxxx, gCloudViewProj[0].xyzw, r3.xyzw +mad r3.xyzw, r0.zzzz, gCloudViewProj[2].xyzw, r3.xyzw +add r3.xyzw, r3.xyzw, gCloudViewProj[3].xyzw +mul r0.xyw, r3.xwxy, l(0.500000, 0.500000, 0.000000, 0.500000) +mad o6.y, r3.w, l(0.500000), -r0.w +add o6.x, r0.y, r0.x +mov o6.zw, r3.wwww + +dp3 r0.x, -r1.xyzx, gSunDirection.xyzx +mad r0.xyw, -r0.xxxx, gSunDirection.xyxz, -r1.xyxz +dp3 r1.x, r1.xyzx, gSunDirection.xyzx +dp3 r1.y, r0.xywx, r0.xywx +rsq r1.y, r1.y +mul o7.xyz, r0.xywx, r1.yyyy + +mov_sat r0.x, r1.x +log r0.x, r0.x +mul r0.x, r0.x, gPiercingLightPower_Strength_NormalStrength_Thickness.x +exp o7.w, r0.x + +dp2 r0.x, r1.xxxx, gScatterG_GSquared_PhaseMult_Scale.xxxx +mad r0.y, r1.x, r1.x, l(1.000000) +add r0.w, gScatterG_GSquared_PhaseMult_Scale.y, l(1.000000) +add r0.x, -r0.x, r0.w +log r0.x, |r0.x| +mul r0.x, r0.x, l(1.500000) +exp r0.x, r0.x +div r0.x, r0.y, r0.x +mul r0.x, r0.x, gScatterG_GSquared_PhaseMult_Scale.z +mul r0.xyw, r0.xxxx, gSunColor.xyxz +mul o8.xyz, r0.xywx, gScatterG_GSquared_PhaseMult_Scale.wwww + +dp3_sat r0.x, r2.xyzx, globalFogParams[3].xyzx +dp3_sat r0.y, r2.xyzx, globalFogParams[4].xyzx +log r0.y, r0.y +mul r0.y, r0.y, globalFogParams[4].w +exp r0.y, r0.y +log r0.x, r0.x +mul r0.x, r0.x, globalFogParams[3].w +exp r0.x, r0.x +add r1.xyz, -globalFogColorE.xyzx, globalFogColorMoon.xyzx +mad r1.xyz, r0.yyyy, r1.xyzx, globalFogColorE.xyzx +add r2.xyz, -r1.xyzx, globalFogColor.xyzx +mad r0.xyw, r0.xxxx, r2.xyxz, r1.xyxz +add r0.xyw, r0.xyxw, -globalFogColorN.xyxz +add r1.x, r1.w, -globalFogParams[0].x +max r1.x, r1.x, l(0.000000) +mul r1.y, r1.x, -globalFogParams[1].z +mul r1.y, r1.y, l(1.442695) +exp r1.y, r1.y +add r1.y, -r1.y, l(1.000000) +mad r0.xyw, r1.yyyy, r0.xyxw, globalFogColorN.xyxz +div r1.y, r1.x, r1.w +mul r1.x, r1.x, globalFogParams[1].w +mul r0.z, r0.z, r1.y +lt r1.y, l(0.010000), |r0.z| +mul r0.z, r0.z, globalFogParams[2].z +mul r1.z, r0.z, l(-1.442695) +exp r1.z, r1.z +add r1.z, -r1.z, l(1.000000) +div r0.z, r1.z, r0.z +movc r0.z, r1.y, r0.z, l(1.000000) +mul r0.z, r0.z, r1.x +min r0.z, r0.z, l(1.000000) +mul r0.z, r0.z, l(1.442695) +exp r0.z, r0.z +min r0.z, r0.z, l(1.000000) +add r0.z, -r0.z, l(1.000000) +mul_sat r0.z, r0.z, globalFogParams[2].y +add r1.x, -v1.x, l(1.000000) +max r0.z, r0.z, r1.x +mul r0.xyw, r0.zzzz, r0.xyxw +add r0.z, -r0.z, l(1.000000) +mul r1.y, r1.x, globalFogParams[2].w +mad r1.x, -r1.x, globalFogParams[2].w, l(1.000000) +mul r2.x, r1.y, globalFogColor.w +mul r2.y, r1.y, globalFogColorE.w +mul r2.z, r1.y, globalFogColorN.w +mad o9.xyz, r0.xywx, r1.xxxx, r2.xyzx +mul o9.w, r0.z, r1.x + +lt r0.x, r3.z, l(0.000000) +div r0.y, l(0.100000), r3.w +movc r0.x, r0.x, r0.y, r3.z +lt r0.y, r3.w, r3.z +add r0.z, r3.w, l(-0.100000) +movc r0.y, r0.y, r0.z, r3.z +ne r0.z, l(0.000000, 0.000000, 0.000000, 0.000000), gCameraPos.w +movc r0.x, r0.z, r0.x, r0.y +lt r0.y, l(0.000000), r3.w +movc o10.z, r0.y, r0.x, r3.z +mov o10.xyw, r3.xyxw + +mul r0.xyzw, v0.yyyy, gWorldViewProj[1].xyzw +mad r0.xyzw, v0.xxxx, gWorldViewProj[0].xyzw, r0.xyzw +mad r0.xyzw, v0.zzzz, gWorldViewProj[2].xyzw, r0.xyzw +add r0.xyzw, r0.xyzw, gWorldViewProj[3].xyzw +dp4 o11.x, r0.xyzw, ClipPlanes.xyzw +mov o11.yzw, l(0,0,0,0) + +ret +// Approximately 135 instruction slots used + + + +*/ \ No newline at end of file diff --git a/Shaders/CodeWalkerShaders.vcxproj b/Shaders/CodeWalkerShaders.vcxproj new file mode 100644 index 0000000..35be97d --- /dev/null +++ b/Shaders/CodeWalkerShaders.vcxproj @@ -0,0 +1,551 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {0D14B076-0ABF-434E-AB9F-36E7800D8887} + CodeWalkerShaders + 8.1 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + $(ProjectDir)%(Filename).cso + 4.0 + + + + + Level3 + Disabled + true + + + $(ProjectDir)%(Filename).cso + 4.0 + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + $(ProjectDir)%(Filename).cso + 4.0 + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + $(ProjectDir)%(Filename).cso + 4.0 + + + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + 4.0 + 4.0 + 4.0 + 4.0 + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + + + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + + + Pixel + Pixel + Pixel + Pixel + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + + + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + + + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + Compute + 4.0 + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Vertex + Vertex + Vertex + Vertex + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Shaders/CodeWalkerShaders.vcxproj.filters b/Shaders/CodeWalkerShaders.vcxproj.filters new file mode 100644 index 0000000..6a0df68 --- /dev/null +++ b/Shaders/CodeWalkerShaders.vcxproj.filters @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Shaders/Common.hlsli b/Shaders/Common.hlsli new file mode 100644 index 0000000..569aa20 --- /dev/null +++ b/Shaders/Common.hlsli @@ -0,0 +1,169 @@ + + + +struct ShaderGlobalLightParams +{ + float3 LightDir; + float LightHdr; //global intensity + float4 LightDirColour; + float4 LightDirAmbColour; + float4 LightNaturalAmbUp; + float4 LightNaturalAmbDown; + float4 LightArtificialAmbUp; + float4 LightArtificialAmbDown; +}; + + + + + +//for unpacking colours etc +uint4 Unpack4x8(uint v) +{ + return uint4(v >> 24, v >> 16, v >> 8, v) & 0xFF; +} +float4 Unpack4x8UNF(uint v) +{ + float4 u = (float4)Unpack4x8(v); + return u*0.0039215686274509803921568627451f;// u * 1/255 +} + + + +float DepthFunc(float2 zw) +{ + return zw.x;// + + //return zw.x * (0.1 + 0.00001*(abs(zw.y))); + //return zw.x * (0.1 + 0.00001*((zw.y))); + + + + //const float far = 1000.0; //outerra version - needs logz written to frag depth in PS... + //const float C = 0.01; //~10m linearization + //const float FC = 1.0/log(far*C + 1); + //////logz = gl_Position.w*C + 1; //version with fragment code + ////logz = log(gl_Position.w*C + 1)*FC; + ////gl_Position.z = (2*logz - 1)*gl_Position.w; + //float logz = log(zw.y*C + 1)*FC; + //return (2*logz - 1)*zw.y; + +} + + + + + + +float3 GeomWindMotion(float3 ipos, float3 vc0, float4 windvec, float4 overrideparams) +{ + + //lt r1.x, r0.x, l(1.000000) + //mul r1.yzw, v2.xxxz, cb12[0].xxxy //umGlobalParams + //mul r1.yzw, r1.yyzw, cb9[13].xxxy //umGlobalOverrideParams + //add r2.x, v2.y, cb9[0].w //_worldPlayerPos_umGlobalPhaseShift + //mul r2.x, |r2.x|, l(6.283185) + //mul r2.yzw, cb9[13].zzzw, cb12[0].zzzw //umGlobalOverrideParams, umGlobalParams + //mad r2.xyz, cb2[12].xxxx, r2.yzwy, r2.xxxx //globalScalars2 + //sincos r2.xyz, null, r2.xyzx + //mad r1.yzw, r2.xxyz, r1.yyzw, v0.xxyz + //movc r1.xyz, r1.xxxx, r1.yzwy, v0.xyzx + //add r1.w, -r0.x, l(1.000000) + //mul r0.xyz, r0.yzwy, r0.xxxx + //mad r0.xyz, r1.wwww, r1.xyzx, r0.xyzx + //mul r1.xyzw, r0.yyyy, cb1[9].xyzw + //mad r1.xyzw, r0.xxxx, cb1[8].xyzw, r1.xyzw + //mad r0.xyzw, r0.zzzz, cb1[10].xyzw, r1.xyzw + //add o0.xyzw, r0.xyzw, cb1[11].xyzw //screen pos out + //mov o1.xy, v4.xyxx + + float3 f1 = vc0.xxz * windvec.xxy * overrideparams.xxy; + float phase = vc0.y + 0.0; //playerpos/global phase shift? + float phrad = abs(phase)*6.283185; + float3 f2 = windvec.zzw * overrideparams.zzw + phrad; //globalScalars2 + f2 = sin(f2); + f1 = f2*f1 + ipos; + return f1; + + //return ipos; +} + + + + +float3 NormalMap(float2 nmv, float bumpinezz, float3 norm, float3 tang, float3 bita) +{ + //r1 = nmv; //sample r1.xyzw, v2.xyxx, t2.xyzw, s2 (BumpSampler) + //float bmp = max(bumpinezz, 0.001); //max r0.x, bumpiness, l(0.001000) + float2 nxy = nmv.xy * 2 - 1; //mad r0.yz, r1.xxyx, l(0.000000, 2.000000, 2.000000, 0.000000), l(0.000000, -1.000000, -1.000000, 0.000000) + float2 bxy = nxy * max(bumpinezz, 0.001); //mul r0.xw, r0.xxxx, r0.yyyz + float bxyz = sqrt(abs(1 - dot(nxy, nxy))); //r0.y = dot(nxy, nxy); //dp2 r0.y, r0.yzyy, r0.yzyy //r0.y = 1.0 - r0.y; //add r0.y, -r0.y, l(1.000000) //r0.y = sqrt(abs(r0.y)); //sqrt r0.y, |r0.y| + float3 t1 = tang * bxy.x; //mad r0.xzw, r0.xxxx, v4.xxyz, r1.xxyz + float3 t2 = bita * bxy.y + t1; //mul r1.xyz, r0.wwww, v5.xyzx + float3 t3 = norm * bxyz + t2; //mad r0.xyz, r0.yyyy, v3.xyzx, r0.xzwx + return normalize(t3); + //r0.w = dot(t3, t3); //dp3 r0.w, r0.xyzx, r0.xyzx + //r0.w = 1.0 / sqrt(r0.w); //rsq r0.w, r0.w + ////r1.x = r0.z*r0.w - 0.35; //mad r1.x, r0.z, r0.w, l(-0.350000) + //t3 = t3*r0.w; //mul r0.xyz, r0.wwww, r0.xyzx + ////mad o1.xyz, t3.xyzx, l(0.500000, 0.500000, 0.500000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) + //return t3; +} + + + + +float3 BasicLighting(float4 lightcolour, float4 ambcolour, float pclit) +{ + return (ambcolour.rgb + lightcolour.rgb*pclit); +} + +float3 AmbientLight(float3 diff, float normz, float4 upcolour, float4 downcolour, float amount) +{ + float bf = normz*0.5 + 0.5; + float3 upval = upcolour.rgb*saturate(1.0-bf); + float3 downval = downcolour.rgb*saturate(bf); + return diff*(upval + downval)*amount; + //return (float3)0; +} + +float3 GlobalLighting(float3 diff, float3 norm, float4 vc0, float lf, uniform ShaderGlobalLightParams globalLights) +{ + float3 c = saturate(diff); + float3 fc = c; + float naturalDiffuseFactor = 1.0; + float artificialDiffuseFactor = saturate(vc0.g); + c *= BasicLighting(globalLights.LightDirColour, globalLights.LightDirAmbColour, lf); + c += AmbientLight(fc, norm.z, globalLights.LightNaturalAmbUp, globalLights.LightNaturalAmbDown, naturalDiffuseFactor); + c += AmbientLight(fc, norm.z, globalLights.LightArtificialAmbUp, globalLights.LightArtificialAmbDown, artificialDiffuseFactor); + return c; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Shaders/DistantLightsPS.cso b/Shaders/DistantLightsPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..422b6e9b5faaecd5522bcd0bebc3bcf83b682a4f GIT binary patch literal 672 zcmaJ-O-lk%6uqTUE=rdzB4$xgAYv(Eo52+hBM1ypI7V;tIGx&+ zd)ccAL1y#3;kGMX+G|#Oor_N0Ro3ivC1(m#5sk`Ot*5A+cDLCANyQSetyDZ7+ejtS zN%A}|FS3Oe{5Z=TPz1O*gUlBO=e)95AH9Rrq==Js&K$;oI5;j^BJbp_0y%nFwJcjB z)iN!cJPSLc=wlDwsQ|Km?u3Vvv9r2^pdzQ)w`ke{R)IracM<_3Dlg&}b$wnc5uHXT zuo;Pr{Fx8HITx}928!R;KvdqZ6NLukYsPrSxc2YTKTR|%=ZuAM@3QZ?jn5EH#&O{# T{|o3Z&UfB5ss4MLG$ZwI0IW}D literal 0 HcmV?d00001 diff --git a/Shaders/DistantLightsPS.hlsl b/Shaders/DistantLightsPS.hlsl new file mode 100644 index 0000000..34c13a6 --- /dev/null +++ b/Shaders/DistantLightsPS.hlsl @@ -0,0 +1,16 @@ + +Texture2D Lightmap : register(t0); +SamplerState TextureSS : register(s0); + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float2 Texcoord : TEXCOORD0; + float4 Colour : COLOR0; +}; + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + //return float4(1,0,0,1); + return Lightmap.Sample(TextureSS, input.Texcoord) * input.Colour; +} diff --git a/Shaders/DistantLightsVS.cso b/Shaders/DistantLightsVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..df0188b5979748a65a2c7ae46a5741a5ddd4f45f GIT binary patch literal 1904 zcmaJ>O>0v@6uoJxNlURGx^SWJC|xK@iERm0v8MTWCK#KL7ej?YjqS5dP4hw$Yd1>l zLKH+?iMS9EK_MG|gkTqS?+qExNrOG|cDa+bAZm+V}=Qk4dCd!b*TuUl%cC-WEZ zrTc-l`00d%pyYZ=*<)Dgqqh1l!e57PK>4Rsd=%?T_}H70RQ_DSew3~_Ytm>myy69} zBSeTLN*fZ%ucsYw_W-AAN#~aX%#)^H6$DsQTb_g5wv{~=E86RJsV1mas1=+NlG|%W zoTBrvBB*&1y^d-=#`d`~-(vj$f)u;ce~2 zNG z@5%8l;zr_JlbJ+?|EOc`(|Y}CtD>`y+$e`U6rY=lH!*z|lP&Su=iXsFjGl+JG}f>9^A0M8 z`yOw6?pZp;v(}HDoon6ughI@lP<4L~D(-4tFpvHbV0?E|#h7&i7Kf}kuYSH^C!D`+ z=JOpp;rxGw_$t6Dt@p)v{m#VPJE>nECLcq^;|(c#_PHlM+6Cvk6AyR6*^~HI7u*Y+ zob+$P#2v9_lP7YRuXxVPU~8F)0OyW=ij|$s*07$1vKEDRfSyg^eX`#Fq#frSQ`-Hm H_vrgC9D}pI literal 0 HcmV?d00001 diff --git a/Shaders/DistantLightsVS.hlsl b/Shaders/DistantLightsVS.hlsl new file mode 100644 index 0000000..b06ceea --- /dev/null +++ b/Shaders/DistantLightsVS.hlsl @@ -0,0 +1,57 @@ +#include "Common.hlsli" + + +struct VS_INPUT +{ + float4 Position : POSITION; + float2 Texcoord : TEXCOORD0; +}; +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float2 Texcoord : TEXCOORD0; + float4 Colour : COLOR0; +}; + +struct DistLODLight +{ + float3 Position; + uint Colour; +}; +StructuredBuffer LightInstances : register(t0); + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4x4 ViewInv; + float3 CamPos; + float Pad0; +}; + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + + DistLODLight light = LightInstances[iid]; + float4 ipos = float4(light.Position - CamPos, 1.0); + float4 vpos = float4(input.Position.xy, 0.0, 0.0);// *20.0f; + + float4 rgbi = Unpack4x8UNF(light.Colour).gbar; + + float dist = length(ipos.xyz); + float size = rgbi.a * min(dist, 50); + + float3 offs = vpos.xyz * min(size*0.1f, 3.0f); + float3 tpos = mul(offs, (float3x3)ViewInv); + ipos.xyz += tpos; + + float4 opos = mul(ipos, ViewProj); + //opos.xy += offs * opos.w; + + output.Position = opos;// +vpos; + output.Texcoord = input.Texcoord; + output.Colour = float4(rgbi.rgb, 0.25); + + return output; +} \ No newline at end of file diff --git a/Shaders/MarkerPS.cso b/Shaders/MarkerPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..71e1845d4dc7799d33d2a9a03be92335455aefa9 GIT binary patch literal 596 zcmaJ-%}N4M82w74T12xf3YvBWA(kRW5ZcW61LnxwYe)oTIijG&KzyR6xwEX#J4q}4EN+c7aVv@v&YQpa<3P+@v5 z`eoiJS`tm7WI8Pr<-m3DoL9Kgpoki4_znJ8*Xu;r8pRGYZM27rx*vUy;yc}RIzguBiv&V0oh5xcyJ<9(DHxoxK literal 0 HcmV?d00001 diff --git a/Shaders/MarkerPS.hlsl b/Shaders/MarkerPS.hlsl new file mode 100644 index 0000000..9860112 --- /dev/null +++ b/Shaders/MarkerPS.hlsl @@ -0,0 +1,15 @@ + +Texture2D Colourmap : register(t0); +SamplerState TextureSS : register(s0); + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float2 Texcoord : TEXCOORD0; +}; + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + //return float4(1,0,0,1); + return Colourmap.Sample(TextureSS, input.Texcoord); +} diff --git a/Shaders/MarkerVS.cso b/Shaders/MarkerVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..d9cc5781917c485155013bd02d8c655ddb78daf7 GIT binary patch literal 1372 zcma)5&uddb5T53Twk6bBJV^Dh^rV*%(-P{%rb!wbNc+Ou5GoXENMCF;P2?qL^xXO8ViZshQ5b>kBHd0mHcNEA(TBR?PaJ${`?i-uc4cahX}c; zJE!EBuV`I!T27_vcHpm7-FuGf1-)L6++pZj=pi%^auQE~Km{P|PvfUyIqPo|$52O% zdJ?|?d>`1f!4+akrQtj*x$V1x8N%2pg1CxoQt|ot^;9Aezm}R`T;Q1s`sR8OG-Tr}i$0~d@?I(D&WbGiuD25BxM4UY zOBc!oYhB7K8(GV;b0D?ASweo0)9djVzzLf(K24u9CZa1_!)SYYHD@c3rm_2T^xVSN zmw%zyE)&oo=04ne3$*SuZ`t>g@R_@Vz9Z%1j2+Y^5!1)_6yhu?T*pW6g#e@h^kshu zU&<2l(G2qJ8B6;~+}*?xFz#J>raX{$${D>n`0Ps>-n^*|FxLE-^!tPU_zYJ1{oH{KS2JG$a1Abb{dG4>wOjE|1_XzTH zBl6^6e`Z9UcgXy~h`f2DXz*@%^R_qe9J;(*?xLR)v5vy~nDjh<3C?f=I@RTU{g37%g5FW2n|7=1jMTjawV38m-m59 z5UQ*qRpNrUgHVM~C>T!kzyUav9yoL2$cYn&DB{3RTKK-VGiJMWLOs&FpP6~z%$s@d z?H*s8nH@QL@W$wg$G`jLO#6i&zP|E#LPTy4i0nZ>0shnzxe2}vo`-zl_*}k(aT2Ev2%y(yLTRaq!D)+Rx>Cb4WCvks_gYp4v#$urSHC?-j zG51;1c?&&d#Gw2Gm0w5ydqn=F%D+Yb2jm&G|54>DOUsuF%d53Y@qDqoQff93d;$?A zfc!9QNh?d$^(MCYX8BUH1ii?k&?|t`m)9;A>y4t*aqYc2ENztEE<)-#cA#iB)y(#= zt@GizN^!Ng)?^-;ohY8IVUD=(VKyL(Ih={SSiV@VHma{Ta|ahja`UGOr*ehT@}*)u zH(On;l`9xbjvg63Iyp8rdU*24)C8QJESz|W`601C9h(>C=N8||iUc@OOYr+fMiQ^0 z1o`)KT;l4scmRp3g%vz^&ehw^xi#+dV|KqhLUU)o#BBtgupi&&NeMmA>vbO6&HwCL zkbQ`??1@Ew632GGo)#Y%i9qB}oc|$&|Fp^}tHag@wy&~D;LPZF5b_a`^evsgk_}_$ zx+K=YhkpS&`rGIabslsi?uRxc*!3I6hUSCk#|zLX@otia;g4|>b5MKwBRvD%xXOO@ zLx0zFj<_@Q!F67MCPvRYg)r+_~L8xnIx+rd_j zQ+F5eMx{-ENbN$5U>YWV9WvtNy=aW{xA2-NyLWB}J9@c?y85c_fA`qlNF4P4+sjka z77zB2wm3F4e-_U;wm}{DWik)z+g}`-Hik;P0FAV;Cu5fzhns}P*0LuSa0kq1T;~Na z=-?1fgz-o1qnI~PgSwu3JJVcaxZfX;#2K7>tAp93VRIVtt6CS6zXdsJ(#hp9)my%X zptCj1W#_I09?x_~XX|LgI|g4FTW2~ya#nWp`IPh}%|Fkj)x_7>=!2Bs3hzJS$ZkQG zge--)yg=kH#PBzG8+-?BIJ}d@p=}(8=ldu1k-|NvZR))o+VDL=9sQ`DwKY9$Qn*tj z^F=-HZ#Q4NVL99`SjN>&m`V)$}JD{!<Y3ACvD`n5V#R$jUaMo8T+Yy2?&*iQr|tjcp0<_;pW|2_sAukb#p>Syi#hET3%|Yh#YGI}^g*y_ zV|(QPuk8^zb^i*~+uO*qV0m=%U3~D3qK&=7`Kvk1+*>Z!lHt2Bq~BP|`Ck!z51CgI zzTtcLZW1f3S8Ez?es)X$iC9Zgr lum : register( t1 ); +RWStructuredBuffer Result : register( u0 ); + +cbuffer cb0 +{ + float4 g_avSampleWeights[15]; + uint g_outputwidth; + float g_inverse; + int2 g_inputsize; +} + +#define kernelhalf 7 +#define groupthreads 128 +groupshared float4 temp[groupthreads]; + +[numthreads( groupthreads, 1, 1 )] +void main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex ) +{ + int2 coord = int2( GI - kernelhalf + (groupthreads - kernelhalf * 2) * Gid.x, Gid.y ); + coord = coord.xy * 8 + int2(4, 3); + coord = clamp( coord, int2(0, 0), int2(g_inputsize.x-1, g_inputsize.y-1) ); + float4 vColor = Input.Load( int3(coord, 0) ); + + float fLum = max(lum[0]*g_inverse, 0.75); + + // Bright pass and tone mapping + vColor = max( 0.0f, vColor - BRIGHT_THRESHOLD ); + vColor *= MIDDLE_GRAY / (fLum + 0.001f); + vColor *= (1.0f + vColor/LUM_WHITE); + vColor /= (1.0f + vColor); + + temp[GI] = vColor; + + GroupMemoryBarrierWithGroupSync(); + + // Horizontal blur + if ( GI >= kernelhalf && + GI < (groupthreads - kernelhalf) && + ( (Gid.x * (groupthreads - 2 * kernelhalf) + GI - kernelhalf) < g_outputwidth) ) + { + float4 vOut = 0; + + [unroll] + for ( int i = -kernelhalf; i <= kernelhalf; ++i ) + vOut += temp[GI + i] * g_avSampleWeights[i + kernelhalf]; + + Result[GI - kernelhalf + (groupthreads - kernelhalf * 2) * Gid.x + Gid.y * g_outputwidth] = float4(vOut.rgb, 1.0f); + } +} diff --git a/Shaders/PPBloomFilterVCS.cso b/Shaders/PPBloomFilterVCS.cso new file mode 100644 index 0000000000000000000000000000000000000000..c1c72733922b1820255d4956030c290039b718ad GIT binary patch literal 2568 zcmb7FO=}ZT6upzgG>KYkL69Ok*eY72)V79NL}S~;R;rbzV7m&nP18u)gnS4U7ongi z6mj8B5D`J4F5M~q1Q)syH@b19i_(?f@tm3W;xHt&xp4Dl?#H?Jo%`};cxrHH>SeU_ z;`8#mkB7f}{cwKzxgjEfkjOTyeb8ebkyFqy=xR`8VmKOGN01l3dr+?XpyG=U3GA<+ zH}J}QKa_YaPzs-^H=*>^^RL2JOPEU;UCNb;gQa@_GvzW^yFDKKfg*Y<_ia^=dtk(U_1+Q9Bo~uQMLXZd zSLsqO=R$fmpDkqPi{_Duqvpt1e9Vk5%*-Y8=1_Jqm(JiJ+|}E4GThzWbv)eL-v{u~ z__>SRJB91G>peaao$7BAiD2??(A(937}GcvvAZTyEbbrUU2^sm`1_FWpLSRM32rUo z5w1Ng9$CQ3bM%PEY5iYZ8MX(=b5_j<1wm#}wTOUGaoG7h`$UE7yoN4;v_1FBzLA2|V?qxak9 z=zFu=1LE^)9KAQ5)sU)D-P?veOK>0DfX|Bss`4@3m@ehGpT_z#=D&Vllo}Uz}H? zSQa0uFU`5ttK$3*c&6|i(yn=69db^a5y1~6re^2n!Rl9W&i|~tclya`qgd8=LiO&h z$$s@5n`+dgpWJVyrV}er2aDV{iiJ;Rl?%hv!M5G**B@7@86iZ zPh%@4vPGJqx4ibf(2jem6&MuqNC}lqYvs3`cX=2i InputBuf : register( t0 ); +Texture2D InputTex : register( t1 ); +RWStructuredBuffer Result : register( u0 ); + +cbuffer cb0 +{ + float4 g_avSampleWeights[15]; + int2 g_outputsize; + int2 g_inputsize; +} + +#define kernelhalf 7 +#define groupthreads 128 +groupshared float4 temp[groupthreads]; + +[numthreads( groupthreads, 1, 1 )] +void main( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex ) +{ + int offsety = GI - kernelhalf + (groupthreads - kernelhalf * 2) * Gid.y; + offsety = clamp( offsety, 0, g_inputsize.y-1 ); + int offset = Gid.x + offsety * g_inputsize.x; + temp[GI] = InputBuf[offset]; + + GroupMemoryBarrierWithGroupSync(); + + // Vertical blur + if ( GI >= kernelhalf && + GI < (groupthreads - kernelhalf) && + ( (GI - kernelhalf + (groupthreads - kernelhalf * 2) * Gid.y) < (uint)g_outputsize.y) ) + { + float4 vOut = 0; + + [unroll] + for ( int i = -kernelhalf; i <= kernelhalf; ++i ) + vOut += temp[GI + i] * g_avSampleWeights[i + kernelhalf]; + + Result[Gid.x + (GI - kernelhalf + (groupthreads - kernelhalf * 2) * Gid.y) * g_outputsize.x] = float4(vOut.rgb, 1.0f); + } +} + +//[numthreads( groupthreads, 1, 1 )] +//void CSHorizFilter( uint3 Gid : SV_GroupID, uint GI : SV_GroupIndex ) +//{ +// int2 coord = int2( GI - kernelhalf + (groupthreads - kernelhalf * 2) * Gid.x, Gid.y ); +// coord = clamp( coord, int2(0, 0), int2(g_inputsize.x-1, g_inputsize.y-1) ); +// temp[GI] = InputTex.Load( int3(coord, 0) ); +// +// GroupMemoryBarrierWithGroupSync(); +// +// // Horizontal blur +// if ( GI >= kernelhalf && +// GI < (groupthreads - kernelhalf) && +// ( (Gid.x * (groupthreads - 2 * kernelhalf) + GI - kernelhalf) < g_outputsize.x) ) +// { +// float4 vOut = 0; +// +// [unroll] +// for ( int i = -kernelhalf; i <= kernelhalf; ++i ) +// vOut += temp[GI + i] * g_avSampleWeights[i + kernelhalf]; +// +// Result[GI - kernelhalf + (groupthreads - kernelhalf * 2) * Gid.x + Gid.y * g_outputsize.x] = float4(vOut.rgb, 1.0f); +// } +//} diff --git a/Shaders/PPCopyPixelsPS.cso b/Shaders/PPCopyPixelsPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..052c970d6d334062746e48ac7a873a6d29d4a138 GIT binary patch literal 896 zcmZ`%ze`(D82u8X)GSI}q&VEc!HR@5N>C^zn!J|;(!7xSkQ4-o@kLXTCZy?F{0lmC z>f8<;vUKd`BxDp^9r_121nJg7dQRTGrG@yxx%WHg`|-Ya@6FW?vK!+@Q-8cVx?Row zy7_XQj)=&`oX7(9U7!bH1pEemMnz(XRdbG;1P7IKfcqLCvB^Z33-<_^2iOOaECV$9 zM1y38+4#x3W;5tZKISH0W@ly?K=tV?6_C&*E^_L0b-$u z^@s6n{+;3LPCMuXZw4|P4kI%6U(L%_qu+hoZ4T5%^{Fb9bV=#+`f1Qt*>0!TYQsq< zwiA2lWHRwAy}i4GCPkeuSJ0a?Jpy>XH2wqUrY*tAh3<5vZsYp!xZ>%eU-Zi2JGHFm zRdbxpL*Ffv$G!@%_O~wt)cgC@yyK%t7o6G{S_XIyye>%O6>iY|puoa!eg>BwPbECd zQzfy~a>zMTfU)mY$ng%M)L`+HxeeFkMl+P<(qKvs@iY!hUi?B$H7+TU#m7c}V)jj& zXZAHbEt?ZJ+E>)sS*#Yxgl*mT;fycvTiPuqc}Bbgn)dho0e1UNsWE2bemSU>;( literal 0 HcmV?d00001 diff --git a/Shaders/PPCopyPixelsPS.hlsl b/Shaders/PPCopyPixelsPS.hlsl new file mode 100644 index 0000000..e86b19c --- /dev/null +++ b/Shaders/PPCopyPixelsPS.hlsl @@ -0,0 +1,27 @@ +//-------------------------------------------------------------------------------------- +// File: DumpToTexture.hlsl +// +// The PS for converting CS output buffer to a texture, used in CS path of +// HDRToneMappingCS11 sample +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +StructuredBuffer buffer : register( t0 ); + +struct QuadVS_Output +{ + float4 Pos : SV_POSITION; + float2 Tex : TEXCOORD0; +}; + +cbuffer cbPS : register( b0 ) +{ + uint4 g_param; +}; + +float4 main( QuadVS_Output Input ) : SV_TARGET +{ + // To calculate the buffer offset, it is natural to use the screen space coordinates, + // Input.Pos is the screen space coordinates of the pixel being written + return buffer[ (Input.Pos.x - 0.5) + (Input.Pos.y - 0.5) * g_param.x ]; +} diff --git a/Shaders/PPFinalPassPS.cso b/Shaders/PPFinalPassPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..743bd5c81ca561d308c8d0e9e274362ed25262a9 GIT binary patch literal 1468 zcmZ`(&ubG=5S}FcWvw<84+a( zjdr(XIZ|qNtcIg*J?nwA?zd&FW!r68U#l9@?~{+Y7x9S)c-bfYEqvG`g>##9LWpHw zH~jmZ)o#OSw2>2ostl1Qew-fSpZoWdxt7(oIz6<|Cv(KD1_0!8bKSA;*|&SzsoH6+ zP%=uIvC+6?Iogul?lv)*mP*Ve&Zm;e#JSYm!aPWd#&WreT-KO?@;5+XIrU!CIA`hf zg?=}VgK>4WS}}@du~HT@S6`}BYFYMH0q1|w{*-QN>me=+CD=TikduNP0RB_J9_*z_Iv+=k)hXu|Z z&CA`uD%jr}kpnaS%SLoKAj*!R4tcSw35A*Tv6Gt`p{~q}jECdo`1G-~I5#AQO=Xb0 zZ=OB#_`=~pj9fpjETmQK9D3eCAM7pf&z67a&82pRp2r=(*D>Gbqh8Le$TVYaK75p@ zF4BK{Can}MiR$>sX8OOnyKs5AU-D4`yi=-XI2P53+{?uogZLoluo;QrjO-nAOgY-# z9-_L)%NNJeN&)-VX9|B0k9@rM#+&IyJhzcACi&ZSxnT`6WA tex : register( t0 ); +StructuredBuffer lum : register( t1 ); +Texture2D bloom : register( t2 ); + +SamplerState PointSampler : register (s0); +SamplerState LinearSampler : register (s1); + + +static const float MIDDLE_GRAY = 0.72f; +static const float LUM_WHITE = 1.5f; + +cbuffer cbPS : register( b0 ) +{ + float4 g_param; +}; + + +float4 main(VS_Output input) : SV_TARGET +{ + float4 vColor = tex.Sample(PointSampler, input.Tex); + float fLum = min(max(lum[0]*g_param.x, 0.2), 10); //limit amplification... + float3 vBloom = bloom.Sample(LinearSampler, input.Tex).rgb; + + // Tone mapping + vColor.rgb *= MIDDLE_GRAY / (fLum + 0.001f); + vColor.rgb *= (1.0f + vColor.rgb/LUM_WHITE); + vColor.rgb /= (1.0f + vColor.rgb); + + vColor.rgb += 0.6f * vBloom; + vColor.a = 1.0f; + + return vColor; +} \ No newline at end of file diff --git a/Shaders/PPFinalPassVS.cso b/Shaders/PPFinalPassVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..d595a8210e680d72acbe22d1a0be183b852e21a4 GIT binary patch literal 544 zcmZ>XaB?o%yw_osoY8cr^X+xH6MVliGB7YGFflN&0%;QIQ#ntxq!?K_HYSm0jhHVs#FBh z@jz{#1O$LA28MK?Pd_O@*dTLKfpSJbK8S4w3^tgYn;b-q5d#B1Ox_J@29pC&F$04= t5bp=GfCQ5RkbsDR#KFK0=+xj4$B+^r59S|`1k4X$ML+^%Hz|Nv^#F_SJOls$ literal 0 HcmV?d00001 diff --git a/Shaders/PPFinalPassVS.hlsl b/Shaders/PPFinalPassVS.hlsl new file mode 100644 index 0000000..5d4694b --- /dev/null +++ b/Shaders/PPFinalPassVS.hlsl @@ -0,0 +1,14 @@ +struct VS_Output +{ + float4 Pos : SV_POSITION; + float2 Tex : TEXCOORD0; +}; + +VS_Output main( float4 pos : POSITION ) +{ + VS_Output output; + output.Pos = pos; + output.Tex.x = (pos.x*0.5)+0.5; + output.Tex.y = (pos.y*-0.5)+0.5; + return output; +} \ No newline at end of file diff --git a/Shaders/PPLumBlendCS.cso b/Shaders/PPLumBlendCS.cso new file mode 100644 index 0000000000000000000000000000000000000000..4f217d3d7c636cfbc3badf8765250f82baff1115 GIT binary patch literal 988 zcmaJXeWrhU}2*W zu(Gi71N;Ju6gK{WjbPz9$-NjBb>QUg%$YNL?rf5)@kH%$Oq>Da{^Bpd z{T9?Ra(R2lawKtV+t#5Yg{`nusewg#1-bzp^g>+}KiUU9(*x@zSKZGdg1wyAr}81y z*GUo)RP}htIxMF11*dGI>cvb&Agkny$XMeW8?mHlJ%3&0L#dK=z}r--Rrj2~H1m4} zyL?pMc8uW4h>^*fS;O4T7cJXJln*L+@oD`Hx=tp?*;5sBi9t!r#Q5&NN0yzv>?o3Fvq0THw@B qT_9E8J@29XYXADwJ=3_FnVZQud?~ Target : register( t0 ); +RWStructuredBuffer Current : register( u0 ); + +cbuffer cb0 +{ + float BlendFactor; + float3 pad; +} + +[numthreads(1, 1, 1)] +void main( uint3 DTid : SV_DispatchThreadID ) +{ + float t = max(Target[0],0); + float c = max(Current[0],0); + Current[0] = c + ((t - c) * BlendFactor); +} \ No newline at end of file diff --git a/Shaders/PPReduceTo0DCS.cso b/Shaders/PPReduceTo0DCS.cso new file mode 100644 index 0000000000000000000000000000000000000000..6e0cb4d8654f8d069927eb0b9b145dd8c7fe76d8 GIT binary patch literal 2236 zcmd5+OKTHR6h4#0G?`V62qM;8LGXcuN=tkoGMXl~P%UP%s34SB(}yHYNT)j&#g%SE z7p?@Ax=_e35JVUH3&e#>7yf|a%B9~oxrYv+N!*#!e!cge*L>&P(>t?xy>R#2=TmR9 zA11!+yuSVX#Dxh*L_VfO4q%-IzC!UG_yu^-muHHl$JobVdj@bl21vp$2=o=;A&!hs z0ys(npm0w-0%+@Je*)WnqVaPZt*t=Hwau-1Aj|g(zH~Z_q5TIi9tkEF>QnfmJjj_G zsK3&q--V9C95LVz50KTRR<&JiAm$LDnM4eeK&YYrIeR`?tk)W~jR4d-?2>~Ym3}cd z*O%MP&E`sAPM6P^*?E87_-obswYDiV8?E&^Hu>CC?oxhoGIu^db#WTW=lmPDa4n&5 zUFbRcv&F><8tvgmUVy@blsI=lxAfG6F=Vwv`mJu)SjQ`#e;y3&JTI{{FBYzual1mb z20eTEhS$Bj=f4fzOXT3n{KSIDSjOIri&%HtK--n9B;u~My~9;S{T#3BleGLYNSDX= z)JN@yp?}X<%fkgbEqf2OscEQ_tEo zzkV-iIcP1M3ysBA)Q)YWCwsZ*Kdctk%X-N5sI6x|t_HbAiR;+`T-pCo;(B=iSI&uY z#dhcngmV&^$$m4Sx#<6|Gr*Z{Tdq3O`W`V4W!Oy9U+Wq5ndbk;C~+M$)9j^k#rD6= zNfvK4-=HWLeXn%YnGEO7zW*-Xd$sF3$G7Jy;8(6y0@PFj;w%orbM K?>(!&cl`@`;+R|j literal 0 HcmV?d00001 diff --git a/Shaders/PPReduceTo0DCS.hlsl b/Shaders/PPReduceTo0DCS.hlsl new file mode 100644 index 0000000..d598ab8 --- /dev/null +++ b/Shaders/PPReduceTo0DCS.hlsl @@ -0,0 +1,54 @@ +StructuredBuffer Input : register( t0 ); +RWStructuredBuffer Result : register( u0 ); + +cbuffer cbCS : register( b0 ) +{ + uint4 g_param; // g_param.x is the actual elements contained in Input + // g_param.y is the x dimension of the Dispatch call +}; + +#define groupthreads 128 +groupshared float accum[groupthreads]; + +[numthreads(groupthreads,1,1)] +void main( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + if ( DTid.x < g_param.x ) + accum[GI] = Input[DTid.x]; + else + accum[GI] = 0; + + // Parallel reduction algorithm follows + GroupMemoryBarrierWithGroupSync(); + if ( GI < 64 ) + accum[GI] += accum[64+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 32 ) + accum[GI] += accum[32+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 16 ) + accum[GI] += accum[16+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 8 ) + accum[GI] += accum[8+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 4 ) + accum[GI] += accum[4+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 2 ) + accum[GI] += accum[2+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 1 ) + accum[GI] += accum[1+GI]; + + if ( GI == 0 ) + { + Result[Gid.x] = accum[0]; + } +} diff --git a/Shaders/PPReduceTo1DCS.cso b/Shaders/PPReduceTo1DCS.cso new file mode 100644 index 0000000000000000000000000000000000000000..274c130ffd35c9f63d37385b42c13d038a354300 GIT binary patch literal 2148 zcmd5+OKTHR6h4`xNjjj^sHGIKgJz+krKTlR(K?!ktyT-2R^qC}Hri?*p-sVsi0DE^ z@BuCqK}1A_Ze5FX<1Y|g7D3Tn@ekC4}7`zJnwhUJ(G0qSStVi)93V! zllSsX@y_`NmmUQ~WF#t5hqVKE2*V5D4e&K0(x1*`bJ$z(-3NleHb6pNN??xzSD@0* z8X@2Z1Pk4=0k{r?4QOKwg?r*QmEVZ^dnSvsCFw8B%#N32_*}}9xjE+0{|;yXRCpHc zi-4X(&L05^W65;^pj;R#=BM)$$k_~NhDek}Aha-ki_znm@xnx5vIGiq>_)&pjgca! z#)hY-W~R=UoL&99o$g+**YQU4BZX-vH8oKj8^v^W}$cM|{4zt>8oDnm9u+gsoVkoxBecL2~K9PE!!=8i@W4R)Zl;?`QV!vA?6l4x# zwj*qZ$=8|=?5|LVoH$#}#;@mv4F|X)%3C>bWzK3`x8m8zmt0t1xh&N)_hUDd3${yl zt>%K5sPff&F#cb2-LnE$_V<6{dT<4CsuZ&;o3~*)>;7ZY%RiXD+|_F2EZ&I#7b{0zrVnwH}B7`u5z{ P64t8})wN!wuX6tr*xH}t literal 0 HcmV?d00001 diff --git a/Shaders/PPReduceTo1DCS.hlsl b/Shaders/PPReduceTo1DCS.hlsl new file mode 100644 index 0000000..3bac5b4 --- /dev/null +++ b/Shaders/PPReduceTo1DCS.hlsl @@ -0,0 +1,63 @@ +Texture2D Input : register( t0 ); +RWStructuredBuffer Result : register( u0 ); + +cbuffer cbCS : register( b0 ) +{ + uint4 g_param; // (g_param.x, g_param.y) is the x and y dimensions of the Dispatch call + // (g_param.z, g_param.w) is the size of the above Input Texture2D +}; + +//#define CS_FULL_PIXEL_REDUCTION // Defining this or not must be the same as in PostProcessor.... + +#define blocksize 8 +#define blocksizeY 8 +#define groupthreads (blocksize*blocksizeY) +groupshared float accum[groupthreads]; + +static const float4 LUM_VECTOR = float4(.299, .587, .114, 0); + +[numthreads(blocksize,blocksizeY,1)] +void main( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + float4 s = +#ifdef CS_FULL_PIXEL_REDUCTION + Input.Load( uint3(DTid.xy , 0) )+ + Input.Load( uint3(DTid.xy + uint2(blocksize*g_param.x, 0), 0) ) + + Input.Load( uint3(DTid.xy + uint2(0, blocksizeY*g_param.y), 0) ) + + Input.Load( uint3(DTid.xy + uint2(blocksize*g_param.x, blocksizeY*g_param.y), 0) ); +#else + Input.Load( uint3((float)DTid.x/81.0f*g_param.z, (float)DTid.y/81.0f*g_param.w, 0) ); +#endif + + accum[GI] = dot( s, LUM_VECTOR ); + + // Parallel reduction algorithm follows + GroupMemoryBarrierWithGroupSync(); + if ( GI < 32 ) + accum[GI] += accum[32+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 16 ) + accum[GI] += accum[16+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 8 ) + accum[GI] += accum[8+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 4 ) + accum[GI] += accum[4+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 2 ) + accum[GI] += accum[2+GI]; + + GroupMemoryBarrierWithGroupSync(); + if ( GI < 1 ) + accum[GI] += accum[1+GI]; + + if ( GI == 0 ) + { + Result[Gid.y*g_param.x+Gid.x] = accum[0]; + } +} diff --git a/Shaders/PathBoxPS.cso b/Shaders/PathBoxPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..7af9a9728e2768320fe085eb41c30de058fbd754 GIT binary patch literal 516 zcmZ>XaB`mZZPJ$&hs$dhWf|{L+3@HuBLf2i3ljqaE08t;;vOJo01BD_aR(3wxwyIo zfW(l142aG0|363_i0zx1T$Ep&pH`xv5u~Z$;S=nm5S)>il3JwToS$2enFC~)=^5); zni&}A8JZbem@uqf?HTOumjl$x48$Bj46_4hBv=ecG4KO%42S^*AhjTQes%_iB$yzO z28jc`zyK6x2o8%6@DKJ3@$~m&aQ64{4`T515At>N0b04*A84lzPz}fokev!Z3~zeY|~Wh$Idf=FKN@N{&2l^3!6BC(1pT|XBLo4}$^$Iv389-?-LnZ$6mjG`-AHqeMc^$Zt zfKqs-9@6=T=y)kO@`qCMyq4ehYt3*d(<$$)LEk_dP%Y%*y&L$_Jk0wNC1haPNx)<&UT15=7_pWjQcTgD7&6rwcV1G z+{%8|5wCV&_lKiqzvbI`@VembB6pdWH5R-$^I2(G@B%p0AS`k6ZeRfLEU0s?<5qM7 z*q2u<)Mp^bpnJ}IQWOJo#jO`6JoWCqg)akcT|L(Wln)ci*Jt+FKwc6!dAYY^_+L$x z$GDGs^z}K!nYnGWO6;A;nQ;E*h@6e;7#Rd0R;cRS5;?DPtfazX8D@;{{88k`R1ASd zO^sO-bDZTB2;agqerA)1SMiPSZeoNa`lDDEA{*_57~@w~#5oJ&dn@9cneoYrIG-JQ zTGzY!{?Y`Z{tMWv-W%s97X~*x%T96UtWEK%+3E=P9F#c}{vT1bXk7ctb~( Nodes : register(t0); + + +struct VS_INPUT +{ + float4 Position : POSITION; + float4 Normal : NORMAL; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float4 Colour : COLOR0; + float3 Normal : NORMAL; +}; + + + +VS_OUTPUT main(VS_INPUT input, uint iid : SV_InstanceID) +{ + VS_OUTPUT output; + + float4 n = Nodes[iid]; + float3 npos = n.xyz; + float3 ipos = input.Position.xyz * 0.25f; + float3 opos = ipos + npos - CameraPos.xyz; + float4 cpos = mul(float4(opos, 1), ViewProj); + + output.Position = cpos; + output.Colour = ((float4)1) * LightColour.a; //apply intensity + output.Normal = input.Normal.xyz; + + return output; +} + diff --git a/Shaders/PathDynVS.cso b/Shaders/PathDynVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..f1122fbfbbed6913c8bd99912b1dc67613890ca0 GIT binary patch literal 1404 zcmaJ>&ubG=5T5+7X@b;RJt%lsiU$P=kxHlty3H>Wh)tS}YYPP%;@WIUvSqWPf?y0D zMLl`)B!WWxAM`H%4SMnBL3$8R*6+){tsyi{n4LG@H#2YEyhn2DnQY?m_qEf{zRZ0b z-unD?BmOBQB9D%U%)l-~wXjGX`X2f-3IJR!moI!nARzIev}d3a{j)E?KR`F(B6L)T zHRqueuBjHCLnPo$%k}K0)f3Y&npW2`8*WdA!y)q`(6`VnXdv8=xhZ^ty%_gH1?aHs z^SAP65l4)%#7{CAau&7w^4Q2U#G+= zbwp-iH7JE|10_ci!oo0b^SZ1DrJPidQwGDCGKX)7!ua4c$FR;3R6?9Qan!0-j8eT+ zS(R+1T&bZCqnKaUQBX(JOT_FHCA5LpR(P(#^ZR)NUv@cJ|L(TnFU4(S8;ouq{pbLsf9;(}d=D7o5~`lhA^xFX4^-S$d9PxAY+<1FS6BkV zmvS8ASipXi!kn_Ie`4epr|{gHd}a#I-pLQ9@SN{Wk=UZBb12Jm@Q%o34&m4(InHEs z{;|AM;D9AK8w$_Fn6NIg4?C_V<~kk+`e4?~VINQW{VSON4ChGf*9#3_{~hBE#U}HE z{lF!Hdkp3p*8O^{N##9W#WqHvl;U|gFN#rLsq_B}vpc{zs~D8Rdt)#ElS!WWlu6u2 H|9$@g0E&@1 literal 0 HcmV?d00001 diff --git a/Shaders/PathDynVS.hlsl b/Shaders/PathDynVS.hlsl new file mode 100644 index 0000000..99304d1 --- /dev/null +++ b/Shaders/PathDynVS.hlsl @@ -0,0 +1,45 @@ +#include "Common.hlsli" + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4 CameraPos; + float4 LightColour; +} + +struct PathShaderVertex +{ + float3 Position; + uint Colour; +}; + +StructuredBuffer Vertices : register(t0); + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float4 Colour : COLOR0; +}; + + +VS_OUTPUT main(uint id : SV_VertexID) +{ + VS_OUTPUT output; + + float3 pos; + float4 col; + + PathShaderVertex vert = Vertices[id]; + pos = vert.Position; + col = Unpack4x8UNF(vert.Colour).abgr; + + float3 opos = pos - CameraPos.xyz; + float4 cpos = mul(float4(opos, 1), ViewProj); + output.Position = cpos; + output.Colour.rgb = col.rgb * LightColour.a; //apply intensity + output.Colour.a = col.a; + + return output; +} + diff --git a/Shaders/PathPS.cso b/Shaders/PathPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..c3c9eb46b733c49c38cf859a5b28558d45209aff GIT binary patch literal 484 zcmZ>XaB|)|^|kEJE4mIh&rjHt5PZ#(k%58X36Nj~(k4LM1H=!2SOh4R0mMNru5JN9 zJ~EI2aajKUX8_8B*uI&`Mft_~X(b98L7EC4KEXZ;!5N7usYMFT`MCv|IY5S)p0S># znSp_xp_#FT3B&5up26;ZK0v)pK+FNe7C;OFKqDEL!7K&_ejx1vWrHY?I7pr!C=nbM zAK)MC8RF^h$KdSm;~xYx(;sN24pa@uOa&l@0c10QdP5w8++9O}dV)P%fx z)2T;&kU4OdR);3C;Sxz*yFJbe% zZRB05G)_N69(~$fv`7t^Hpy*>cynp4H&lm}luIUE!e=(LIk_^4!`0gu*PN~G&Dedm zCuWeJAH(xp@@r#w&W`+W49|Jto~8_V)?(k(KR+p~=|7S5Z21*Ck0-b`-K;bR$e9MX Uhr%z7bIc@*Xa2u5`~4sJ4Me45VgLXD literal 0 HcmV?d00001 diff --git a/Shaders/PathVS.hlsl b/Shaders/PathVS.hlsl new file mode 100644 index 0000000..9df1950 --- /dev/null +++ b/Shaders/PathVS.hlsl @@ -0,0 +1,37 @@ + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4 CameraPos; + float4 LightColour; +} + +struct VS_INPUT +{ + float4 Position : POSITION; + float4 Colour : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float4 Colour : COLOR0; +}; + + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + + float3 pos = input.Position.xyz; + float4 col = input.Colour; + + float3 opos = pos - CameraPos.xyz; + float4 cpos = mul(float4(opos, 1), ViewProj); + output.Position = cpos; + output.Colour.rgb = col.rgb * LightColour.a; //apply intensity + output.Colour.a = col.a; + + return output; +} + diff --git a/Shaders/Quaternion.hlsli b/Shaders/Quaternion.hlsli new file mode 100644 index 0000000..c648bcc --- /dev/null +++ b/Shaders/Quaternion.hlsli @@ -0,0 +1,11 @@ + + + + +float3 mulvq(float3 v, float4 q) +{ + float3 u = q.xyz; + float s = q.w; + return (dot(u, v)*u*2.0f) + (s*s - dot(u, u)) * v + (cross(u, v)*s*2.0f); +} + diff --git a/Shaders/ShadowPS.cso b/Shaders/ShadowPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..78ab5decf69d81f326b25cf68178794045ed9a81 GIT binary patch literal 1120 zcmb7C&ubG=5S}&>wO9>WLBt=A;6bH?YC@Nz8IaSwP&|pSw~UzXFh-Y z>-*cvlQ|;V&Jvx$SpvR+Sehql0KYRtj$zhE;5hFK0E%t^l$}hNYys~S&ve?jhVcP_ zT-*b#Xad6##};vZ;>!%v^{#&u9frP?R112+Vc7Qu)RvYX^tZflNMo*N-D4n^(ph2w z7{|E(9d$3^WRAh6`E~H;aG%b%z+X^&I^R6-c6z>=j>co6E7(ajL86Lx4`Jt!<{Xw?}r(7r&9+g*C3J=P~)e^Lu(%NW4 zllR~mR{=Ke#&5!Q2{2+W`C&ee!;xFB+qP`FO?!h}vs1He$AIkEhVHV;V_gAgOY5TE ztvZ(JqDVFj=QD&WNc4dh_+<5u0$$SZC6Bb7yhP_3KIb6uH#doPa+G+cgi-Cv~i?oa8l^i86(d8NTU ze*F2m_E_H$)3aPxobJ7tn&V$Rc&F(epy+>lT*dlj?4rNde1%m;>uIbZN4ixvLgXUA az1jFb!{GPilX)G3d&*|hc$V(`~u{ literal 0 HcmV?d00001 diff --git a/Shaders/ShadowPS.hlsl b/Shaders/ShadowPS.hlsl new file mode 100644 index 0000000..705e6e1 --- /dev/null +++ b/Shaders/ShadowPS.hlsl @@ -0,0 +1,32 @@ +Texture2D Colourmap : register(t0); +SamplerState TextureSS : register(s0); + +cbuffer PSGeomVars : register(b0) +{ + uint EnableTexture; + uint EnableTint; + uint IsDecal; + uint Pad3; +} + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + //float3 Normal : NORMAL; + float2 Texcoord : TEXCOORD0; + //float4 Colour : COLOR0; + //float4 Tint : COLOR1; +}; + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + if (EnableTexture == 1) + { + float4 c = Colourmap.Sample(TextureSS, input.Texcoord); + if ((IsDecal == 0) && (c.a <= 0.33)) discard; + if ((IsDecal == 1) && (c.a <= 0.0)) discard; + } + return float4(1.0f, 1.0f, 1.0f, 1.0f); +} \ No newline at end of file diff --git a/Shaders/ShadowVS.cso b/Shaders/ShadowVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..b1a5314c118c7417a901edde5d791cabe7ffb3f8 GIT binary patch literal 2600 zcmah~O=x3P6h3Kdr>%pHbv6zzo+72nP&%EVjv|^)e%eCY7xF?JQ5c@h?KGMu`tsDe z5Yke?A5anL%H4<*BjRSZqC16IxD+?K*OiM|iTZu--jjI~Q|G|BKi@g$yXTyHUsAYo zIX_$6`Es*2_3QgLwtxTn+wGN%h|Eoi+=KZd^vsyZ=g_~PUrmZs3dPdTqaxVKO(^Gw zpfdLNKZ4-vuzkk;5Ft19_m^aH&`(^3%dZRLm9<$3bQ ztLwqK7wm*}6M6ae?yHR^7EALN=AT?zSeQS*bm7uP_G2wr*?iaK$QpK_Do8Vt=~E)F zDTtXkZw0XIK~;#e&QUD(73AJ2dCGpUR$cQqWz(;0EU!zocqQ-qm4f8`b-yA#ANiEw zPafuT2}@92!haaR-SLmTDj(ALCSflM&(G@jJud^Mift!e95IjrDnw^BAvOJYM^E>!UlkPAiw%M{@KQj;cv4&mf=Hdp4Wx?gQgJ@Xh=({bNpZ zqwg0Vco^;5=Q{DjUhCe#wQKL?C!3$1L7e%I<9#x2eBZ-pxwIzQ^}W!p{OKOkPEPgH z8u9j~v~Ko;v6QsGMgIH#^!{nr?}qD4j-&l TintPalette : register(t0); +//SamplerState TextureSS : register(s0); + + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 ipos = input.Position.xyz; + float3 tpos = (HasTransforms == 1) ? mul(float4(ipos, 1), Transform).xyz : ipos; + float3 spos = tpos * Scale; + float3 bpos = mulvq(spos, Orientation); + if (EnableWind) + { + bpos = GeomWindMotion(bpos, input.Colour.xyz, WindVector, WindOverrideParams); + } + float3 opos = CamRel.xyz + bpos; + float4 pos = float4(opos, 1); + float4 cpos = mul(pos, ViewProj); + //if (IsDecal == 1) + //{ + // //cpos.z -= 0.003; //todo: correct decal z-bias + //} + //cpos.z = saturate(cpos.z); //might need work + + //cpos.z = DepthFunc(cpos.zw); + + //float3 inorm = input.Normal; + //float3 tnorm = (HasTransforms == 1) ? mul(inorm, (float3x3)Transform) : inorm; + //float3 bnorm = normalize(mulvq(tnorm, Orientation)); + + //float4 tnt = 0; + //if (EnableTint == 1) + //{ + // tnt = TintPalette.SampleLevel(TextureSS, float2(input.Colour.b, TintYVal), 0); + //} + + output.Position = cpos; + //output.Normal = bnorm; + output.Texcoord = input.Texcoord; + //output.Colour = input.Colour; + //output.Tint = tnt; + return output; +} \ No newline at end of file diff --git a/Shaders/Shadowmap.hlsli b/Shaders/Shadowmap.hlsli new file mode 100644 index 0000000..6b6f46b --- /dev/null +++ b/Shaders/Shadowmap.hlsli @@ -0,0 +1,250 @@ +#include "Common.hlsli" + +//Texture2DArray Depthmap : register(t1); +//SamplerState DepthmapSS : register(s1); +Texture2D Depthmap : register(t1); +SamplerComparisonState DepthmapSS : register(s1); + +cbuffer ShadowmapVars : register(b1) +{ + float4 CamScenePos; //in shadow scene coords + float4x4 CamSceneView; + float4x4 LightView; + float4 LightDir; + float4 CascadeOffsets[16]; + float4 CascadeScales[16]; + float4 CascadeDepths[16]; //in scene eye space + int CascadeCount; + int CascadeVisual; + int PCFLoopStart; + int PCFLoopEnd; + float BorderPaddingMin; + float BorderPaddingMax; + float Bias; + float BlurBetweenCascades; + float CascadeCountInv; + float TexelSize; + float TexelSizeX; + float Pad20; +}; + + + +float ShadowmapSceneDepth(float3 camRelPos, out float4 lspos) +{ + float4 scenePos = float4(camRelPos + CamScenePos.xyz, 1.0); + lspos = mul(scenePos, LightView); + return mul(scenePos, CamSceneView).z; +} + + + + +//-------------------------------------------------------------------------------------- +// Use PCF to sample the depth map and return a percent lit value. +//-------------------------------------------------------------------------------------- +void ShadowmapCalculatePCFPercentLit(in float4 vShadowTexCoord, + in float fRightTexelDepthDelta, + in float fUpTexelDepthDelta, + in float fBlurRowSize, + in float fCascade, + out float fPercentLit +) +{ + fPercentLit = 0.0f; + // This loop could be unrolled, and texture immediate offsets could be used if the kernel size were fixed. + // This would be performance improvment. + for (int x = PCFLoopStart; x < PCFLoopEnd; ++x) + { + for (int y = PCFLoopStart; y < PCFLoopEnd; ++y) + { + float depthcompare = vShadowTexCoord.z; + // A very simple solution to the depth bias problems of PCF is to use an offset. + // Unfortunately, too much offset can lead to Peter-panning (shadows near the base of object disappear ) + // Too little offset can lead to shadow acne ( objects that should not be in shadow are partially self shadowed ). + depthcompare -= Bias; + //depthcompare += Bias; + // Compare the transformed pixel depth to the depth read from the map. + //fPercentLit += Depthmap.SampleLevel(DepthmapSS, + fPercentLit += Depthmap.SampleCmpLevelZero(DepthmapSS, + float2( + vShadowTexCoord.x + (((float)x) * TexelSizeX), + vShadowTexCoord.y + (((float)y) * TexelSize)//, + ), depthcompare); + //fCascade + //), 0).r > depthcompare ? 1.0 : 0.0;// , depthcompare);//== 1.0)?1:0;// + } + } + fPercentLit /= (float)fBlurRowSize; +} + + +//-------------------------------------------------------------------------------------- +// Calculate amount to blend between two cascades and the band where blending will occure. +//-------------------------------------------------------------------------------------- +void ShadowmapCalculateBlendAmountForMap(in float4 vShadowMapTextureCoord, + in out float fCurrentPixelsBlendBandLocation, + out float fBlendBetweenCascadesAmount) +{ + // Calcaulte the blend band for the map based selection. + float2 distanceToOne = float2 (1.0f - vShadowMapTextureCoord.x, 1.0f - vShadowMapTextureCoord.y); + fCurrentPixelsBlendBandLocation = min(vShadowMapTextureCoord.x, vShadowMapTextureCoord.y); + float fCurrentPixelsBlendBandLocation2 = min(distanceToOne.x, distanceToOne.y); + fCurrentPixelsBlendBandLocation = + min(fCurrentPixelsBlendBandLocation, fCurrentPixelsBlendBandLocation2); + fBlendBetweenCascadesAmount = BlurBetweenCascades != 0.0 ? + (fCurrentPixelsBlendBandLocation / BlurBetweenCascades) : 0.0; +} + +static const float4 vCascadeColorsMultiplier[8] = +{ + float4 (1.5f, 0.0f, 0.0f, 1.0f), + float4 (0.0f, 1.5f, 0.0f, 1.0f), + float4 (0.0f, 0.0f, 5.5f, 1.0f), + float4 (1.5f, 0.0f, 5.5f, 1.0f), + float4 (1.5f, 1.5f, 0.0f, 1.0f), + float4 (1.0f, 1.0f, 1.0f, 1.0f), + float4 (0.0f, 1.0f, 5.5f, 1.0f), + float4 (0.5f, 3.5f, 0.75f, 1.0f) +}; + +void ShadowComputeCoordinatesTransform(in int iCascadeIndex, inout float4 vShadowTexCoord) +{ + //transform X coord for current cascade. + vShadowTexCoord.x *= CascadeCountInv;// m_fShadowPartitionSize; // precomputed (float)iCascadeIndex / (float)CASCADE_CNT + vShadowTexCoord.x += (CascadeCountInv*(float)iCascadeIndex);// (m_fShadowPartitionSize * (float)iCascadeIndex); +} + + +float ShadowAmount(float4 shadowcoord, float shadowdepth)//, inout float4 colour) +{ + + float4 vShadowMapTextureCoord = 0.0f; + float4 vShadowMapTextureCoord_blend = 0.0f; + + float4 vVisualizeCascadeColor = float4(0.0f, 0.0f, 0.0f, 1.0f); + + float fPercentLit = 0.0f; + float fPercentLit_blend = 0.0f; + + + float fUpTextDepthWeight = 0; + float fRightTextDepthWeight = 0; + float fUpTextDepthWeight_blend = 0; + float fRightTextDepthWeight_blend = 0; + + int iBlurRowSize = PCFLoopEnd - PCFLoopStart; + iBlurRowSize *= iBlurRowSize; + float fBlurRowSize = (float)iBlurRowSize; + + int iCascadeFound = 0; + int iNextCascadeIndex = 1; + + // The interval based selection technique compares the pixel's depth against the frustum's cascade divisions. + float fCurrentPixelDepth = shadowdepth; + + // This for loop is not necessary when the frustum is uniformaly divided and interval based selection is used. + // In this case fCurrentPixelDepth could be used as an array lookup into the correct frustum. + int iCurrentCascadeIndex = 0; + + float4 vShadowMapTextureCoordViewSpace = shadowcoord; + + if (CascadeCount == 1) + { + vShadowMapTextureCoord = vShadowMapTextureCoordViewSpace * CascadeScales[0]; + vShadowMapTextureCoord += CascadeOffsets[0]; + } + if (CascadeCount > 1) { + for (int iCascadeIndex = 0; iCascadeIndex < CascadeCount && iCascadeFound == 0; ++iCascadeIndex) + { + vShadowMapTextureCoord = vShadowMapTextureCoordViewSpace * CascadeScales[iCascadeIndex]; + vShadowMapTextureCoord += CascadeOffsets[iCascadeIndex]; + + if (min(vShadowMapTextureCoord.x, vShadowMapTextureCoord.y) > BorderPaddingMin + && max(vShadowMapTextureCoord.x, vShadowMapTextureCoord.y) < BorderPaddingMax) + { + iCurrentCascadeIndex = iCascadeIndex; + iCascadeFound = 1; + } + } + } + + if (iCascadeFound == 0 || vShadowMapTextureCoord.z>=1) + { + //colour = float4(0.1, 0.3, 1.0, 0.5); + return 1.0; //out of range! + } + else + { + ShadowComputeCoordinatesTransform(iCurrentCascadeIndex, vShadowMapTextureCoord); + + + vVisualizeCascadeColor = vCascadeColorsMultiplier[iCurrentCascadeIndex]; + //colour = vVisualizeCascadeColor; + + // Repeat texcoord calculations for the next cascade. + // The next cascade index is used for blurring between maps. + iNextCascadeIndex = min(CascadeCount - 1, iCurrentCascadeIndex + 1); + + float fBlendBetweenCascadesAmount = 1.0f; + float fCurrentPixelsBlendBandLocation = 1.0f; + + ShadowmapCalculateBlendAmountForMap(vShadowMapTextureCoord, fCurrentPixelsBlendBandLocation, fBlendBetweenCascadesAmount); + + + ShadowmapCalculatePCFPercentLit(vShadowMapTextureCoord, fRightTextDepthWeight, fUpTextDepthWeight, fBlurRowSize, (float)iCurrentCascadeIndex, fPercentLit); + + if (CascadeCount > 1) + { + if (fCurrentPixelsBlendBandLocation < BlurBetweenCascades) + { // the current pixel is within the blend band. + + // Repeat texcoord calculations for the next cascade. + // The next cascade index is used for blurring between maps. + vShadowMapTextureCoord_blend = vShadowMapTextureCoordViewSpace * CascadeScales[iNextCascadeIndex]; + vShadowMapTextureCoord_blend += CascadeOffsets[iNextCascadeIndex]; + + ShadowComputeCoordinatesTransform(iNextCascadeIndex, vShadowMapTextureCoord_blend); + + // We repeat the calcuation for the next cascade layer, when blending between maps. + if (fCurrentPixelsBlendBandLocation < BlurBetweenCascades) + { + // the current pixel is within the blend band. + ShadowmapCalculatePCFPercentLit(vShadowMapTextureCoord_blend, fRightTextDepthWeight_blend, fUpTextDepthWeight_blend, fBlurRowSize, (float)iNextCascadeIndex, fPercentLit_blend); + fPercentLit = lerp(fPercentLit_blend, fPercentLit, fBlendBetweenCascadesAmount); + // Blend the two calculated shadows by the blend amount. + } + } + } + + return fPercentLit; + + } +} + + + + +float3 FullLighting(float3 diff, float3 spec, float3 norm, float4 vc0, uniform ShaderGlobalLightParams globalLights, uint enableShadows, float shadowdepth, float4 shadowcoord) +{ + float lf = saturate(dot(norm, globalLights.LightDir.xyz)); + + float shadowlit = 1.0; + if (enableShadows == 1) + { + //float shadowdepth = input.Shadows.x;// *0.000001; + if (abs(shadowdepth) < 2000)//2km + { + //float4 shadowcoord = input.LightShadow; + //float4 shadowcolour = (float4)1; + shadowlit = ShadowAmount(shadowcoord, shadowdepth);// , shadowcolour); + } + } + + lf *= shadowlit; + + float3 speclit = spec*shadowlit; + + return GlobalLighting(diff, norm, vc0, lf, globalLights) + speclit; +} + diff --git a/Shaders/SkyMoonPS.cso b/Shaders/SkyMoonPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..6bdfcaa7a9e3ec1c497db64942108172520abfa9 GIT binary patch literal 792 zcmZuvzfZzI6n+RMIH<&l!Qnon~4mtP>^BUmzf8id+9RMnCMhtogf%0;b&=2g4 zkf7hPuR2}VmXfNDb0M4Otux!Dx@2#=>9(oY>oEt{zXFL6*N3t>#yfl}zu=rXU6*Iob%Qx28(QJIkl2ar&EjBj3xe;HC6?0n4Aa%cJ-CHt^O-9K7Y*TU$g235qTy65d`m>ITBk zo#1G^YmsPTpl(-Jb^4886L8|}aaZ-}V}4G*6+F(9EPjJqm0wj{YgkQMd8>m8ehHq% V!uJ{2?1ydk!!jy2Di-bu>_0ueTWSCR literal 0 HcmV?d00001 diff --git a/Shaders/SkyMoonPS.hlsl b/Shaders/SkyMoonPS.hlsl new file mode 100644 index 0000000..d55c2d8 --- /dev/null +++ b/Shaders/SkyMoonPS.hlsl @@ -0,0 +1,24 @@ + +cbuffer PSMoonVars : register(b0) +{ + float4 Colour; +} + +Texture2D MoonSampler : register(t0); +SamplerState TextureSS : register(s0); + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float2 Texcoord : TEXCOORD0; +}; + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + float2 texc = input.Texcoord; + float4 m = MoonSampler.Sample(TextureSS, texc); + + return float4(Colour.rgb*m.rgb, m.a); +} + diff --git a/Shaders/SkyMoonVS.cso b/Shaders/SkyMoonVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..ec98e70e07672237b5f4c8b53d9d5e3b12f69cf0 GIT binary patch literal 1156 zcmb7CO=}ZT6utRSqo}RYWfzaGtdtOw5?T;5CetwkZ70mcP&dXNxfGC#%GOSHVLAUJ4s z!huBW?076RCCfU4Kua6!_E$-s?Z}IX9{Ew23+0?!X_)R)04P z20?eIuDQ#qzUgf$uh)6#hpHCrANKbUl=G$hdbv=@-zb;XR;gusceYm`!?pPz6p&a( z2Xp5{8jfc-ZD*S^4rUtQxB+L@bRRXQGl)%Hr(-?lFN%1r_EfI9u~Ty#*QBmjH{DNY zGSE3h|2`cxd5~w6VCGmL>__rrY13UeQ-tOjC)v(yJ4?fF@7--OV3#&1xDmN zP{yZG)%A; zGT1e$T;Wbi&s^4C-wQj)FU{boPrf>X=RJ`h&*1rPMUlDWZj*aV8z4j~8gY^~V)s|= d7M|T}-fr?eF9AG{MqR#XV%+n8EYbPb%pX&$Z!iD= literal 0 HcmV?d00001 diff --git a/Shaders/SkyMoonVS.hlsl b/Shaders/SkyMoonVS.hlsl new file mode 100644 index 0000000..08e6000 --- /dev/null +++ b/Shaders/SkyMoonVS.hlsl @@ -0,0 +1,36 @@ +#include "Common.hlsli" + +cbuffer VSMoonVars : register(b0) +{ + float4x4 ViewProj; + float4x4 ViewInv; + float4 CamRel; + float2 Size; + float2 Offset; +} + + +struct VS_INPUT +{ + float4 Position : POSITION; +}; +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float2 Texcoord : TEXCOORD0; +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 ipos = input.Position.xyz * float3(Size, 1); + float3 bpos = mul(ipos, (float3x3)ViewInv); + float3 opos = CamRel.xyz + bpos; + float4 pos = float4(opos, 1); + float4 cpos = mul(pos, ViewProj); + cpos.z = DepthFunc(cpos.zw); + output.Position = cpos; + output.Texcoord = input.Position.xy*0.5+0.5; + return output; +} + diff --git a/Shaders/SkySunPS.cso b/Shaders/SkySunPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..a6c9029092b288ce3cf83923c886ca028b8055e5 GIT binary patch literal 520 zcmZ>XaB`LmQcD#)^L)yc@Y_W*H_i>uoa zh%kc(l$HUhWBLCdq;>+3X#?V80YGVx5{7`_;L^OX#G+z`)vG~jL1GC&EC9qXPyuCt z#DLCWXn^va^KP!mA3Kaj5jq(SZh@fCm=2AH7?ejptj z79ZjmMgl{^txo~Sf|!%az`*=T0pc?=1_m}58>R-N&JL(F bIK(le1jq*Y6$U`=KnCc1WI1eXV$}lxN0T`O literal 0 HcmV?d00001 diff --git a/Shaders/SkySunPS.hlsl b/Shaders/SkySunPS.hlsl new file mode 100644 index 0000000..8148812 --- /dev/null +++ b/Shaders/SkySunPS.hlsl @@ -0,0 +1,11 @@ + +cbuffer PSSunVars : register(b0) +{ + float4 Colour; +} + + +float4 main() : SV_TARGET +{ + return Colour; +} \ No newline at end of file diff --git a/Shaders/SkySunVS.cso b/Shaders/SkySunVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..7f5b4bfd808077b2182c744b33583368bea7931d GIT binary patch literal 1116 zcmb7C&ubG=5T0~n8>PP#k3BppNG&C#O^FpmW3pWnsNJwHgjx!1sGBCGZDbP_JcaxL z;z>Mu@F2vSSO1Vgq4dy`NAW1?_hsLP9vY|^irjrjcsZ???lU`Y-R#87)Uw{n9=6_H? zWO$CgO^u0^TwN>|-F4Qus40Qr1gu%KwtZ@-t*&fK1S2yym>)F)R z1>5_Aq%1P`k^3BLcHSwRL~a1vC=aIj0wR0heyZ?HT_4;M?mX8q8fU{?iKYIFi8!Xt z=_oKF*MST^jhx}<4G+b{EySqfjD-45SK)?+0QuP=JijyY)V!>Ilp^2*X2Gc6&olbm zC1>gyK9*%x=kZO>q)g4E@n$c~AU`{Vr#|`I5T1J?-yOp9-8fUU+h~uE@SM8*q}&ES T0Z@m=eC{?f_WvJa{Z;HAMp147 literal 0 HcmV?d00001 diff --git a/Shaders/SkySunVS.hlsl b/Shaders/SkySunVS.hlsl new file mode 100644 index 0000000..f794141 --- /dev/null +++ b/Shaders/SkySunVS.hlsl @@ -0,0 +1,36 @@ +#include "Common.hlsli" + +cbuffer VSSunVars : register(b0) +{ + float4x4 ViewProj; + float4x4 ViewInv; + float4 CamRel; + float2 Size; + float2 Offset; +} + + +struct VS_INPUT +{ + float4 Position : POSITION; +}; +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float2 Texcoord : TEXCOORD0; +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 ipos = input.Position.xyz * float3(Size, 1); + float3 bpos = mul(ipos, (float3x3)ViewInv); + float3 opos = CamRel.xyz + bpos; + float4 pos = float4(opos, 1); + float4 cpos = mul(pos, ViewProj); + cpos.z = DepthFunc(cpos.zw); + output.Position = cpos; + output.Texcoord = input.Position.xy; + return output; +} + diff --git a/Shaders/Skydome.hlsli b/Shaders/Skydome.hlsli new file mode 100644 index 0000000..a11e9be --- /dev/null +++ b/Shaders/Skydome.hlsli @@ -0,0 +1,45 @@ + + + +cbuffer SkySystemLocals : register(b0) +{ + float4 azimuthEastColor; // Offset: 0 Size: 12 [unused] + float4 azimuthWestColor; // Offset: 16 Size: 12 [unused] + float3 azimuthTransitionColor; // Offset: 32 Size: 12 [unused] + float azimuthTransitionPosition; // Offset: 44 Size: 4 [unused] + float4 zenithColor; // Offset: 48 Size: 12 [unused] + float4 zenithTransitionColor; // Offset: 64 Size: 12 [unused] + float4 zenithConstants; // Offset: 80 Size: 16 [unused] + float4 skyPlaneColor; // Offset: 96 Size: 16 [unused] + float4 skyPlaneParams; // Offset: 112 Size: 16 [unused] + float hdrIntensity; // Offset: 128 Size: 4 [unused] + float3 sunColor; // Offset: 132 Size: 12 + float4 sunColorHdr; // Offset: 144 Size: 12 + float4 sunDiscColorHdr; // Offset: 160 Size: 12 [unused] + float4 sunConstants; // Offset: 176 Size: 16 + float4 sunDirection; // Offset: 192 Size: 12 + float4 sunPosition; // Offset: 208 Size: 12 [unused] + float4 cloudBaseMinusMidColour; // Offset: 224 Size: 12 + float4 cloudMidColour; // Offset: 240 Size: 12 + float4 cloudShadowMinusBaseColourTimesShadowStrength;// Offset: 256 Size: 12 + float4 cloudDetailConstants; // Offset: 272 Size: 16 + float4 cloudConstants1; // Offset: 288 Size: 16 + float4 cloudConstants2; // Offset: 304 Size: 16 + float4 smallCloudConstants; // Offset: 320 Size: 16 + float4 smallCloudColorHdr; // Offset: 336 Size: 12 + float4 effectsConstants; // Offset: 352 Size: 16 + float horizonLevel; // Offset: 368 Size: 4 [unused] + float3 speedConstants; // Offset: 372 Size: 12 [unused] + float starfieldIntensity; // Offset: 384 Size: 4 + float3 moonDirection; // Offset: 388 Size: 12 + float3 moonPosition; // Offset: 400 Size: 12 [unused] + float moonIntensity; // Offset: 412 Size: 4 [unused] + float4 lunarCycle; // Offset: 416 Size: 12 + float3 moonColor; // Offset: 432 Size: 12 + float noiseFrequency; // Offset: 444 Size: 4 [unused] + float noiseScale; // Offset: 448 Size: 4 [unused] + float noiseThreshold; // Offset: 452 Size: 4 [unused] + float noiseSoftness; // Offset: 456 Size: 4 [unused] + float noiseDensityOffset; // Offset: 460 Size: 4 [unused] + float4 noisePhase; // Offset: 464 Size: 8 [unused] +}; diff --git a/Shaders/SkydomePS.cso b/Shaders/SkydomePS.cso new file mode 100644 index 0000000000000000000000000000000000000000..514108fe4f2c3a6f39812441d3ddebf9f9b31020 GIT binary patch literal 3732 zcmaKuUu+ab9LMJh6evmy`cMcVt1qGwEQM6iXs_J$ps{~0-2TUyH#48# zpZWb}W_O#P*_S)G>C6jXUHog^@C66 zM+;f7F6frfR-$b|6Dx1s5^!Dz-8oEGkaY-Svwez2f389QTM%@K?q2j?aFQa%|NH;Z z(WWF%#Pv|xwy-C_-V{L^M4ooEI9L|z1fG4z|U)ruE{?Kzo>b; z{Wsv3Quq(xS2Rc0jPnclwG{p*`1KV2FE}q3^Q4$Ow{?T1@Tb776g~kykiuUC&!+I> z;KdYv8vJkye;<4fyz@SM3?74b?*EtI4Q=0kUYEg7r`Z1tel~?)1wW_baDU9X{|$Z~ zymR0F0l%0Mrwh-?w<&QpfL}`CTfi@;@JGQHQ}|x+r4&96eg(WUPv@jttH;$*CyH}{ z7le4!7czJ=WtuxIgtmEB8XFBtq2otx>;}GaRer6v+8t)aK$&9^zWp-zGjdY;Zd_Gy z)VMRcvGAkV@#9ED$L5Qk<4fgZW<@7-YLTc`!ZAOVOmAL9b)BFY9H@kZc{eI2-g=%3 znz5-2Wtp|nvYB|<3+k19P9!H>zaCAv75djhk?@YGU3DtKtBD~!lx4}S$w+DJIF$a; zxT>7OAEnWf{TDhP$=Xw|n?bx+r@6f=&j-5lh_UvZNF?;{yHROSGlD3GR z!l%YOWxW{xN~ndLdc(~VM$Y$NFBG)rm_p9hi#;Oen8Kd*n>c1K$oZ)-oMQ?(UU^~# z28_cog`CGgd;8GK#VLENG&VIUN~1Hmsj2Ba>zqQJ{Khj^)@q>{p+80Ymqw=dkCxzM zW8Y68sVsC`;rJZVExc`ECd4K*GiOZJ`aDxPtZvLqKT4ZZzr~sUjrn-hk3J>RVXYs{Bp=47SPWdbADxHC!DU`;E%JTh9@Bt+6k3 zsdWmcti}k|q42vli0(mcZ({Z|S~lxov$-b?R7~$=|GncqY~wV{deiwC8Dwb#1=Qn%iwmzC+fXYa`b+ zf9SOitx{`tpRtm)@h>@RY3bK1{f&2&-t1HRx$x}GxqPs?Rl_N>_d0jpRh8G`2lpe1^_ z2aM6ZR@ruCF;S95m$WYaLVj9W`pz_-HS0HZGY0Es&%L9ropm=XXjG2Im+yxgy(%Z( zU&h)CUsJ28tF>oBJdV1|y6wJFn7MIm&Vg&0XZ*Icv=4nLPa_4pG*XH&egMt91DSU}ni1xAH%ZgcU)ORsw}k%( DeE9s? literal 0 HcmV?d00001 diff --git a/Shaders/SkydomePS.hlsl b/Shaders/SkydomePS.hlsl new file mode 100644 index 0000000..4882371 --- /dev/null +++ b/Shaders/SkydomePS.hlsl @@ -0,0 +1,342 @@ +#include "Skydome.hlsli" + +Texture2D Starmap : register(t0); +SamplerState TextureSS : register(s0); + +cbuffer PSSceneVars : register(b1) +{ + float4 LightDirection; + uint EnableHDR; + uint Pad0; + uint Pad1; + uint Pad2; +} + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; // 0 xyzw 0 POS float xyzw + float4 o1 : TEXCOORD0; // 0 xyzw 1 NONE float xyzw + float4 o2 : TEXCOORD1; // 1 xyzw 2 NONE float xyzw + float4 o3 : TEXCOORD2; // 2 xyzw 3 NONE float xyzw + float4 o4 : TEXCOORD3; // 3 xyzw 4 NONE float xyzw + float4 o5 : TEXCOORD4; // 4 xyzw 5 NONE float xyzw + float2 o6 : TEXCOORD5; // 5 xy 6 NONE float xy + float4 o7 : TEXCOORD6; // 6 xyzw 7 NONE float xyzw +}; + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + //return float4(1,0,0,1); + float4 sf = Starmap.Sample(TextureSS, input.o6); + sf.rgb = saturate(sf.rgb*2.0 - 0.1); + + float3 skybase = input.o3.rgb; + + if (EnableHDR == 0) + { + sf.rgb *= max(starfieldIntensity, 1.25); + if (hdrIntensity != 0.0) + { + sf.rgb *= saturate(1.0f / (hdrIntensity*25.0f));//fake hiding stars when no HDR + } + } + else + { + sf.rgb *= starfieldIntensity; + } + + //float4 zen = zenithColor * hdrIntensity; + //sf.rgb += zen.rgb; + + + //sf.rgb += input.o3.rgb * hdrIntensity; + + + float4 o2 = input.o2; + + float4 r0, r1, r2, r3, r4; + float poslen = length(o2); //4d length... + r2.xyz = o2.xyz / poslen; //normalized + r4.x = dot(r2.xyz, -sunDirection.xyz); //dp3 r4.x, r2.xyzx, -sunDirection.xyzx + ///return float4(r4.xxx, 1); + //r4.y = dot(r2.xyz, -moonDirection.xyz); //dp3 r4.y, r2.xyzx, moonDirection.xyzx;//.yzwy + r0.z = r4.x*-sunConstants.x +sunConstants.y; //mad r0.z, -sunConstants.x, r4.x, sunConstants.y //mie phase, scatter + r0.z = log(abs(r0.z)); //log r0.z, |r0.z| + r0.z = r0.z * 1.5; //mul r0.z, r0.z, l(1.500000) + r0.z = exp(r0.z); //exp r0.z, r0.z + r0.w = r4.x*r4.x + 1.0; //mad r0.w, r4.x, r4.x, l(1.000000) + r4.x = saturate(-r4.x); //mov_sat r4.x, -r4.x + //r2.xy = 1.0 - r4.xy; //add r2.xy, -r4.xyxx, l(1.000000, 1.000000, 0.000000, 0.000000) + r0.z = r0.w / r0.z; //div r0.z, r0.w, r0.z + r0.w = r0.z*sunConstants.z; //mul r0.w, r0.z, sunConstants.z //mie range? + r0.z = saturate(1.0 - r0.w); //mad_sat r0.z, -r0.z, sunConstants.z, l(1.000000) + r0.w = saturate(r0.w); //mov_sat r0.w, r0.w + r4.xyz = r0.w*sunColorHdr.xyz; //mul r4.xyz, r0.wwww, sunColorHdr.xyzx + r4.xyz = r4.xyz*sunConstants.w; //mul r4.xyz, r4.xyzx, sunConstants.wwww //scatter intensity? + r4.xyz = skybase*r0.z + r4.xyz; //mad r4.xyz, v3.xyzx, r0.zzzz, r4.xyzx + + sf.rgb += r4.xyz; + + if (EnableHDR == 0) + { + sf = saturate(sf); + } + else + { + sf.a = saturate(sf.a); + } + + return sf; + + //float f = frac(tc.x); + //return (f < 0.5) ? float4(1, 0, 1, 1) : sf; +} + + + + +/* + +sky normal all PS: + +ps_4_0 +dcl_constantbuffer CB2[14], immediateIndexed +dcl_constantbuffer CB12[28], immediateIndexed +dcl_sampler s3, mode_default +dcl_sampler s4, mode_default +dcl_sampler s5, mode_default +dcl_sampler s6, mode_default +dcl_resource_texture2d (float,float,float,float) t3 perlinSampler +dcl_resource_texture2d (float,float,float,float) t4 highDetailSampler +dcl_resource_texture2d (float,float,float,float) t5 starFieldSampler +dcl_resource_texture2d (float,float,float,float) t6 ditherSampler +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xyzw +dcl_input_ps linear v3.xyz +dcl_input_ps linear v4.xyzw +dcl_input_ps linear v5.xyzw +dcl_input_ps linear v6.xy +dcl_input_ps linear v7.xyzw +dcl_output o0.xyzw +dcl_temps 6 +sample r0.xyzw, v4.xyxx, highDetailSampler.xyzw, s4 +add r0.x, r0.x, l(-0.500000) +mul r0.x, r0.x, cloudDetailConstants.x +sample r1.xyzw, v5.zwzz, highDetailSampler.xyzw, s4 +add r0.z, r1.x, l(-0.500000) +mul r0.y, r0.z, smallCloudConstants.y +sample r1.xyzw, v4.zwzz, highDetailSampler.xyzw, s4 +add r1.x, r1.x, l(-0.500000) +mul r0.z, r1.x, cloudConstants2.z +sample r2.xyzw, v1.zwzz, perlinSampler.xyzw, s3 +mad r0.z, r0.z, cloudDetailConstants.z, r2.x +mul r0.z, r0.z, cloudConstants1.x +sample r3.xyzw, v1.xyxx, perlinSampler.xyzw, s3 +mul r0.z, r0.z, r3.x +mad_sat r0.w, -r0.z, l(2.000000), l(1.000000) +mul r0.xy, r0.wwww, r0.xyxx +mul r0.xy, r3.zzzz, r0.xyxx +mov r4.x, cloudDetailConstants.z +mov r4.y, smallCloudConstants.y +add r1.y, -r3.z, l(1.000000) +mad r0.xy, r1.xyxx, r4.xyxx, r0.xyxx +add r0.w, r0.x, r2.y +mad r1.xyz, r0.wwww, cloudShadowMinusBaseColourTimesShadowStrength.xyzx, cloudBaseMinusMidColour.xyzx +mad r1.xyz, r0.zzzz, r1.xyzx, cloudMidColour.xyzx +mov r3.y, l(0) +add r0.xy, r0.xyxx, r3.xyxx +mul r2.x, r0.x, cloudConstants1.y +mul r2.y, r0.y, smallCloudConstants.z +add_sat r0.x, -r0.x, l(1.000000) +mov r3.y, -smallCloudConstants.w +mov r3.xz, -cloudConstants1.zzwz +add_sat r0.yz, r2.xxyx, r3.xxyx +mul r0.yz, r0.yyzy, r0.yyzy +dp4 r0.w, v2.xyzw, v2.xyzw +rsq r0.w, r0.w +mul r2.xyz, r0.wwww, v2.xyzx +mad_sat r0.w, r2.z, l(5.000000), r3.z +mul r3.xy, r0.wwww, r0.yzyy +mad r0.y, -r0.y, r0.w, l(1.000000) +mul r0.y, r0.y, r3.y +mad r0.y, r0.y, l(0.300000), r3.x + +dp3 r4.x, r2.xyzx, -sunDirection.xyzx +dp3 r4.y, r2.xyzx, moonDirection.xyzx;//.yzwy +mad r0.z, -sunConstants.x, r4.x, sunConstants.y +log r0.z, |r0.z| +mul r0.z, r0.z, l(1.500000) +exp r0.z, r0.z +mad r0.w, r4.x, r4.x, l(1.000000) +mov_sat r4.x, -r4.x +add r2.xy, -r4.xyxx, l(1.000000, 1.000000, 0.000000, 0.000000) +div r0.z, r0.w, r0.z +mul r0.w, r0.z, sunConstants.z +mad_sat r0.z, -r0.z, sunConstants.z, l(1.000000) +mov_sat r0.w, r0.w +mul r4.xyz, r0.wwww, sunColorHdr.xyzx +mul r4.xyz, r4.xyzx, sunConstants.wwww +mad r4.xyz, v3.xyzx, r0.zzzz, r4.xyzx + +add r5.xyz, -r4.xyzx, smallCloudColorHdr.xyzx +mad r4.xyz, r3.yyyy, r5.xyzx, r4.xyzx +mad r1.xyz, r1.xyzx, cloudConstants2.wwww, -r4.xyzx +mad r1.xyz, r3.xxxx, r1.xyzx, r4.xyzx +add r0.z, r3.y, r3.x +add_sat o0.w, -r0.z, v2.w +div r0.zw, r2.xxxy, effectsConstants.xxxz +ge r1.w, r2.y, l(0.000545) +and r1.w, r1.w, l(0x3f800000) +mul_sat r0.zw, r0.zzzw, l(0.000000, 0.000000, 100.000000, 100.000000) +add r0.zw, -r0.zzzw, l(0.000000, 0.000000, 1.000000, 1.000000) +mul r0.zw, r0.yyyy, r0.zzzw +add r0.y, -r0.y, l(1.000000) +mul r0.xz, r0.xxxx, r0.zzwz +mul r0.xz, r0.xxzx, r0.xxzx +mul r0.xz, r0.xxzx, r0.xxzx +mad r0.w, lunarCycle.y, l(0.500000), l(0.500000) +mul r0.w, r0.w, effectsConstants.w +mul r0.z, r0.w, r0.z +mul r0.x, r0.x, effectsConstants.y +mul r2.xyz, r0.zzzz, moonColor.xyzx +mad r0.xzw, sunColor.yyzw, r0.xxxx, r2.xxyz +add r0.xzw, r0.xxzw, r1.xxyz + +sample r2.xyzw, v6.xyxx, starFieldSampler.xyzw, s5 +mad_sat r1.xyz, r2.xyzx, l(2.000000, 2.000000, 2.000000, 0.000000), l(-0.100000, -0.100000, -0.100000, 0.000000) +mul r1.xyz, r1.xyzx, starfieldIntensity.xxxx +mul r1.xyz, r1.wwww, r1.xyzx +mad r0.xyz, r1.xyzx, r0.yyyy, r0.xzwx +add r1.xyz, -r0.xyzx, v7.xyzx +mad r0.xyz, v7.wwww, r1.xyzx, r0.xyzx + +sample r1.xyzw, v5.xyxx, ditherSampler.xyzw, s6 +add r0.w, r1.x, l(-0.500000) +mad r0.xyz, r0.wwww, l(0.000100, 0.000100, 0.000100, 0.000000), r0.xyzx +mul o0.xyz, r0.xyzx, globalScalars3.zzzz + +ret +// Approximately 92 instruction slots used + + + + + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer misc_globals +// { +// +// float4 globalFade; // Offset: 0 Size: 16 [unused] +// float globalHeightScale; // Offset: 16 Size: 4 [unused] +// float4 g_Rage_Tessellation_CameraPosition;// Offset: 32 Size: 16 [unused] +// float4 g_Rage_Tessellation_CameraZAxis;// Offset: 48 Size: 16 [unused] +// float4 g_Rage_Tessellation_ScreenSpaceErrorParams;// Offset: 64 Size: 16 [unused] +// float4 g_Rage_Tessellation_LinearScale;// Offset: 80 Size: 16 [unused] +// float4 g_Rage_Tessellation_Frustum[4];// Offset: 96 Size: 64 [unused] +// float4 g_Rage_Tessellation_Epsilons;// Offset: 160 Size: 16 [unused] +// float4 globalScalars; // Offset: 176 Size: 16 [unused] +// float4 globalScalars2; // Offset: 192 Size: 16 [unused] +// float4 globalScalars3; // Offset: 208 Size: 16 +// float4 globalScreenSize; // Offset: 224 Size: 16 [unused] +// uint4 gTargetAAParams; // Offset: 240 Size: 16 [unused] +// float4 colorize; // Offset: 256 Size: 16 [unused] +// float4 gGlobalParticleShadowBias; // Offset: 272 Size: 16 [unused] +// float gGlobalParticleDofAlphaScale;// Offset: 288 Size: 4 [unused] +// float gGlobalFogIntensity; // Offset: 292 Size: 4 [unused] +// float4 gPlayerLFootPos; // Offset: 304 Size: 16 [unused] +// float4 gPlayerRFootPos; // Offset: 320 Size: 16 [unused] +// +// } +// +// cbuffer sky_system_locals +// { +// +// float3 azimuthEastColor; // Offset: 0 Size: 12 [unused] +// float3 azimuthWestColor; // Offset: 16 Size: 12 [unused] +// float3 azimuthTransitionColor; // Offset: 32 Size: 12 [unused] +// float azimuthTransitionPosition; // Offset: 44 Size: 4 [unused] +// float3 zenithColor; // Offset: 48 Size: 12 [unused] +// float3 zenithTransitionColor; // Offset: 64 Size: 12 [unused] +// float4 zenithConstants; // Offset: 80 Size: 16 [unused] +// float4 skyPlaneColor; // Offset: 96 Size: 16 [unused] +// float4 skyPlaneParams; // Offset: 112 Size: 16 [unused] +// float hdrIntensity; // Offset: 128 Size: 4 [unused] +// float3 sunColor; // Offset: 132 Size: 12 +// float3 sunColorHdr; // Offset: 144 Size: 12 +// float3 sunDiscColorHdr; // Offset: 160 Size: 12 [unused] +// float4 sunConstants; // Offset: 176 Size: 16 +// float3 sunDirection; // Offset: 192 Size: 12 +// float3 sunPosition; // Offset: 208 Size: 12 [unused] +// float3 cloudBaseMinusMidColour; // Offset: 224 Size: 12 +// float3 cloudMidColour; // Offset: 240 Size: 12 +// float3 cloudShadowMinusBaseColourTimesShadowStrength;// Offset: 256 Size: 12 +// float4 cloudDetailConstants; // Offset: 272 Size: 16 +// float4 cloudConstants1; // Offset: 288 Size: 16 +// float4 cloudConstants2; // Offset: 304 Size: 16 +// float4 smallCloudConstants; // Offset: 320 Size: 16 +// float3 smallCloudColorHdr; // Offset: 336 Size: 12 +// float4 effectsConstants; // Offset: 352 Size: 16 +// float horizonLevel; // Offset: 368 Size: 4 [unused] +// float3 speedConstants; // Offset: 372 Size: 12 [unused] +// float starfieldIntensity; // Offset: 384 Size: 4 +// float3 moonDirection; // Offset: 388 Size: 12 +// float3 moonPosition; // Offset: 400 Size: 12 [unused] +// float moonIntensity; // Offset: 412 Size: 4 [unused] +// float3 lunarCycle; // Offset: 416 Size: 12 +// float3 moonColor; // Offset: 432 Size: 12 +// float noiseFrequency; // Offset: 444 Size: 4 [unused] +// float noiseScale; // Offset: 448 Size: 4 [unused] +// float noiseThreshold; // Offset: 452 Size: 4 [unused] +// float noiseSoftness; // Offset: 456 Size: 4 [unused] +// float noiseDensityOffset; // Offset: 460 Size: 4 [unused] +// float2 noisePhase; // Offset: 464 Size: 8 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// perlinSampler sampler NA NA s3 1 +// highDetailSampler sampler NA NA s4 1 +// starFieldSampler sampler NA NA s5 1 +// ditherSampler sampler NA NA s6 1 +// perlinSampler texture float4 2d t3 1 +// highDetailSampler texture float4 2d t4 1 +// starFieldSampler texture float4 2d t5 1 +// ditherSampler texture float4 2d t6 1 +// misc_globals cbuffer NA NA cb2 1 +// sky_system_locals cbuffer NA NA cb12 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float +// TEXCOORD 0 xyzw 1 NONE float xyzw +// TEXCOORD 1 xyzw 2 NONE float xyzw +// TEXCOORD 2 xyzw 3 NONE float xyz +// TEXCOORD 3 xyzw 4 NONE float xyzw +// TEXCOORD 4 xyzw 5 NONE float xyzw +// TEXCOORD 5 xy 6 NONE float xy +// TEXCOORD 6 xyzw 7 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// + + + +*/ \ No newline at end of file diff --git a/Shaders/SkydomeVS.cso b/Shaders/SkydomeVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..779704b227a4d2266260e072994ea41115f25c2b GIT binary patch literal 5420 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 literal 0 HcmV?d00001 diff --git a/Shaders/TerrainPS.hlsl b/Shaders/TerrainPS.hlsl new file mode 100644 index 0000000..dfdf94a --- /dev/null +++ b/Shaders/TerrainPS.hlsl @@ -0,0 +1,278 @@ +#include "Shadowmap.hlsli" + +Texture2D Colourmap0 : register(t0); +Texture2D Colourmap1 : register(t2); +Texture2D Colourmap2 : register(t3); +Texture2D Colourmap3 : register(t4); +Texture2D Colourmap4 : register(t5); +Texture2D Colourmask : register(t6); +Texture2D Normalmap0 : register(t7); +Texture2D Normalmap1 : register(t8); +Texture2D Normalmap2 : register(t9); +Texture2D Normalmap3 : register(t10); +Texture2D Normalmap4 : register(t11); +SamplerState TextureSS : register(s0); + + +cbuffer PSSceneVars : register(b0) +{ + ShaderGlobalLightParams GlobalLights; + uint EnableShadows; + uint RenderMode; //0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct + uint RenderModeIndex; //colour or texcoord index + uint RenderSamplerCoord; +} +cbuffer PSEntityVars : register(b2) +{ + uint EnableTexture0; + uint EnableTexture1; + uint EnableTexture2; + uint EnableTexture3; + uint EnableTexture4; + uint EnableTextureMask; + uint EnableNormalMap; + uint ShaderName; + uint EnableTint; + uint EnableVertexColour; + float bumpiness; + uint Pad102; +} + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float4 Tint : COLOR2; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float4 Shadows : TEXCOORD4; + float4 LightShadow : TEXCOORD5; + float4 Tangent : TEXCOORD6; + float4 Bitangent : TEXCOORD7; + float3 CamRelPos : TEXCOORD8; +}; + + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + float4 vc0 = input.Colour0; + float4 vc1 = input.Colour1; + float2 tc0 = input.Texcoord0; + float2 tc1 = input.Texcoord1; + float2 tc2 = input.Texcoord2; + + float2 sc0 = tc0; + float2 sc1 = tc0; + float2 sc2 = tc0; + float2 sc3 = tc0; + float2 sc4 = tc0; + float2 scm = tc1; + + ////switch (ShaderName) + ////{ + //// case 3965214311: //terrain_cb_w_4lyr_cm_pxm_tnt vt: PNCTTTX_3 //vb_35_beache + //// case 4186046662: //terrain_cb_w_4lyr_cm_pxm vt: PNCTTTX_3 //cs6_08_struct08 + //// //vc1 = vc0; + //// //sc1 = tc0*25; + //// //sc2 = sc1; + //// //sc3 = sc1; + //// //sc4 = sc1; + //// //scm = tc0; + //// break; + ////} + + float4 bc0 = float4(0.5, 0.5, 0.5, 1); + //if (EnableVertexColour) + //{ + // bc0 = vc0; + //} + + if (RenderMode == 8) //direct texture - choose texcoords + { + if (RenderSamplerCoord == 2) sc0 = tc1; + else if (RenderSamplerCoord == 3) sc0 = tc2; + } + + + float4 c0 = (EnableTexture0 == 1) ? Colourmap0.Sample(TextureSS, sc0) : bc0; + float4 c1 = (EnableTexture1 == 1) ? Colourmap1.Sample(TextureSS, sc1) : bc0; + float4 c2 = (EnableTexture2 == 1) ? Colourmap2.Sample(TextureSS, sc2) : bc0; + float4 c3 = (EnableTexture3 == 1) ? Colourmap3.Sample(TextureSS, sc3) : bc0; + float4 c4 = (EnableTexture4 == 1) ? Colourmap4.Sample(TextureSS, sc4) : bc0; + float4 m = (EnableTextureMask == 1) ? Colourmask.Sample(TextureSS, scm) : vc1; + float4 b0 = (EnableNormalMap == 1) ? Normalmap0.Sample(TextureSS, sc0) : float4(0.5, 0.5, 0.5, 1);// float4(input.Normal, 0); + float4 b1 = (EnableNormalMap == 1) ? Normalmap1.Sample(TextureSS, sc1) : b0; + float4 b2 = (EnableNormalMap == 1) ? Normalmap2.Sample(TextureSS, sc2) : b0; + float4 b3 = (EnableNormalMap == 1) ? Normalmap3.Sample(TextureSS, sc3) : b0; + float4 b4 = (EnableNormalMap == 1) ? Normalmap4.Sample(TextureSS, sc4) : b0; + + float4 tv=0, nv=0; + float4 t1, t2, n1, n2; + + switch (ShaderName) + { + case 137526804: //terrain_cb_w_4lyr_lod vt: PNCCT //brdgeplatform_01_lod.. + //return float4(vc1.rgb, vc1.a*0.5 + 0.5); + t1 = c1*(1 - vc1.b) + c2*vc1.b; + t2 = c3*(1 - vc1.b) + c4*vc1.b; + tv = t1*(1 - vc1.g) + t2*vc1.g; + n1 = b1*(1 - vc1.b) + b2*vc1.b; + n2 = b3*(1 - vc1.b) + b4*vc1.b; + nv = n1*(1 - vc1.g) + n2*vc1.g; + break; + + default: + case 2535953532: //terrain_cb_w_4lyr_2tex_blend_lod vt: PNCCTT //cs1_12_riverbed1_lod.. + //return float4(vc0.rgb, vc0.a*0.5 + 0.5); + //return float4(vc1.rgb, vc1.a*0.5 + 0.5); + vc1 = m*(1 - vc0.a) + vc1*vc0.a; + t1 = c1*(1 - vc1.b) + c2*vc1.b; + t2 = c3*(1 - vc1.b) + c4*vc1.b; + tv = t1*(1 - vc1.g) + t2*vc1.g; + n1 = b1*(1 - vc1.b) + b2*vc1.b; + n2 = b3*(1 - vc1.b) + b4*vc1.b; + nv = n1*(1 - vc1.g) + n2*vc1.g; + break; + + + case 653544224: //terrain_cb_w_4lyr_2tex_blend_pxm_spm vt: PNCCTTTX //ch2_04_land06, rd_04_20.. + case 2486206885: //terrain_cb_w_4lyr_2tex_blend_pxm vt: PNCCTTTX //cs2_06c_lkbed_05.. + case 1888432890: //terrain_cb_w_4lyr_2tex_pxm vt: PNCCTTTX //ch1_04b_vineland01.. + //return float4(0, 1, 0, 1); + vc1 = m*(1 - vc0.a) + vc1*vc0.a; //perhaps another sampling of the mask is needed here + t1 = c1*(1 - vc1.b) + c2*vc1.b; + t2 = c3*(1 - vc1.b) + c4*vc1.b; + tv = t1*(1 - vc1.g) + t2*vc1.g; + n1 = b1*(1 - vc1.b) + b2*vc1.b; + n2 = b3*(1 - vc1.b) + b4*vc1.b; + nv = n1*(1 - vc1.g) + n2*vc1.g; + break; + + + case 3051127652: //terrain_cb_w_4lyr vt: PNCCTX //ss1_05_gr.. + case 646532852: //terrain_cb_w_4lyr_spec vt: PNCCTX //hw1_07_grnd_c.. + //return float4(1, 1, 0, 1); + vc1 = m*(1 - vc0.a) + vc1*vc0.a; //perhaps another sampling of the mask is needed here + t1 = c1*(1 - vc1.b) + c2*vc1.b; + t2 = c3*(1 - vc1.b) + c4*vc1.b; + tv = t1*(1 - vc1.g) + t2*vc1.g; + n1 = b1*(1 - vc1.b) + b2*vc1.b; + n2 = b3*(1 - vc1.b) + b4*vc1.b; + nv = n1*(1 - vc1.g) + n2*vc1.g; + break; + + + case 2316006813: //terrain_cb_w_4lyr_2tex_blend vt: PNCCTTX //ch2_04_land02b, vb_34_beachn_01.. + case 3112820305: //terrain_cb_w_4lyr_2tex vt: PNCCTTX //ch1_05_land5.. + case 2601000386: //terrain_cb_w_4lyr_spec_pxm vt: PNCCTTX_2 //ch2_03_land05, grnd_low2.. _road + case 4105814572: //terrain_cb_w_4lyr_pxm vt: PNCCTTX_2 //ch2_06_house02.. vb_35_beache + case 3400824277: //terrain_cb_w_4lyr_pxm_spm vt: PNCCTTX_2 //ch2_04_land02b, ch2_06_terrain01a .. vb_35_beacha + //return float4(1, 1, 1, 1); + vc1 = m*(1 - vc0.a) + vc1*vc0.a; //perhaps another sampling of the mask is needed here + t1 = c1*(1 - vc1.b) + c2*vc1.b; + t2 = c3*(1 - vc1.b) + c4*vc1.b; + tv = t1*(1 - vc1.g) + t2*vc1.g; + n1 = b1*(1 - vc1.b) + b2*vc1.b; + n2 = b3*(1 - vc1.b) + b4*vc1.b; + nv = n1*(1 - vc1.g) + n2*vc1.g; + break; + + + case 295525123: //terrain_cb_w_4lyr_cm vt: PNCTTX //_prewtrproxy_2.. + case 417637541: //terrain_cb_w_4lyr_cm_tnt vt: PNCTTX //_prewtrproxy_2.. //golf course.. + //tv = 1;// c1;// *vc0.r; //TODO! + //nv = b0; + vc1 = m; //needs work! + t1 = c1*(1 - vc1.b) + c2*vc1.b; + t2 = c3*(1 - vc1.b) + c4*vc1.b; + tv = t1*(1 - vc1.g) + t2*vc1.g; + n1 = b1*(1 - vc1.b) + b2*vc1.b; + n2 = b3*(1 - vc1.b) + b4*vc1.b; + nv = n1*(1 - vc1.g) + n2*vc1.g; + break; + + case 3965214311: //terrain_cb_w_4lyr_cm_pxm_tnt vt: PNCTTTX_3 //vb_35_beache + case 4186046662: //terrain_cb_w_4lyr_cm_pxm vt: PNCTTTX_3 //cs6_08_struct08 + //m = min(m, vc0); + //return float4(m.rgb, m.a*0.5 + 0.5); + //return float4(vc0.rgb, vc0.a*0.5 + 0.5); + //return float4(0, 1, 1, 1); + //m = vc0; + vc1 = m; //needs work! + t1 = c1*(1 - vc1.b) + c2*vc1.b; + t2 = c3*(1 - vc1.b) + c4*vc1.b; + tv = t1*(1 - vc1.g) + t2*vc1.g; + n1 = b1*(1 - vc1.b) + b2*vc1.b; + n2 = b3*(1 - vc1.b) + b4*vc1.b; + nv = n1*(1 - vc1.g) + n2*vc1.g; + break; + + } + if (EnableTint == 1) + { + tv.rgb *= input.Tint.rgb; + } + + + if (RenderMode == 1) //normals + { + tv.rgb = normalize(input.Normal)*0.5+0.5; + } + else if (RenderMode == 2) //tangents + { + tv.rgb = normalize(input.Tangent.xyz)*0.5+0.5; + } + else if (RenderMode == 3) //colours + { + tv.rgb = input.Colour0.rgb; + if (RenderModeIndex == 2) tv.rgb = input.Colour1.rgb; + } + else if (RenderMode == 4) //texcoords + { + tv.rgb = float3(input.Texcoord0, 0); + if (RenderModeIndex == 2) tv.rgb = float3(input.Texcoord1, 0); + if (RenderModeIndex == 3) tv.rgb = float3(input.Texcoord2, 0); + } + else if (RenderMode == 5) //render diffuse maps + { + //nothing to do here yet, diffuse maps rendered by default + } + else if (RenderMode == 6) //render normalmaps + { + tv.rgb = nv.rgb; + } + else if (RenderMode == 7) //render spec maps + { + tv.rgb = 0.5; //nothing to see here yet... + } + else if (RenderMode == 8) //render direct texture + { + tv = c0; + } + + //nv = normalize(nv*2-1); + //float4 tang = input.Tangent; + float3 nz = normalize(input.Normal); + //float3 nx = normalize(tang.xyz); + //float3 ny = normalize(cross(nz, nx)); + ////float3 norm = normalize(nx*nv.x + ny*nv.y + nz*nv.z); + float3 norm = nz;// normalize(input.Normal) + + + if ((RenderMode == 0) && (EnableNormalMap == 1)) + { + norm = NormalMap(nv.xy, bumpiness, input.Normal.xyz, input.Tangent.xyz, input.Bitangent.xyz); + } + + float3 spec = 0; + + tv.rgb = FullLighting(tv.rgb, spec, norm, vc0, GlobalLights, EnableShadows, input.Shadows.x, input.LightShadow); + + + return float4(tv.rgb, saturate(tv.a)); +} \ No newline at end of file diff --git a/Shaders/TerrainVS.hlsli b/Shaders/TerrainVS.hlsli new file mode 100644 index 0000000..4547600 --- /dev/null +++ b/Shaders/TerrainVS.hlsli @@ -0,0 +1,87 @@ +#include "Shadowmap.hlsli" +#include "Quaternion.hlsli" + + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; +} +cbuffer VSEntityVars : register(b2) +{ + float4 CamRel; + float4 Orientation; + uint HasSkeleton; + uint HasTransforms; + uint TintPaletteIndex; + uint Pad1; + float3 Scale; + uint Pad2; +} +cbuffer VSModelVars : register(b3) +{ + float4x4 Transform; +} +cbuffer VSGeomVars : register(b4) +{ + uint EnableTint; + float TintYVal; + uint Pad4; + uint Pad5; +} + + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float4 Tint : COLOR2; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float4 Shadows : TEXCOORD4; + float4 LightShadow : TEXCOORD5; + float4 Tangent : TEXCOORD6; + float4 Bitangent : TEXCOORD7; + float3 CamRelPos : TEXCOORD8; +}; + +Texture2D TintPalette : register(t0); +SamplerState TextureSS : register(s0); + + + + +float3 ModelTransform(float3 ipos) +{ + float3 tpos = (HasTransforms == 1) ? mul(float4(ipos, 1), Transform).xyz : ipos; + float3 spos = tpos * Scale; + float3 bpos = mulvq(spos, Orientation); + return CamRel.xyz + bpos; +} +float4 ScreenTransform(float3 opos) +{ + float4 pos = float4(opos, 1); + float4 cpos = mul(pos, ViewProj); + cpos.z = DepthFunc(cpos.zw); + return cpos; +} +float3 NormalTransform(float3 inorm) +{ + float3 tnorm = (HasTransforms == 1) ? mul(inorm, (float3x3)Transform) : inorm; + float3 bnorm = normalize(mulvq(tnorm, Orientation)); + return bnorm; +} + +float4 ColourTint(float tx) +{ + float4 tnt = 1; + if (EnableTint == 1) + { + tnt = TintPalette.SampleLevel(TextureSS, float2(tx, TintYVal), 0); + } + return tnt; +} + diff --git a/Shaders/TerrainVS_PNCCT.cso b/Shaders/TerrainVS_PNCCT.cso new file mode 100644 index 0000000000000000000000000000000000000000..e20d72820b0857c6a1e9b0540d94ab18cafe0341 GIT binary patch literal 4908 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 a$p2Dq*B}QFGq$#(UY_dLJ-gKz@c#hVFw(OC literal 0 HcmV?d00001 diff --git a/Shaders/TerrainVS_PNCCTT.hlsl b/Shaders/TerrainVS_PNCCTT.hlsl new file mode 100644 index 0000000..a850e0b --- /dev/null +++ b/Shaders/TerrainVS_PNCCTT.hlsl @@ -0,0 +1,40 @@ +#include "TerrainVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 tnt = ColourTint(input.Colour0.b); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Colour0 = input.Colour0; + output.Colour1 = input.Colour1; + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = input.Texcoord1; + output.Texcoord2 = 0.5; + output.Tint = tnt; + output.Tangent = float4(btang, 0); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} diff --git a/Shaders/TerrainVS_PNCCTTTX.cso b/Shaders/TerrainVS_PNCCTTTX.cso new file mode 100644 index 0000000000000000000000000000000000000000..3601f02466cb8ac6c6e233e3a643def9a5c20c91 GIT binary patch literal 5504 zcmb`LO=w)#700hWELn~lt4a!{1ZQwUaEmdD?7B``nrD5CEs!;XW<1#4#8c0+HLWxw z-aN-{8-g$)rJFV@lSLp|ln_uCU1X6!D4}%Wg%?d0rHj&nDfOaV7(*RsOWptPzI(<` z)2Ecu9Jq7O{hxEs*FEpP$IPFboxAyuZ#>xlR{H4GH$FOh;Hg)CG~}Gy{E~CKG#}Gg z9e3`+Zs%@II5#SMWqzT2SQzrEl*PIyG~DRF9yqQ4KIYs%wHyH(AZ#1Qz zM4G(p3!0};Dj?f`pg?Xi=EDVY{F%;k1#;pw`9gu5I89!UuccR#xK?xZb|2b1Vh%)(Iu`fz08Vb`pVK)+L6?b~$l+z-lR5nL;0ufzy&2X&*9;Z~{KJ6X(p)XT ze=GcT;p~CT&L4%p4M0$$yTJ~@ybTucNrDrVzzHPa(*cjbwKptXH82-6|EvJ-2!FQ# z|DkYl3)}m4UK8+(9R5a7cvtg#1^5TT-!H&_DV$n`?au6cBH*I}{I>947vO&tezO4o zR5)j#$&=ZiYp(nDt9E-T-H3*1IA^j(JHG0+wzftjAI-^^+Lu>TFZA4eJJFWj#bzt6 zT)NbY)1Ee&O*`M9P`jw^{|xzjypgVchJ3DjrIQj9-8W>1uFQh{M!R>Vx#p^K<)vK48qI5Nw%zQx*|jUlY@A+=<4$nY zGmk!^#m-AkPkFpnYyTjA$enX?H8V}T`?809IiR(U2N^{-yjrN+D<42AjdG7f1^pR(e zA3br*E!Ivg-<2O?VBFL&vI^|ei}YgyHG|W|^2!1H;KH~4u|7LTsa zTL%wrBE$EJ0ngj<^$7abE9m=r1pC;8z{%D8vKIo^CsZG2F9g0v!}Qq;fj^?*>(F@d zzm$Ayt9E*RWm+2|WpqoypI2L#e^T=K;n&t;eZSk9Jjuz{_+{7{88!Mg@C9xxeOv6; zmW_-*d)B!ZB}*o=wejqMzb70Y#$y|PMmV;Or+&s$Gt;L|mlfi@Qf42!G5)kR9vMEs z;qhTSKHz7B?+W~{ay&TxOdo&7a~8%^L*qFw_(Xd-qgA!bF3lw!{glh%{PJeW$3$F1 zQC7p_YQ02q;x12RdSKTBhMseqFMLsUW`(i0{AkeES&|oo96v>JY$HFogPc8IS1aC@ z92&EEBD2>Bah;G2(`hIMsBt~Zi8zG#81Q%F)eQIic&5vK%M~9!=dd4MG;Z?paFB;t z7ACG2>?!B=&*?@odd-Ge|)fK?b#kY zYwl6{bEmV;%k7-@e-~Rn$@R87$@J{`CZ@g(#fW`k5cxX^ zIeYT6oi&)1gsd0Ur+YXzWH&-z<=%7teb~1lAAHMD7qI(JWJ3PVe|? literal 0 HcmV?d00001 diff --git a/Shaders/TerrainVS_PNCCTTTX.hlsl b/Shaders/TerrainVS_PNCCTTTX.hlsl new file mode 100644 index 0000000..585a06c --- /dev/null +++ b/Shaders/TerrainVS_PNCCTTTX.hlsl @@ -0,0 +1,42 @@ +#include "TerrainVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float4 Tangent : TANGENT; +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = NormalTransform(input.Tangent.xyz); + + float4 tnt = ColourTint(input.Colour0.b); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Colour0 = input.Colour0; + output.Colour1 = input.Colour1; + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = input.Texcoord1; + output.Texcoord2 = input.Texcoord2; + output.Tangent = float4(btang, input.Tangent.w); + output.Bitangent = float4(cross(btang, bnorm) * input.Tangent.w, 0); + output.Tint = tnt; + return output; +} diff --git a/Shaders/TerrainVS_PNCCTTX.cso b/Shaders/TerrainVS_PNCCTTX.cso new file mode 100644 index 0000000000000000000000000000000000000000..fe731543906b21240509a34747e1e0c6d782c956 GIT binary patch literal 5480 zcmb`LUx-}Q9mmi9$!<1AlddU95gmevl@QiVnkJ#GH~VL@3!9x`XB-k=beg%zPP;p^ z+_^Dn{lgMO(1+Hi;DZl7ND;OVKKP&@BBc}`1f>tfheAt``k;ahG=h}c@8{g}o7|n= zwUqjUGrx1bzu)=&JHLDGW#-P#%-;R?AAf%0(HH)D^5fQ5Pj78~KIEKR{jPJn#E&u` zcWz;~b8k#I_t^pGR_5l*hlC-oN?B8Pw}u=2*Vj(#ug0AFrZW z3;a^72p)(Wbu8|_0i4{>KdWMT0zgorFM=I{c?B%s`w31|0w<7wPX#;z*WR#n)i8Nn{M7=yBmA`j z{7K>D7Pj~8JSX7w9R5;Jcuo9`0{kuEZx-P12&YzIyE8j~6!2~VeqH$Q3-Hf`zgK{N zDV#G9^JMmCo9n*)s@h=1Bf|*V(s+uNAknFk~m)1FtQ5llkhDA#lh*~apCWZ8-Y`oefu)pIvtz={s(a*F!CGG z1U#=#dxC!;ZiK$d;_Xx`wZ-~kW!WuPR?eJSa1<+|Id zD8H5r^X?|UC^&&(4^mie$((Br&T?EEY6G~>Pcm>5q0hh$I64p*`GKD^<$(MAbim*y zLLYpuCg6EHW8m7-)2>dn;Ux&tH|E1(x zTeXF`l__nAl+pVN{+!Y;|ElEk!>_G1^>wi|d6JW@@yoC^GHUcF@Z;P}`i8hmTQ;)! zBab-um}JTRY;AM)Fux%jA2!D}^J(GOwmJ1P9cp$_VcjTYHnA1sLu;EO!!9^;?Ajc= z%%_F#3iIFP=HU1+ea^z>)ZgaR&E}jD^F(_&msPdMF7c9%d(vfbes8nnVr<%$oVbJ)*ZG;Z?paF7Qs3lmoh z_LOt`r}cQ6&dJSN{@Wzgg@y|n7^C*GJj8myv)DFOpUIEJnnz~mTlR%tzVN| zEWZi5V-uM__7~Of=C8Ne+S|7k;uwy!F{4P#583qbYwhcqkIm{KnX^7ZJ`{mueKc9h z&VxQe#yw!<`(y_>HS>MAgB)APukIipk(?fx(J!{>ch6NfWDs)txJV9${NN69{O{Dq z?4^&*hWYrm`}BY5DRTaQdW!wuc2B9k^ED)Wwr+I53^qbY+4)@ZeY*M!e!~0*@7-tQ} zdy;&i1>LVVO4+wSImpY;WbxSd20oxkxssjTrav5kZa$nJ`iqM4`Fj&z9pP#3V9_h!!#HKDG)R`+DwF!aj8;9%3zqbB9>4F_i5 zS7UlEkqO&*EDLk+=_fLWiK9x)F^`VpBP=V^DBVSJm}nG4%Z ztk@oo^y8d*#Sg#uiA>h&r|PLzbq(T%^miup_O)Q0yDM1!2U%a4Kz-_KW$T^zzX3*~ B__qK6 literal 0 HcmV?d00001 diff --git a/Shaders/TerrainVS_PNCCTTX.hlsl b/Shaders/TerrainVS_PNCCTTX.hlsl new file mode 100644 index 0000000..15907a3 --- /dev/null +++ b/Shaders/TerrainVS_PNCCTTX.hlsl @@ -0,0 +1,41 @@ +#include "TerrainVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float4 Tangent : TANGENT; +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = NormalTransform(input.Tangent.xyz); + + float4 tnt = ColourTint(input.Colour0.b); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Colour0 = input.Colour0; + output.Colour1 = input.Colour1; + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = input.Texcoord1; + output.Texcoord2 = 0.5; + output.Tangent = float4(btang, input.Tangent.w); + output.Bitangent = float4(cross(btang, bnorm) * input.Tangent.w, 0); + output.Tint = tnt; + return output; +} diff --git a/Shaders/TerrainVS_PNCCTX.cso b/Shaders/TerrainVS_PNCCTX.cso new file mode 100644 index 0000000000000000000000000000000000000000..df8b4bd88b99169a199c4d2d969c5fc815fb1653 GIT binary patch literal 5456 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 E0ZiBTP5=M^ literal 0 HcmV?d00001 diff --git a/Shaders/TerrainVS_PNCTTTX.hlsl b/Shaders/TerrainVS_PNCTTTX.hlsl new file mode 100644 index 0000000..d1e1b56 --- /dev/null +++ b/Shaders/TerrainVS_PNCTTTX.hlsl @@ -0,0 +1,41 @@ +#include "TerrainVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float4 Colour0 : COLOR0; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float4 Tangent : TANGENT; +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = NormalTransform(input.Tangent.xyz); + + float4 tnt = ColourTint(input.Colour0.b); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Colour0 = input.Colour0; + output.Colour1 = float4(0.5,0.5,0.5,1); + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = input.Texcoord1; + output.Texcoord2 = input.Texcoord2; + output.Tangent = float4(btang, input.Tangent.w); + output.Bitangent = float4(cross(btang, bnorm) * input.Tangent.w, 0); + output.Tint = tnt; + return output; +} diff --git a/Shaders/TerrainVS_PNCTTX.cso b/Shaders/TerrainVS_PNCTTX.cso new file mode 100644 index 0000000000000000000000000000000000000000..0c2ff0cf65836224f584c7b79ca8c993c532eb62 GIT binary patch literal 5456 zcmb`LUx-{+9mmhkZg#V2G}~>2BGL|_lvYC6ZemP}n4A4G$>Q$LurnPJA8c=vkj| zZf3u8FHbu6x5Lh@Ei6`!3WHyhu%_-ydfeCtA3Cl7Gw$4fwHyT-B5d=F>!+j<8)JGt z6lw6h&uN@SsDMoWp#r|~7>^e4+0SI2Ea2m>@fQpD_-Xt`a;<+QP3m>mXm|Rxcq8fe z6W6TQFD9L&8K*s0UyobetDEtbUp4ECoqoIjov>Kxwvvr7Kbv$n{gjv<&>pum{w0?@ za>2eND`E^pj4F$JWC$lVIe?w!f z0ROx27loq(nVq+UzXE_$qIZKGoOuN-;8Qp!Dud%lz-Iy;flD_mT`f$W)%f!Qyd(T( z0scMV#1_;Cc77z_*E#&9AaGOTZwm0=3;$gK{zu{DDyTcN^H%|{72vmpzg~d&31Ct?dLbBCg{|Nqk_e!UaPjugi6e-IoqovLZPNzKCsJFkH+?$fAYu9~)!PCxFqyB&8f?$w`9bm3{PTtBcY*J3u(xYN7TO*eb_yK$-0O0JQ+C!BAX zK|iUH1CdyAwiSGegy-`*Ff5@rgUoO~{wW;Ha623C3g@mIj_*C;mV^5x(nK|~v z$>XO^xTX5p)z`ESZsW&GdWD3 zf&W&c5jgFMom#cN)L5#ny4C91%9&+1UtO-QxyIu8`D%4-!8OjTo?TpRxSguvXvr|| zXyS;%CJfkvWX>(y=9+`EoRC6&2={S_2W~9nd9VYH3LY zNFh>0Z^-!z3cvD`vX75_ZLO)#i>-;1m~73yJhp~Mj=l-}EH{w86&{qzRyKe7Y3H61 zFP+NPHb;l~9pUW3d{%R8+Z@{_L;fzyl{@9k4*CgpwYE7tY=JY!md&xnd{+3rF#l6- z4o)php8VUKoZFmS*_^sCPo+yO*3}mKG?rE3X_xu=#qF~93BN|7ELSJhN~!qxU7610 zz^(@jIp?-d-!D6J!qBaJKFF(P#09};pCUfC;UC$9kIq-sa<|2Y#%-L;>@|a5r)0xq zn(_f^Ue98}4(Q&3umB|-5=E`*L{a3md1_V7w=Z7dof=^-g)p zuPcFH`9bE7ePgf(G_9>PMO!TGQn?-!SCG6fT;`4oB_hu0v3_kZZvcvo1i`9ntKh%Se^`iRp0Cj_RBlK17 zJ?Gzt0~^|dZyE9ecK6}z9FY_9>T~r_Hd?NcD@FQoPPw*c`!qVU((&gue9wW|x7N7M zD0RlpZOIW^Dbmjnp~E|c@2#g~2YX;?z^rFY4*y3Y{fJDC+S)y47~g4De_{Lam0Fb| v{S4ypbN6+btT)ay`dT*h-~+_}YRbLO3+vpy!SeseddwK=S)XTH?=}7p(Mt1S literal 0 HcmV?d00001 diff --git a/Shaders/TerrainVS_PNCTTX.hlsl b/Shaders/TerrainVS_PNCTTX.hlsl new file mode 100644 index 0000000..b44b868 --- /dev/null +++ b/Shaders/TerrainVS_PNCTTX.hlsl @@ -0,0 +1,40 @@ +#include "TerrainVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float4 Colour0 : COLOR0; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float4 Tangent : TANGENT; +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = NormalTransform(input.Tangent.xyz); + + float4 tnt = ColourTint(input.Colour0.b); //colour tinting if enabled + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Colour0 = input.Colour0; + output.Colour1 = float4(0.5,0.5,0.5,1); + output.Texcoord0 = input.Texcoord0; + output.Texcoord1 = input.Texcoord1; + output.Texcoord2 = 0.5; + output.Tangent = float4(btang, input.Tangent.w); + output.Bitangent = float4(cross(btang, bnorm) * input.Tangent.w, 0); + output.Tint = tnt; + return output; +} diff --git a/Shaders/TreesLodPS.cso b/Shaders/TreesLodPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..d8645ac0d83bf42f7d137289709bd3fb38b71dbd GIT binary patch literal 2056 zcma)6OHUI~6h3Wv6clMHCdOzSU8y02S1K9;)INZu(56!ex{(2jG%2(hO2n8bY20Xt zOIB>$xTz*=P1w3)AsZHoiSZ|x=*k4YZ|2@Y0gWd)bI<+G>$_*}OmymA03dm97q zKP7g{&u{O3c;gWfzh9&tYcDk66Zr;hs}oso6iG*8@c{N-_;#RxXqr4>7Cni47G3oG`bRg{!z&Ssag zla{>`vI5${vEfrR)^! zkIJ5g&G+tcZjE2|fxlDp<0)xwtNjjEV*2zN-vy2Fect95si>*Hv$FTYyq8M1KiDVk2lHk;ic=jMC1FD5}DCC4%nQ(eImO+j=5=|H3 z90I-%y^nFmUmLK%6RP*DNqs=N)4UP59~UwDqH9k~h|C1UX9ogK9PMt{JQwZju*o5d z{2zv!gPD1W8K4_fUtIH=;p77r&yd^ms?_~VpwQoG=&OxtH_EI%<|31XC z59j);)#ah%1BUo@eB7&Qm5nNikRkP&BmER&K~?XPns>LznePf~cxgCsNBe1v?+LL@ zy5}wAGtQlh4C+kQ{W4Bj@y!19S8_bzgqF=-aIQ8utNjP&t$5 z++5D98rS5WS^LPHK5}k2;^SV&ApfsC8Wa!Clsw~V*8F#A9vh8^JdV$v??BJcHq^UR s?}ho~!F;X*7?+s|XZUZxU3I<-EY5$7nT(;Zp0*v}$m2AeXZRoa1KDQf;{X5v literal 0 HcmV?d00001 diff --git a/Shaders/TreesLodPS.hlsl b/Shaders/TreesLodPS.hlsl new file mode 100644 index 0000000..94cbedc --- /dev/null +++ b/Shaders/TreesLodPS.hlsl @@ -0,0 +1,53 @@ +#include "Common.hlsli" + +Texture2D Colourmap : register(t0); +SamplerState TextureSS : register(s0); + + +cbuffer PSSceneVars : register(b0) +{ + ShaderGlobalLightParams GlobalLights; +} +cbuffer PSEntityVars : register(b1) +{ + uint EnableTexture; + uint Pad1; + uint Pad2; + uint Pad3; +} + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float2 Texcoord : TEXCOORD0; + float4 Colour : COLOR0; +}; + + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + //return float4(1,0,0,1);//red + + float4 c = 0;// float4(input.Colour.rgb, 1); + //return c; + + if (EnableTexture == 1) + { + //c = Colourmap.SampleLevel(TextureSS, input.Texcoord, 0); + c = Colourmap.Sample(TextureSS, input.Texcoord); + if (c.a <= 0.25) discard; + c.a = 1; + // c = float4(input.Colour.rgb, 1); + } + + float3 norm = input.Normal; + float lf = saturate(dot(normalize(norm), GlobalLights.LightDir.xyz)); + + c.rgb = GlobalLighting(c.rgb, norm, input.Colour, lf, GlobalLights); + c.a = saturate(c.a); + + return c; +} \ No newline at end of file diff --git a/Shaders/TreesLodVS.cso b/Shaders/TreesLodVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..709737440f7fbc20736b5803408416e8e6a6d098 GIT binary patch literal 3020 zcma)7PiP!v6o0$hWV=Z*F+C|FLy=lVLb?rUEyYf{n{5J{?6R{i5tK4yr)JyDZk-tv zsfQ2>q7=PIPaZu8t2e!=5b)rk2fgV{ElAHj6i@2!_s#b<D832Y z0j?3+)<1@P&f!`XZ^_?j1YH?q&{t+? z6{&@tpcngbr{9xRKk}{z-5`c8avXkkFj&FX4E@LSZUT45;LF_` z+kP{MVli6M%BxYp>$!nG{ca>NbllWpvK}t$e&}Nk>z%EzAN8-s&Z))=&T7@GI?0`O zO8uQ1oo*01OY>*uUtU^Rm_NOA=G>yJd6zftqZZy{@(*Aolxb)tFY=Ruki>ZsfaPbf z5^?sKgF;+Si@0Hn(}zTi_d@--CQ)`Z7_+kG(Y3S1T7J#J&z4H6@(;i`o*QcHGchtL4UBH0&Zvgha2Qyvj$8iO4#2tu^Y}`#NaSQ8@o(9>fSMePcjwkY?|1Tv|2f#Tmr2Aj zJ*DP|ZF#jr{DH2eRL9q%}8dRG`obMwyVJcz?*YIuG)2ko7AJME|M8uw&eK9hHC z&ar2uchG*%=waTaL+qTNc~=jyGdJyfhuB#sG8a;JW%w=8bAyWv>y@$Q( v_pgFkG8ZxZ4pyE`zM-#R6kc<=$$!X;VET~?;1gi>NK%=s9{rqn%su}A2uBjk literal 0 HcmV?d00001 diff --git a/Shaders/TreesLodVS.hlsl b/Shaders/TreesLodVS.hlsl new file mode 100644 index 0000000..2d41c21 --- /dev/null +++ b/Shaders/TreesLodVS.hlsl @@ -0,0 +1,95 @@ +#include "Common.hlsli" +#include "Quaternion.hlsli" + + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; +} +cbuffer VSEntityVars : register(b1) +{ + float4 CamRel; + float4 Orientation; + uint HasSkeleton; + uint HasTransforms; + uint Pad0; + uint Pad1; + float3 Scale; + uint Pad2; +} +cbuffer VSModelVars : register(b2) +{ + float4x4 Transform; +} +cbuffer TreesLodShaderVSGeometryVars : register(b3) +{ + float4 AlphaTest; + float4 AlphaScale; + float4 UseTreeNormals; + float4 treeLod2Normal; + float4 treeLod2Params; +} + + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float2 Texcoord2 : TEXCOORD2; + float2 Texcoord3 : TEXCOORD3; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float2 Texcoord : TEXCOORD0; + float4 Colour : COLOR0; +}; + + + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + + //first find the base point of the billboard.. full transformation may not be necessary! + float3 ipos = input.Position.xyz; + float3 tpos = (HasTransforms == 1) ? mul(float4(ipos, 1), Transform).xyz : ipos; + float3 spos = tpos;// *Scale; + float3 bpos = mulvq(spos, Orientation); + float3 opos = CamRel.xyz + bpos; + + float3 dir = normalize(opos); + float3 bbside = normalize(cross(dir, treeLod2Normal.xyz)); + float2 bbvpos = treeLod2Params.xy*(0.5 - input.Texcoord0)*input.Texcoord2; + opos += bbside*bbvpos.x; + opos += treeLod2Normal.xyz*bbvpos.y; + + + + //float3 ipos = input.Position.xyz + float3(treeLod2Params.xy*(input.Texcoord0-0.5)*input.Texcoord2,0); + //float3 tpos = (HasTransforms == 1) ? mul(float4(ipos, 1), Transform).xyz : ipos; + //float3 spos = tpos;// *Scale; + //float3 bpos = mulvq(spos, Orientation); + //float3 opos = CamRel.xyz + bpos; + + float4 pos = float4(opos, 1); + float4 cpos = mul(pos, ViewProj); + cpos.z = DepthFunc(cpos.zw); + + //float3 inorm = input.Normal; + //float3 tnorm = (HasTransforms == 1) ? mul(inorm, (float3x3)Transform) : inorm; + //float3 bnorm = normalize(mulvq(tnorm, Orientation)); + float3 bnorm = normalize(-pos.xyz); //normal pointing towards the camera... + + output.Position = cpos; + output.Normal = bnorm; + output.Texcoord = input.Texcoord1; + output.Colour = input.Colour0;// float4(input.Texcoord2, 0, 1);// input.Colour1; + return output; +} \ No newline at end of file diff --git a/Shaders/WaterPS.cso b/Shaders/WaterPS.cso new file mode 100644 index 0000000000000000000000000000000000000000..d287c4c5d40cb29e97f1c8cf519a9f9bd4338b65 GIT binary patch literal 10084 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 Colourmap : register(t0); +Texture2D Bumpmap : register(t2); +Texture2D Foammap : register(t3); +Texture2D WaterBumpSampler : register(t4);// graphics.ytd, waterbump and waterbump2 +Texture2D WaterBumpSampler2 : register(t5); +Texture2D WaterFog : register(t6); +SamplerState TextureSS : register(s0); + + +cbuffer PSSceneVars : register(b0) +{ + ShaderGlobalLightParams GlobalLights; + uint EnableShadows; + uint RenderMode;//0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct + uint RenderModeIndex; + uint RenderSamplerCoord; + uint EnableWaterbumps;//if the waterbump textures are ready.. + uint EnableFogtex; //if the fog texture is ready + uint ScnPad1; + uint ScnPad2; + float4 gFlowParams; + float4 CameraPos; + float4 WaterFogParams; //xy = base location, zw = inverse size +} +cbuffer PSGeomVars : register(b2) +{ + uint EnableTexture; + uint EnableBumpMap; + uint EnableFoamMap; + uint ShaderMode; + float SpecularIntensity; + float SpecularFalloff; + float GeoPad1; + float GeoPad2; + float WaveOffset; //for terrainfoam + float WaterHeight; //for terrainfoam + float WaveMovement; //for terrainfoam + float HeightOpacity; //for terrainfoam + float RippleSpeed; + float RippleScale; + float RippleBumpiness; + float GeoPad3; +} + + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float4 Flow : TEXCOORD1; + float4 Shadows : TEXCOORD3; + float4 LightShadow : TEXCOORD4; + float4 Colour0 : COLOR0; + float4 Tangent : TEXCOORD5; + float4 Bitangent : TEXCOORD6; + float3 CamRelPos : TEXCOORD7; +}; + + + + +float3 RippleNormal(VS_OUTPUT input, float3 worldpos) +{ + //// + //// Input signature: + //// + //// Name Index Mask Register SysValue Format Used + //// -------------------- ----- ------ -------- -------- ------- ------ + //// SV_Position 0 xyzw 0 POS float + //// TEXCOORD 0 xyzw 1 NONE float xyzw + //// TEXCOORD 1 xyzw 2 NONE float xyzw + //// TEXCOORD 2 xyzw 3 NONE float zw + //// TEXCOORD 3 xyzw 4 NONE float xyzw //NORMAL +half + //// TEXCOORD 4 xyzw 5 NONE float zw //FLOW + //// + // + + float3 norm = input.Normal.xyz; + float v2w = input.Colour0.r; //vertex red channel + + float4 r0, r1, r2, r3, r4; + + r0.xy = input.Flow.zw * RippleSpeed; //mul r0.xy, v5.zwzz, RippleSpeed + r1 = -r0.xyxy * gFlowParams.xxyy + worldpos.xyxy; //mad r1.xyzw, -r0.xyxy, gFlowParams.xxyy, v2.xyxy + r0.x = min(sqrt(dot(r0.xy, r0.xy)), 1.0); //dp2 r0.x, r0.xyxx, r0.xyxx //sqrt r0.x, r0.x //min r0.x, r0.x, l(1.000000) + r0.yz = r1.xy * RippleScale; //mul r0.yz, r1.xxyx, RippleScale + r1.xy = r1.zw * RippleScale + 0.5; //mad r1.xy, r1.zwzz, RippleScale, l(0.500000, 0.500000, 0.000000, 0.000000) + r1.xy = r1.xy * 2.3; //mul r1.xy, r1.xyxx, l(2.300000, 2.300000, 0.000000, 0.000000) + r0.yz = r0.yz * 2.3; //mul r0.yz, r0.yyzy, l(0.000000, 2.300000, 2.300000, 0.000000) + r2 = WaterBumpSampler2.Sample(TextureSS, r0.yz); //sample r2.xyzw, r0.yzyy, WaterBumpSampler2.xyzw, s14 + r3 = WaterBumpSampler.Sample(TextureSS, r0.yz); //sample r3.xyzw, r0.yzyy, WaterBumpSampler.xyzw, s10 + r4 = WaterBumpSampler2.Sample(TextureSS, r1.xy); //sample r4.xyzw, r1.xyxx, WaterBumpSampler2.xyzw, s14 + r1 = WaterBumpSampler.Sample(TextureSS, r1.xy); //sample r1.xyzw, r1.xyxx, WaterBumpSampler.xyzw, s10 + r3.zw = r1.xy; //mov r3.zw, r1.xxxy + r2.zw = r4.xy; //mov r2.zw, r4.xxxy + r1 = r2 + r3; //add r1.xyzw, r2.xyzw, r3.xyzw + r2 = r3 + 0.5; //add r2.xyzw, r3.xyzw, l(0.500000, 0.500000, 0.500000, 0.500000) + r1 = r1 - r2; //add r1.xyzw, r1.xyzw, -r2.xyzw + r0 = r1 * r0.x + r2; //mad r0.xyzw, r0.xxxx, r1.xyzw, r2.xyzw + r0 = r0 * 2 - 2; //mad r0.xyzw, r0.xyzw, l(2.000000, 2.000000, 2.000000, 2.000000), l(-2.000000, -2.000000, -2.000000, -2.000000) + r0 = r0 * gFlowParams.zzww; //mul r0.xyzw, r0.xyzw, gFlowParams.zzww + r0.xy = r0.xy + r0.zw; //add r0.xy, r0.zwzz, r0.xyxx + r0.zw = r0.xy * RippleBumpiness;//mul r0.zw, r0.xxxy, RippleBumpiness + //r0.x = sqrt(dot(r0.xy, r0.xy)); //dp2 r0.x, r0.xyxx, r0.xyxx //sqrt r0.x, r0.x + //r0.x = r0.x * 0.27 + 0.44; //mad r0.x, r0.x, l(0.270000), l(0.440000) + r1.xy = r0.zw * v2w + norm.xy; //mad r1.xy, r0.zwzz, v2.wwww, v4.xyxx + r1.z = norm.z; //mov r1.z, v4.z + //return normalize(r1.xyz); + r0.y = dot(r1.xyz, r1.xyz); //dp3 r0.y, r1.xyzx, r1.xyzx + r0.y = 1.0 / sqrt(r0.y); //rsq r0.y, r0.y + r2.xyz = -r1.xyz * r0.y + float3(0, 0, 1); //mad r2.xyz, -r1.xyzx, r0.yyyy, l(0.000000, 0.000000, 1.000000, 0.000000) + r0.yzw = r1.xyz * r0.y; //mul r0.yzw, r0.yyyy, r1.xxyz + //r1.xyz = r2.xyz * 0.833333 + r0.yzw; //mad r1.xyz, r2.xyzx, l(0.833333, 0.833333, 0.833333, 0.000000), r0.yzwy + //r2.xyz = worldpos - //add r2.xyz, v2.xyzx, -gViewInverse[3].xyzx + + return r0.yzw; + //return r0.wzy; + ////return float3(r0.w, r0.z, r0.y); + + ////return normalize(input.Normal); +} + + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + float4 c = float4(0.1, 0.18, 0.25, 0.8); + //if (RenderMode == 0) c = float4(1, 1, 1, 1); + + //c.a *= input.Colour0.a; + + float3 camrel = input.CamRelPos; + float3 worldpos = camrel + CameraPos.xyz; + if ((EnableFoamMap == 0) && (EnableFogtex == 1)) + { + float2 fogtc = saturate((worldpos.xy - WaterFogParams.xy) * WaterFogParams.zw); + fogtc.y = 1.0 - fogtc.y; + c = WaterFog.Sample(TextureSS, fogtc); + c.a = 0.9; + } + + + float3 norm = EnableFoamMap ? normalize(input.Normal) : RippleNormal(input, worldpos);// normalize(input.Normal); + + if (RenderMode == 1) //normals + { + c.rgb = norm*0.5+0.5; + } + else if (RenderMode == 2) //tangents + { + c.rgb = normalize(input.Tangent.rgb)*0.5+0.5; + } + else if (RenderMode == 3) //colours + { + c.rgb = input.Colour0.rgb; + } + else if (RenderMode == 4) //texcoords + { + c.rgb = float3(input.Texcoord0, 0); + } + else if ((RenderMode == 8) || (EnableTexture == 1)) //single texture or diffuse enabled + { + c.rgb = Colourmap.Sample(TextureSS, input.Texcoord0).rgb; + } + else if (EnableFoamMap) + { + c = Foammap.Sample(TextureSS, input.Texcoord0); + } + + + float3 spec = 0; + + if (RenderMode == 0) + { + + float4 nv = Bumpmap.Sample(TextureSS, input.Texcoord0); //sample r1.xyzw, v2.xyxx, t3.xyzw, s3 (BumpSampler) + + + float2 nmv = nv.xy; + float4 r0 = 0, r1, r2, r3; + + float bumpiness = 0.5; + + if (EnableBumpMap) + { + norm = NormalMap(nmv, bumpiness, input.Normal.xyz, input.Tangent.xyz, input.Bitangent.xyz); + } + + + float3 tc = c.rgb; + c.rgb = tc;// *r0.z; //diffuse factors... + + float3 incident = normalize(input.CamRelPos); + float3 refl = normalize(reflect(incident, norm)); + float specb = saturate(dot(refl, GlobalLights.LightDir)); + float specp = max(exp(specb * 10) - 1, 0); + spec += GlobalLights.LightDirColour.rgb * 0.00006 * specp * SpecularIntensity; + + if (ShaderMode == 1) //river foam + { + c.a *= input.Colour0.g; + } + else if (ShaderMode == 2) //terrain foam + { + c.a *= c.r; + c.a *= input.Colour0.r; + } + else + { + ///c.a = 1; + } + } + + + + float4 fc = c; + + c.rgb = FullLighting(c.rgb, spec, norm, 0, GlobalLights, EnableShadows, input.Shadows.x, input.LightShadow); + c.a = saturate(c.a); + return c; +} + + + + + + + + + + + + + + + + + + + + + + + + +/* +water_terrainfoam.fxc_PSFoam + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer misc_globals +// { +// +// float4 globalFade; // Offset: 0 Size: 16 [unused] +// float globalHeightScale; // Offset: 16 Size: 4 [unused] +// float4 g_Rage_Tessellation_CameraPosition;// Offset: 32 Size: 16 [unused] +// float4 g_Rage_Tessellation_CameraZAxis;// Offset: 48 Size: 16 [unused] +// float4 g_Rage_Tessellation_ScreenSpaceErrorParams;// Offset: 64 Size: 16 [unused] +// float4 g_Rage_Tessellation_LinearScale;// Offset: 80 Size: 16 [unused] +// float4 g_Rage_Tessellation_Frustum[4];// Offset: 96 Size: 64 [unused] +// float4 g_Rage_Tessellation_Epsilons;// Offset: 160 Size: 16 [unused] +// float4 globalScalars; // Offset: 176 Size: 16 +// float4 globalScalars2; // Offset: 192 Size: 16 +// float4 globalScalars3; // Offset: 208 Size: 16 [unused] +// float4 globalScreenSize; // Offset: 224 Size: 16 [unused] +// uint4 gTargetAAParams; // Offset: 240 Size: 16 [unused] +// float4 colorize; // Offset: 256 Size: 16 [unused] +// float4 gGlobalParticleShadowBias; // Offset: 272 Size: 16 [unused] +// float gGlobalParticleDofAlphaScale;// Offset: 288 Size: 4 [unused] +// float gGlobalFogIntensity; // Offset: 292 Size: 4 [unused] +// float4 gPlayerLFootPos; // Offset: 304 Size: 16 [unused] +// float4 gPlayerRFootPos; // Offset: 320 Size: 16 [unused] +// +// } +// +// cbuffer more_stuff +// { +// +// float4 gEntitySelectColor[2]; // Offset: 0 Size: 32 [unused] +// float4 gAmbientOcclusionEffect; // Offset: 32 Size: 16 [unused] +// float4 gDynamicBakesAndWetness; // Offset: 48 Size: 16 +// float4 gAlphaRefVec0; // Offset: 64 Size: 16 [unused] +// float4 gAlphaRefVec1; // Offset: 80 Size: 16 [unused] +// float gAlphaTestRef; // Offset: 96 Size: 4 [unused] +// bool gTreesUseDiscard; // Offset: 100 Size: 4 [unused] +// float gReflectionMipCount; // Offset: 104 Size: 4 [unused] +// bool gUseTransparencyAA; // Offset: 108 Size: 4 [unused] +// bool gUseFogRay; // Offset: 112 Size: 4 [unused] +// +// } +// +// cbuffer water_terrainfoam_locals +// { +// +// float WaveOffset; // Offset: 0 Size: 4 +// float WaterHeight; // Offset: 4 Size: 4 +// float WaveMovement; // Offset: 8 Size: 4 +// float HeightOpacity; // Offset: 12 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// FoamSampler sampler NA NA s3 1 +// WetSampler sampler NA NA s9 1 +// WaterBumpSampler sampler NA NA s10 1 +// FoamSampler texture float4 2d t3 1 +// WetSampler texture float4 2d t9 1 +// WaterBumpSampler texture float4 2d t10 1 +// misc_globals cbuffer NA NA cb2 1 +// more_stuff cbuffer NA NA cb5 1 +// water_terrainfoam_locals cbuffer NA NA cb10 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float +// TEXCOORD 0 xyzw 1 NONE float zw +// TEXCOORD 1 xyz 2 NONE float xyz +// TEXCOORD 2 xyz 3 NONE float +// TEXCOORD 3 xyz 4 NONE float +// TEXCOORD 4 xyzw 5 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// SV_Target 1 xyzw 1 TARGET float xyzw +// SV_Target 2 xyzw 2 TARGET float xyzw +// SV_Target 3 xyzw 3 TARGET float xyzw +// +ps_4_0 +dcl_constantbuffer CB2[13], immediateIndexed +dcl_constantbuffer CB5[4], immediateIndexed +dcl_constantbuffer CB10[1], immediateIndexed +dcl_sampler s3, mode_default +dcl_sampler s9, mode_default +dcl_sampler s10, mode_default +dcl_resource_texture2d (float,float,float,float) t3 +dcl_resource_texture2d (float,float,float,float) t9 +dcl_resource_texture2d (float,float,float,float) t10 +dcl_input_ps linear v1.zw +dcl_input_ps linear v2.xyz +dcl_input_ps linear v5.xyzw +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_output o2.xyzw +dcl_output o3.xyzw +dcl_temps 3 +mov r0.x, l(0) +sample r1.xyzw, v5.zwzz, t9.xyzw, s9 +dp2 r0.y, r1.xxxx, cb10[0].zzzz +add r0.xy, -r0.xyxx, v5.xyxx +add r0.xy, r0.xyxx, cb10[0].xxxx +add r0.zw, r0.xxxy, v5.xxxy +sample r2.xyzw, r0.xyxx, t3.xyzw, s3 +sample r0.xyzw, r0.zwzz, t10.xyzw, s10 +mul r0.x, r0.x, r2.y +add r0.y, v1.z, -cb10[0].y +max r0.y, r0.y, l(0.000000) +mul r0.y, r0.y, cb10[0].w +mul r0.x, r0.y, r0.x +mul r0.x, r0.x, v1.w +mul_sat r0.x, r1.x, r0.x +mul r0.x, r0.x, cb2[11].x +mov o0.w, r0.x +add r0.y, v2.z, l(-0.350000) +mul_sat r0.y, r0.y, l(1.538462) +mul r0.y, r0.y, cb5[3].z +add r0.z, -cb2[12].z, l(1.000000) +mul r0.y, r0.z, r0.y +mul r0.y, r0.y, cb2[11].z +mad o0.xyz, r0.yyyy, l(-0.500000, -0.500000, -0.500000, 0.000000), l(1.000000, 1.000000, 1.000000, 0.000000) +mul r0.yz, r0.yyyy, l(0.000000, 0.500000, 0.488281, 0.000000) +sqrt o2.xy, r0.yzyy +mov o1.w, r0.x +mov o2.w, r0.x +mad o1.xyz, v2.xyzx, l(0.500000, 0.500000, 0.500000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +mov o2.z, l(0.980000) +mov o3.xyzw, l(0,0,0,0) +ret +// Approximately 32 instruction slots used + + + +*/ + + + + + + + + + +/* +water_riverfoam.fxc_PSFoam + + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer misc_globals +// { +// +// float4 globalFade; // Offset: 0 Size: 16 [unused] +// float globalHeightScale; // Offset: 16 Size: 4 [unused] +// float4 g_Rage_Tessellation_CameraPosition;// Offset: 32 Size: 16 [unused] +// float4 g_Rage_Tessellation_CameraZAxis;// Offset: 48 Size: 16 [unused] +// float4 g_Rage_Tessellation_ScreenSpaceErrorParams;// Offset: 64 Size: 16 [unused] +// float4 g_Rage_Tessellation_LinearScale;// Offset: 80 Size: 16 [unused] +// float4 g_Rage_Tessellation_Frustum[4];// Offset: 96 Size: 64 [unused] +// float4 g_Rage_Tessellation_Epsilons;// Offset: 160 Size: 16 [unused] +// float4 globalScalars; // Offset: 176 Size: 16 [unused] +// float4 globalScalars2; // Offset: 192 Size: 16 [unused] +// float4 globalScalars3; // Offset: 208 Size: 16 +// float4 globalScreenSize; // Offset: 224 Size: 16 [unused] +// uint4 gTargetAAParams; // Offset: 240 Size: 16 [unused] +// float4 colorize; // Offset: 256 Size: 16 [unused] +// float4 gGlobalParticleShadowBias; // Offset: 272 Size: 16 [unused] +// float gGlobalParticleDofAlphaScale;// Offset: 288 Size: 4 [unused] +// float gGlobalFogIntensity; // Offset: 292 Size: 4 [unused] +// float4 gPlayerLFootPos; // Offset: 304 Size: 16 [unused] +// float4 gPlayerRFootPos; // Offset: 320 Size: 16 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// FoamSampler sampler NA NA s2 1 +// LightingSampler sampler NA NA s15 1 +// FoamSampler texture float4 2d t2 1 +// LightingSampler texture float4 2d t15 1 +// misc_globals cbuffer NA NA cb2 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float +// TEXCOORD 0 xyzw 1 NONE float w +// TEXCOORD 1 xyzw 2 NONE float xy w +// TEXCOORD 2 xy 3 NONE float xy +// TEXCOORD 3 xyz 4 NONE float xyz +// TEXCOORD 4 xyz 5 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_4_0 +dcl_constantbuffer CB2[14], immediateIndexed +dcl_sampler s2, mode_default +dcl_sampler s15, mode_default +dcl_resource_texture2d (float,float,float,float) t2 +dcl_resource_texture2d (float,float,float,float) t15 +dcl_input_ps linear v1.w +dcl_input_ps linear v2.xyw +dcl_input_ps linear v3.xy +dcl_input_ps linear v4.xyz +dcl_input_ps linear v5.xyz +dcl_output o0.xyzw +dcl_temps 1 +div r0.xy, v2.xyxx, v2.wwww +sample r0.xyzw, r0.xyxx, t15.xyzw, s15 +mad r0.xyz, v5.xyzx, r0.wwww, v4.xyzx +mul o0.xyz, r0.xyzx, cb2[13].zzzz +sample r0.xyzw, v3.xyxx, t2.xyzw, s2 +mul r0.x, r0.w, v1.w +mul o0.w, r0.x, r0.x +ret +// Approximately 8 instruction slots used + + + +*/ + + + + + + + +/* +water_river.fxc_PS + +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float +// TEXCOORD 0 xyzw 1 NONE float xyzw +// TEXCOORD 1 xyzw 2 NONE float xyzw +// TEXCOORD 2 xyzw 3 NONE float zw +// TEXCOORD 3 xyzw 4 NONE float xyzw +// TEXCOORD 4 xyzw 5 NONE float zw +// + +mul r0.xy, v5.zwzz, RippleSpeed +mad r1.xyzw, -r0.xyxy, gFlowParams.xxyy, v2.xyxy +dp2 r0.x, r0.xyxx, r0.xyxx +sqrt r0.x, r0.x +min r0.x, r0.x, l(1.000000) +mul r0.yz, r1.xxyx, RippleScale +mad r1.xy, r1.zwzz, RippleScale, l(0.500000, 0.500000, 0.000000, 0.000000) +mul r1.xy, r1.xyxx, l(2.300000, 2.300000, 0.000000, 0.000000) +mul r0.yz, r0.yyzy, l(0.000000, 2.300000, 2.300000, 0.000000) +sample r2.xyzw, r0.yzyy, WaterBumpSampler2.xyzw, s14 +sample r3.xyzw, r0.yzyy, WaterBumpSampler.xyzw, s10 +sample r4.xyzw, r1.xyxx, WaterBumpSampler2.xyzw, s14 +sample r1.xyzw, r1.xyxx, WaterBumpSampler.xyzw, s10 +mov r3.zw, r1.xxxy +mov r2.zw, r4.xxxy +add r1.xyzw, r2.xyzw, r3.xyzw +add r2.xyzw, r3.xyzw, l(0.500000, 0.500000, 0.500000, 0.500000) +add r1.xyzw, r1.xyzw, -r2.xyzw +mad r0.xyzw, r0.xxxx, r1.xyzw, r2.xyzw +mad r0.xyzw, r0.xyzw, l(2.000000, 2.000000, 2.000000, 2.000000), l(-2.000000, -2.000000, -2.000000, -2.000000) +mul r0.xyzw, r0.xyzw, gFlowParams.zzww +add r0.xy, r0.zwzz, r0.xyxx +mul r0.zw, r0.xxxy, RippleBumpiness +dp2 r0.x, r0.xyxx, r0.xyxx +sqrt r0.x, r0.x +mad r0.x, r0.x, l(0.270000), l(0.440000) +mad r1.xy, r0.zwzz, v2.wwww, v4.xyxx +mov r1.z, v4.z +dp3 r0.y, r1.xyzx, r1.xyzx +rsq r0.y, r0.y +mad r2.xyz, -r1.xyzx, r0.yyyy, l(0.000000, 0.000000, 1.000000, 0.000000) +mul r0.yzw, r0.yyyy, r1.xxyz +mad r1.xyz, r2.xyzx, l(0.833333, 0.833333, 0.833333, 0.000000), r0.yzwy +add r2.xyz, v2.xyzx, -gViewInverse[3].xyzx +dp3 r1.w, r2.xyzx, r2.xyzx +rsq r1.w, r1.w +mul r3.xyz, r1.wwww, r2.xyzx +dp3 r2.w, r3.xyzx, r1.xyzx +add r2.w, r2.w, r2.w +mad r1.xyz, r1.xyzx, -r2.wwww, r3.xyzx +dp3 r2.w, -r3.xyzx, r0.yzwy +mad r1.z, -r2.z, r1.w, -r1.z +mad r1.z, -r2.z, r1.w, |r1.z| +mul r3.xyz, r1.yyyy, gReflectionWorldViewProj[1].xwyx +mad r3.xyz, r1.xxxx, gReflectionWorldViewProj[0].xwyx, r3.xyzx +mad r1.xyz, r1.zzzz, gReflectionWorldViewProj[2].xwyx, r3.xyzx +mul r3.xyz, r1.xyzx, l(0.500000, 0.500000, 0.500000, 0.000000) +mad r4.y, r1.y, l(0.500000), -r3.z +add r4.x, r3.y, r3.x +div r1.xy, r4.xyxx, r1.yyyy +sample r3.xyzw, r1.xyxx, PlanarReflectionSampler.xyzw, s7 +sample r4.xyzw, v1.zwzz, WetSampler.xyzw, s9 +mul r1.x, r4.x, l(0.650000) +add r1.y, -v4.w, l(512.000000) +mul_sat r1.y, r1.y, l(0.001953) +mul r1.x, r1.y, r1.x +sample r4.xyzw, v3.zwzz, StaticFoamSampler.xyzw, s4 +mul r1.y, r4.y, l(0.350000) +mad r4.x, r1.y, r0.x, r1.x +mov r4.yw, l(0,0.500000,0,0.500000) +sample r5.xyzw, r4.xyxx, BlendSampler.xyzw, s6 +mov r1.xy, -r0.yzyy +mov r1.z, l(0) +mad r1.xyz, r2.xyzx, r1.wwww, r1.xyzx +mad r2.xyz, r2.xyzx, r1.wwww, gDirectionalLight.xyzx +div r6.xy, v1.xyxx, v4.wwww +sample r7.xyzw, r6.xyxx, LightingSampler.xyzw, s15 +mad r1.xyz, r1.xyzx, r7.yyyy, v2.xyzx +mov r6.z, r7.y +mul r5.xzw, r1.yyyy, gRefractionWorldViewProj[1].xxwy +mad r1.xyw, r1.xxxx, gRefractionWorldViewProj[0].xwxy, r5.xzxw +mad r1.xyz, r1.zzzz, gRefractionWorldViewProj[2].xwyx, r1.xywx +add r1.xyz, r1.xyzx, gRefractionWorldViewProj[3].xwyx +mul r1.xzw, r1.xxyz, l(0.500000, 0.000000, 0.500000, 0.500000) +mad r4.y, r1.y, l(0.500000), -r1.w +add r4.x, r1.z, r1.x +div r1.xy, r4.xyxx, r1.yyyy +sample r7.xyzw, r1.xyxx, LightingSampler.xyzw, s15 +ne r0.x, l(0.000000, 0.000000, 0.000000, 0.000000), r7.z +mov r1.z, r7.y +movc r1.xyz, r0.xxxx, r6.xyzx, r1.xyzx +mul r0.x, r1.z, r5.y +sample r5.xyzw, r1.xyxx, RefractionSampler.xyzw, s12 +dp3 r1.x, r0.yzwy, -gDirectionalLight.xyzx +mad_sat r1.x, r1.x, l(0.700000), l(0.300000) +mul r1.xyw, r1.xxxx, gWaterDirectionalColor.xyxz +mad r1.xyw, r1.xyxw, r7.wwww, gWaterAmbientColor.xyxz +mad r1.xyw, r1.xyxw, r0.xxxx, r5.xyxz +add r3.xyz, -r1.xywx, r3.xyzx +add r0.x, -r2.w, l(1.000000) +mad r4.z, r0.x, l(0.300000), r2.w +sample r4.xyzw, r4.zwzz, BlendSampler.xyzw, s6 +mad r3.xyz, r4.xxxx, r3.xyzx, r1.xywx +dp3 r0.x, r2.xyzx, r2.xyzx +rsq r0.x, r0.x +mul r2.xyz, r0.xxxx, r2.xyzx +dp3_sat r0.x, -r2.xyzx, r0.yzwy +log r0.x, r0.x +mul r0.x, r0.x, SpecularFalloff +exp r0.x, r0.x +mul r0.x, r0.x, SpecularIntensity +mul r0.x, r7.w, r0.x +mad r0.xyz, gWaterDirectionalColor.xyzx, r0.xxxx, r3.xyzx +add r0.xyz, -r1.xywx, r0.xyzx +mad r0.xyz, r1.zzzz, r0.xyzx, r1.xywx +mul o0.xyz, r0.xyzx, globalScalars3.zzzz +mov o0.w, l(0) +ret +// Approximately 108 instruction slots used + + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer rage_matrices +// { +// +// row_major float4x4 gWorld; // Offset: 0 Size: 64 [unused] +// row_major float4x4 gWorldView; // Offset: 64 Size: 64 [unused] +// row_major float4x4 gWorldViewProj; // Offset: 128 Size: 64 [unused] +// row_major float4x4 gViewInverse; // Offset: 192 Size: 64 +// +// } +// +// cbuffer misc_globals +// { +// +// float4 globalFade; // Offset: 0 Size: 16 [unused] +// float globalHeightScale; // Offset: 16 Size: 4 [unused] +// float4 g_Rage_Tessellation_CameraPosition;// Offset: 32 Size: 16 [unused] +// float4 g_Rage_Tessellation_CameraZAxis;// Offset: 48 Size: 16 [unused] +// float4 g_Rage_Tessellation_ScreenSpaceErrorParams;// Offset: 64 Size: 16 [unused] +// float4 g_Rage_Tessellation_LinearScale;// Offset: 80 Size: 16 [unused] +// float4 g_Rage_Tessellation_Frustum[4];// Offset: 96 Size: 64 [unused] +// float4 g_Rage_Tessellation_Epsilons;// Offset: 160 Size: 16 [unused] +// float4 globalScalars; // Offset: 176 Size: 16 [unused] +// float4 globalScalars2; // Offset: 192 Size: 16 [unused] +// float4 globalScalars3; // Offset: 208 Size: 16 +// float4 globalScreenSize; // Offset: 224 Size: 16 [unused] +// uint4 gTargetAAParams; // Offset: 240 Size: 16 [unused] +// float4 colorize; // Offset: 256 Size: 16 [unused] +// float4 gGlobalParticleShadowBias; // Offset: 272 Size: 16 [unused] +// float gGlobalParticleDofAlphaScale;// Offset: 288 Size: 4 [unused] +// float gGlobalFogIntensity; // Offset: 292 Size: 4 [unused] +// float4 gPlayerLFootPos; // Offset: 304 Size: 16 [unused] +// float4 gPlayerRFootPos; // Offset: 320 Size: 16 [unused] +// +// } +// +// cbuffer lighting_globals +// { +// +// float4 gDirectionalLight; // Offset: 0 Size: 16 +// float4 gDirectionalColour; // Offset: 16 Size: 16 [unused] +// int gNumForwardLights; // Offset: 32 Size: 4 [unused] +// float4 gLightPositionAndInvDistSqr[8];// Offset: 48 Size: 128 [unused] +// float4 gLightDirectionAndFalloffExponent[8];// Offset: 176 Size: 128 [unused] +// float4 gLightColourAndCapsuleExtent[8];// Offset: 304 Size: 128 [unused] +// float gLightConeScale[8]; // Offset: 432 Size: 116 [unused] +// float gLightConeOffset[8]; // Offset: 560 Size: 116 [unused] +// float4 gLightNaturalAmbient0; // Offset: 688 Size: 16 [unused] +// float4 gLightNaturalAmbient1; // Offset: 704 Size: 16 [unused] +// float4 gLightArtificialIntAmbient0;// Offset: 720 Size: 16 [unused] +// float4 gLightArtificialIntAmbient1;// Offset: 736 Size: 16 [unused] +// float4 gLightArtificialExtAmbient0;// Offset: 752 Size: 16 [unused] +// float4 gLightArtificialExtAmbient1;// Offset: 768 Size: 16 [unused] +// float4 gDirectionalAmbientColour; // Offset: 784 Size: 16 [unused] +// float4 globalFogParams[5]; // Offset: 800 Size: 80 [unused] +// float4 globalFogColor; // Offset: 880 Size: 16 [unused] +// float4 globalFogColorE; // Offset: 896 Size: 16 [unused] +// float4 globalFogColorN; // Offset: 912 Size: 16 [unused] +// float4 globalFogColorMoon; // Offset: 928 Size: 16 [unused] +// float4 gReflectionTweaks; // Offset: 944 Size: 16 [unused] +// +// } +// +// cbuffer water_globals +// { +// +// float2 gWorldBaseVS; // Offset: 0 Size: 8 [unused] +// float4 gFlowParams; // Offset: 16 Size: 16 +// float4 gFlowParams2; // Offset: 32 Size: 16 [unused] +// float4 gWaterAmbientColor; // Offset: 48 Size: 16 +// float4 gWaterDirectionalColor; // Offset: 64 Size: 16 +// float4 gScaledTime; // Offset: 80 Size: 16 [unused] +// float4 gOceanParams0; // Offset: 96 Size: 16 [unused] +// float4 gOceanParams1; // Offset: 112 Size: 16 [unused] +// row_major float4x4 gReflectionWorldViewProj;// Offset: 128 Size: 64 +// float4 gFogLight_Debugging; // Offset: 192 Size: 16 [unused] +// row_major float4x4 gRefractionWorldViewProj;// Offset: 208 Size: 64 +// +// } +// +// cbuffer water_common_locals +// { +// +// float RippleBumpiness; // Offset: 0 Size: 4 +// float RippleSpeed; // Offset: 4 Size: 4 +// float RippleScale; // Offset: 8 Size: 4 +// float SpecularIntensity; // Offset: 12 Size: 4 +// float SpecularFalloff; // Offset: 16 Size: 4 +// float ParallaxIntensity; // Offset: 20 Size: 4 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// StaticFoamSampler sampler NA NA s4 1 +// BlendSampler sampler NA NA s6 1 +// PlanarReflectionSampler sampler NA NA s7 1 +// WetSampler sampler NA NA s9 1 +// WaterBumpSampler sampler NA NA s10 1 +// RefractionSampler sampler NA NA s12 1 +// WaterBumpSampler2 sampler NA NA s14 1 +// LightingSampler sampler NA NA s15 1 +// StaticFoamSampler texture float4 2d t4 1 +// BlendSampler texture float4 2d t6 1 +// PlanarReflectionSampler texture float4 2d t7 1 +// WetSampler texture float4 2d t9 1 +// WaterBumpSampler texture float4 2d t10 1 +// RefractionSampler texture float4 2d t12 1 +// WaterBumpSampler2 texture float4 2d t14 1 +// LightingSampler texture float4 2d t15 1 +// rage_matrices cbuffer NA NA cb1 1 +// misc_globals cbuffer NA NA cb2 1 +// lighting_globals cbuffer NA NA cb3 1 +// water_globals cbuffer NA NA cb4 1 +// water_common_locals cbuffer NA NA cb10 1 +// +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_4_0 +dcl_constantbuffer CB1[16], immediateIndexed +dcl_constantbuffer CB2[14], immediateIndexed +dcl_constantbuffer CB3[1], immediateIndexed +dcl_constantbuffer CB4[17], immediateIndexed +dcl_constantbuffer CB10[2], immediateIndexed +dcl_sampler s4, mode_default +dcl_sampler s6, mode_default +dcl_sampler s7, mode_default +dcl_sampler s9, mode_default +dcl_sampler s10, mode_default +dcl_sampler s12, mode_default +dcl_sampler s14, mode_default +dcl_sampler s15, mode_default +dcl_resource_texture2d (float,float,float,float) t4 +dcl_resource_texture2d (float,float,float,float) t6 +dcl_resource_texture2d (float,float,float,float) t7 +dcl_resource_texture2d (float,float,float,float) t9 +dcl_resource_texture2d (float,float,float,float) t10 +dcl_resource_texture2d (float,float,float,float) t12 +dcl_resource_texture2d (float,float,float,float) t14 +dcl_resource_texture2d (float,float,float,float) t15 +dcl_input_ps linear v1.xyzw +dcl_input_ps linear v2.xyzw +dcl_input_ps linear v3.zw +dcl_input_ps linear v4.xyzw +dcl_input_ps linear v5.zw +dcl_output o0.xyzw +dcl_temps 8 + + +*/ diff --git a/Shaders/WaterVS.hlsli b/Shaders/WaterVS.hlsli new file mode 100644 index 0000000..90b85a6 --- /dev/null +++ b/Shaders/WaterVS.hlsli @@ -0,0 +1,474 @@ +#include "Quaternion.hlsli" +#include "Shadowmap.hlsli" + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4 WaterVector; + float ScaledTime; + float ScnPad0; + float ScnPad1; + float ScnPad2; +} +cbuffer VSEntityVars : register(b2) +{ + float4 CamRel; + float4 Orientation; + float3 Scale; + uint EntPad0; +} +cbuffer VSGeomVars : register(b3) +{ + float4 WaterParams; + uint EnableFlow; + uint ShaderMode; + uint GeoPad1; + uint GeoPad2; + float RippleSpeed; + float GeoPad3; + float GeoPad4; + float GeoPad5; +} + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float4 Flow : TEXCOORD1; + float4 Shadows : TEXCOORD3; + float4 LightShadow : TEXCOORD4; + float4 Colour0 : COLOR0; + float4 Tangent : TEXCOORD5; + float4 Bitangent : TEXCOORD6; + float3 CamRelPos : TEXCOORD7; +}; + +Texture2D FlowSampler : register(t0); +SamplerState TextureSS : register(s0); + + + +float3 ModelTransform(float3 ipos) +{ + float3 tpos = ipos; + float3 spos = tpos * Scale; + float3 bpos = mulvq(spos, Orientation); + return CamRel.xyz + bpos; +} +float4 ScreenTransform(float3 opos) +{ + float4 pos = float4(opos, 1); + float4 cpos = mul(pos, ViewProj); + cpos.z = DepthFunc(cpos.zw); + return cpos; +} +float3 NormalTransform(float3 inorm) +{ + float3 tnorm = inorm; + float3 bnorm = normalize(mulvq(tnorm, Orientation)); + return bnorm; +} + + + + + + + +float2 GetWaterTexcoords(float2 tc) +{ + if (ShaderMode == 1) + { + return tc + float2(ScaledTime * RippleSpeed, 0); + } + else + { + return tc; + } +} + + +float4 GetWaterFlow(float2 tc, float4 vc) +{ + float4 f = float4(vc.g, 0, 0.02, 0.03); + if (EnableFlow) + { + float4 fv = FlowSampler.SampleLevel(TextureSS, tc, 0); + f.zw = fv.xy * 2 - 1; + f.x = vc.g; + f.y = 0; + //sample_l r0.xyzw, v2.xyxx, t2.xyzw, s2, l(0.000000) + //mad o5.zw, r0.xxxy, l(0.000000, 0.000000, 2.000000, 2.000000), l(0.000000, 0.000000, -1.000000, -1.000000) + //mov o5.x, v1.y + //mov o5.y, l(0) + } + return f; +} + + + + + + + + + +/* +water_terrainfoam.fxc_VSFoam + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer rage_matrices +// { +// +// row_major float4x4 gWorld; // Offset: 0 Size: 64 +// row_major float4x4 gWorldView; // Offset: 64 Size: 64 [unused] +// row_major float4x4 gWorldViewProj; // Offset: 128 Size: 64 +// row_major float4x4 gViewInverse; // Offset: 192 Size: 64 [unused] +// +// } +// +// cbuffer water_globals +// { +// +// float2 gWorldBaseVS; // Offset: 0 Size: 8 +// float4 gFlowParams; // Offset: 16 Size: 16 [unused] +// float4 gFlowParams2; // Offset: 32 Size: 16 [unused] +// float4 gWaterAmbientColor; // Offset: 48 Size: 16 [unused] +// float4 gWaterDirectionalColor; // Offset: 64 Size: 16 [unused] +// float4 gScaledTime; // Offset: 80 Size: 16 [unused] +// float4 gOceanParams0; // Offset: 96 Size: 16 [unused] +// float4 gOceanParams1; // Offset: 112 Size: 16 [unused] +// row_major float4x4 gReflectionWorldViewProj;// Offset: 128 Size: 64 [unused] +// float4 gFogLight_Debugging; // Offset: 192 Size: 16 [unused] +// row_major float4x4 gRefractionWorldViewProj;// Offset: 208 Size: 64 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// rage_matrices cbuffer NA NA cb1 1 +// water_globals cbuffer NA NA cb4 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyz 0 NONE float xyz +// NORMAL 0 xyz 1 NONE float xyz +// TANGENT 0 xyz 2 NONE float xyz +// TEXCOORD 0 xy 3 NONE float xy +// COLOR 0 xyzw 4 NONE float w +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xyzw +// TEXCOORD 0 xyzw 1 NONE float xyzw +// TEXCOORD 1 xyz 2 NONE float xyz +// TEXCOORD 2 xyz 3 NONE float xyz +// TEXCOORD 3 xyz 4 NONE float xyz +// TEXCOORD 4 xyzw 5 NONE float xyzw +// +vs_4_0 +dcl_constantbuffer CB1[12], immediateIndexed +dcl_constantbuffer CB4[1], immediateIndexed +dcl_input v0.xyz +dcl_input v1.xyz +dcl_input v2.xyz +dcl_input v3.xy +dcl_input v4.w +dcl_output_siv o0.xyzw, position +dcl_output o1.xyzw +dcl_output o2.xyz +dcl_output o3.xyz +dcl_output o4.xyz +dcl_output o5.xyzw +dcl_temps 1 +mul r0.xyzw, v0.yyyy, cb1[9].xyzw +mad r0.xyzw, v0.xxxx, cb1[8].xyzw, r0.xyzw +mad r0.xyzw, v0.zzzz, cb1[10].xyzw, r0.xyzw +add o0.xyzw, r0.xyzw, cb1[11].xyzw +mul r0.xyz, v0.yyyy, cb1[1].xyzx +mad r0.xyz, v0.xxxx, cb1[0].xyzx, r0.xyzx +mad r0.xyz, v0.zzzz, cb1[2].xyzx, r0.xyzx +add r0.xyz, r0.xyzx, cb1[3].xyzx +mov o1.xyz, r0.xyzx +add r0.xy, r0.xyxx, -cb4[0].xyxx +mul o5.zw, r0.xxxy, l(0.000000, 0.000000, 0.001953, 0.001953) +mov o1.w, v4.w +mov o2.xyz, v1.xyzx +mov o3.xyz, v2.xyzx +mul r0.xyz, v1.zxyz, v2.yzxy +mad r0.xyz, v1.yzxy, v2.zxyz, -r0.xyzx +dp3 r0.w, r0.xyzx, r0.xyzx +rsq r0.w, r0.w +mul o4.xyz, r0.wwww, r0.xyzx +mov o5.xy, v3.xyxx +ret +// Approximately 21 instruction slots used + + +*/ + + + + + + + +/* +water_riverfoam.fxc_VS + + +vs_4_0 +dcl_constantbuffer CB1[12], immediateIndexed +dcl_constantbuffer CB2[13], immediateIndexed +dcl_constantbuffer CB3[47], immediateIndexed +dcl_constantbuffer CB4[6], immediateIndexed +dcl_constantbuffer CB10[1], immediateIndexed +dcl_input v0.xyz +dcl_input v1.y +dcl_input v2.xy +dcl_input v3.xyz +dcl_output_siv o0.xyzw, position +dcl_output o1.xyzw +dcl_output o2.xyzw +dcl_output o3.xy +dcl_output o4.xyz +dcl_output o5.xyz +dcl_temps 2 +mul r0.xyzw, v0.yyyy, gWorldViewProj[1].xyzw +mad r0.xyzw, v0.xxxx, gWorldViewProj[0].xyzw, r0.xyzw +mad r0.xyzw, v0.zzzz, gWorldViewProj[2].xyzw, r0.xyzw +add r0.xyzw, r0.xyzw, gWorldViewProj[3].xyzw +mul r1.xyzw, r0.xyzw, l(1.000000, 1.000000, 0.999995, 1.000000) +mov o0.xyzw, r1.xyzw +mov o2.zw, r1.wwww +add o1.xyz, v0.xyzx, gWorld[3].xyzx +mov o1.w, v1.y +mul r0.xyz, r0.xwyx, l(0.500000, 0.500000, 0.500000, 0.000000) +mad o2.y, r0.w, l(0.500000), -r0.z +add o2.x, r0.y, r0.x + +mul r0.x, gScaledTime.x, RippleSpeed +mov r0.y, l(0) +add o3.xy, r0.xyxx, v2.xyxx ///TEXCOORD OUT + +add r0.x, v3.z, gLightNaturalAmbient0.w +mul r0.x, r0.x, gLightNaturalAmbient1.w +max r0.x, r0.x, l(0.000000) +mad r0.yzw, gLightArtificialIntAmbient0.xxyz, r0.xxxx, gLightArtificialIntAmbient1.xxyz +mad r1.xyz, gLightNaturalAmbient0.xyzx, r0.xxxx, gLightNaturalAmbient1.xyzx +mad o4.xyz, r0.yzwy, globalScalars2.zzzz, r1.xyzx +dp3_sat r0.x, v3.xyzx, -gDirectionalLight.xyzx +mul o5.xyz, r0.xxxx, gDirectionalColour.xyzx + +ret +// Approximately 24 instruction slots used + + +// +// cbuffer water_globals +// { +// +// float2 gWorldBaseVS; // Offset: 0 Size: 8 [unused] +// float4 gFlowParams; // Offset: 16 Size: 16 [unused] +// float4 gFlowParams2; // Offset: 32 Size: 16 [unused] +// float4 gWaterAmbientColor; // Offset: 48 Size: 16 [unused] +// float4 gWaterDirectionalColor; // Offset: 64 Size: 16 [unused] +// float4 gScaledTime; // Offset: 80 Size: 16 +// float4 gOceanParams0; // Offset: 96 Size: 16 [unused] +// float4 gOceanParams1; // Offset: 112 Size: 16 [unused] +// row_major float4x4 gReflectionWorldViewProj;// Offset: 128 Size: 64 [unused] +// float4 gFogLight_Debugging; // Offset: 192 Size: 16 [unused] +// row_major float4x4 gRefractionWorldViewProj;// Offset: 208 Size: 64 [unused] +// +// } +// +// cbuffer water_common_locals +// { +// +// float RippleBumpiness; // Offset: 0 Size: 4 [unused] +// float RippleSpeed; // Offset: 4 Size: 4 +// float RippleScale; // Offset: 8 Size: 4 [unused] +// float SpecularIntensity; // Offset: 12 Size: 4 [unused] +// float SpecularFalloff; // Offset: 16 Size: 4 [unused] +// float ParallaxIntensity; // Offset: 20 Size: 4 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// rage_matrices cbuffer NA NA cb1 1 +// misc_globals cbuffer NA NA cb2 1 +// lighting_globals cbuffer NA NA cb3 1 +// water_globals cbuffer NA NA cb4 1 +// water_common_locals cbuffer NA NA cb10 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyz 0 NONE float xyz +// COLOR 0 xyzw 1 NONE float y +// TEXCOORD 0 xy 2 NONE float xy +// NORMAL 0 xyz 3 NONE float xyz +// TANGENT 0 xyz 4 NONE float +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xyzw +// TEXCOORD 0 xyzw 1 NONE float xyzw +// TEXCOORD 1 xyzw 2 NONE float xyzw +// TEXCOORD 2 xy 3 NONE float xy +// TEXCOORD 3 xyz 4 NONE float xyz +// TEXCOORD 4 xyz 5 NONE float xyz +// + + + +*/ + + + + + + +/* +water_river.fxc_VS + + +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 +// +// +// Buffer Definitions: +// +// cbuffer rage_matrices +// { +// +// row_major float4x4 gWorld; // Offset: 0 Size: 64 +// row_major float4x4 gWorldView; // Offset: 64 Size: 64 [unused] +// row_major float4x4 gWorldViewProj; // Offset: 128 Size: 64 +// row_major float4x4 gViewInverse; // Offset: 192 Size: 64 [unused] +// +// } +// +// cbuffer water_globals +// { +// +// float2 gWorldBaseVS; // Offset: 0 Size: 8 +// float4 gFlowParams; // Offset: 16 Size: 16 [unused] +// float4 gFlowParams2; // Offset: 32 Size: 16 [unused] +// float4 gWaterAmbientColor; // Offset: 48 Size: 16 +// float4 gWaterDirectionalColor; // Offset: 64 Size: 16 [unused] +// float4 gScaledTime; // Offset: 80 Size: 16 [unused] +// float4 gOceanParams0; // Offset: 96 Size: 16 [unused] +// float4 gOceanParams1; // Offset: 112 Size: 16 [unused] +// row_major float4x4 gReflectionWorldViewProj;// Offset: 128 Size: 64 [unused] +// float4 gFogLight_Debugging; // Offset: 192 Size: 16 [unused] +// row_major float4x4 gRefractionWorldViewProj;// Offset: 208 Size: 64 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// FlowSampler sampler NA NA s2 1 +// FlowSampler texture float4 2d t2 1 +// rage_matrices cbuffer NA NA cb1 1 +// water_globals cbuffer NA NA cb4 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyz 0 NONE float xyz +// COLOR 0 xyzw 1 NONE float xy +// TEXCOORD 0 xy 2 NONE float xy +// NORMAL 0 xyz 3 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xyzw +// TEXCOORD 0 xyzw 1 NONE float xyzw +// TEXCOORD 1 xyzw 2 NONE float xyzw +// TEXCOORD 2 xyzw 3 NONE float xyzw +// TEXCOORD 3 xyzw 4 NONE float xyzw +// TEXCOORD 4 xyzw 5 NONE float xyzw +// +vs_4_0 +dcl_constantbuffer CB1[12], immediateIndexed +dcl_constantbuffer CB4[4], immediateIndexed +dcl_sampler s2, mode_default +dcl_resource_texture2d (float,float,float,float) t2 +dcl_input v0.xyz +dcl_input v1.xy +dcl_input v2.xy +dcl_input v3.xyz +dcl_output_siv o0.xyzw, position +dcl_output o1.xyzw +dcl_output o2.xyzw +dcl_output o3.xyzw +dcl_output o4.xyzw +dcl_output o5.xyzw +dcl_temps 2 +mul r0.xyzw, v0.yyyy, cb1[9].xyzw +mad r0.xyzw, v0.xxxx, cb1[8].xyzw, r0.xyzw +mad r0.xyzw, v0.zzzz, cb1[10].xyzw, r0.xyzw +add r0.xyzw, r0.xyzw, cb1[11].xyzw +mov o0.xyzw, r0.xyzw +mul r0.xyz, r0.xwyx, l(0.500000, 0.500000, 0.500000, 0.000000) +mad o1.y, r0.w, l(0.500000), -r0.z +add o1.x, r0.y, r0.x +mov o4.w, r0.w +add r0.xyz, v0.xyzx, cb1[3].xyzx +add r1.xy, r0.xyxx, -cb4[0].xyxx +mad o1.zw, r1.xxxy, l(0.000000, 0.000000, 0.001953, 0.001953), l(0.000000, 0.000000, 0.001953, 0.001953) +mov o2.xyz, r0.xyzx +mul o3.zw, r0.xxxy, cb4[3].wwww +mov o2.w, v1.x +mov o3.xy, v2.xyxx +dp3 r0.x, v3.xyzx, v3.xyzx +rsq r0.x, r0.x +mul o4.xyz, r0.xxxx, v3.xyzx +sample_l r0.xyzw, v2.xyxx, t2.xyzw, s2, l(0.000000) +mad o5.zw, r0.xxxy, l(0.000000, 0.000000, 2.000000, 2.000000), l(0.000000, 0.000000, -1.000000, -1.000000) +mov o5.x, v1.y +mov o5.y, l(0) +ret +// Approximately 24 instruction slots used + + + +*/ + + diff --git a/Shaders/WaterVS_PCT.cso b/Shaders/WaterVS_PCT.cso new file mode 100644 index 0000000000000000000000000000000000000000..e9aecdd397cbea003b829ca4fd2aa6977186a2b5 GIT binary patch literal 4596 zcmaJ_O=w(I6uzBInxsultd+)6bSNd(A|;*Hw3gDoPLgR0lgu!0Iz|!N*UW1&W&U{c zVqy^qAwqT0s*8dsA}CUbi-Im(6qM413m5L(bR|**brZC@kk;?J@1B{L;WY>Dob$f( zbI(2Jy!%MTr&D8>s~-(Kzw@`$2cOL5djDLxwMi-U*ON+hgCEAa+XLRK)O4Rxi@@{a z6X~nK;?V7d@n-PdSStSTk-~Ekx_fx+BGy5S&2=9uhQ&P?=Me}@>$ZWf@gai5|KSEY z+Vu0MgSemgKNF#6zM?OI=40ZB$%O6>WRQt+_?VYbtxrDb*LMPD4Kx z?TMOS_TMxQr`>v0i_G&WtQ7?QDO3=ik9E6^!(RXwV&1IB3JNnKAUN|y`PDu+h4GAu zIS3ukH*KEhz=>G~Uo`kt@LUA`A@KKs(}yH+J_i070Tu@Im5FnkI5C6&Xz+W)rO;6S zVetQmWASXHek1G#{~`k45Bz2XegrskFz&55DFC-Zc)=Kyz`u#W=YfA4fnNd6vl(|K zajpUQJ_7#~_}vKnCh#93@UMZhR$!VW{+LtMqm`>SQPM6fu~15M#j?AgR##WMppS?2 zneyzMua#OFFMDul&NwAEd+Acs^_y^#n9^TkV9z)ecLV*n+wkW$(2v#UYd&-0^lg%1 zz{yPfV!1i*R8(#(ovGIww(oepJWSL|DpmJNu9tI4rE+a{vRqS$!?T;ALY(y$&Z0_{ zou*1v=Dn2bFSu^aY}Aw;bw+1vZz#OMZpAKNaof_g!dA%<=9}Tg1G2C3Q(%mT)%2gL) z4Y`jPe$eow`W5j=%$IpdzP|$})`|ZEJOR8Pi}v~w0vp7=@*=oQ-4HJ)5N0p$R#et2 zyEWhO%k^526>AvG6o%OlZa|$QZ@h316}|@~=0cJj`+*aan#!I#f$xaG_W&OC8O|JYn!~&rSf}8?u*Prh)H^z^8zRYa{l$RXN9Vs!cUfb1qg~ek=5c!SyEV zC0F4yfQlS6JgM^K2EHS9!*xprJ7oA_!(UR9X&&SdONf}a}KON`a4 zjWRw%iO~ax4!k@%GIHSH=%J&B)mi)W)Ex3=C-9lpa|)(Ox-)m)MkN15??);U}?jBym>;;A5q8#@eNN$7pKH;~?C(HorkrDK7u_!E0D z5Mb%$z@HeXhw;TH%;DQd9rp?QeEDA69})Xx|FBJ1PU7kmn`29D-*vJYTso!GQ402Y zU*;k?5BHheaW3L=F4kPmI{a=sHezgT)h$$)8}U{gy&wH07Q|Mp2iMod>X%ruSInZd z;;$_2%iKV^XOzWW>OtiwUOU!<`b`#*rIYv*p?7=2X#p*XAMAl4k$2Z-E+g)KRLhjBWBT3Xz3&+IVYX0e!z9U;hsUirBffX;27!`AJB{5JH|g|5ebvte_dUumHMDt zJu=sFcH!fu$Fx6&_$1`iiY0Xvd#LryNZs}9EC+WVePuqnA*V4P+RogK#AH6A^t^Lq zKBDxzhh#pY^t_v7f8I%*`*VI0oG)|ET}ugl7xE08Z*rWyZ@a1U7U)Ubi!%Lr9=;cQ zj1Bz^^>p?zZSLwLh$(k)tDeSRY&Zv=!Q|bKSrWQEUzo#fynA_8xog^Xv=402FMV$? z-{(|3F8T9}XE66`9s8%>4tg)&AvqWJ8|XY&%tDZk`HWeFmc9!XWu>;Gq?}vvk6Ae6 z&z~Q^e&_Gw)RUeLY`Rk>pIzpgCU+0>mt2Ug;q2_gecX?x7rnm#W4~h-emY2eI9usw z+dhoLd5T&1S@-@foz#0n&l-pKX5Cpoc^7C$jNd_G)SZBfT{ue9(E6uwMb+CrhVU<4#OA*4ZKNExsoAu!Ce15Ku#X5KJXV*=04D}6ehH@r1#ZB&U}IuTbU{)VMon}>KYreRG{s>fRGdb$}nlxYemtsY|JaZlx{& zFAk67E(2?aY&VqGgYU#p?GGL*tjmzy#?1g!!>0L_UIQg-JgXTz=!lg5-?aSGGZ4JT;8NPNoq8U<_0t~zVThn;#bvxYqD&D8?N#O_-s z&4A2||FYYdv#V+%o6CD%-3n|!ki|%?qB5Rear_CpQgLhN#@w2MALeeF3Vv2=*b6G- z+6|Sd&iNT9n0K6-*{C5q>WD^bZz6D)5rQ!J2pgd@=^V0Q}V$oX0oed#|gP?7;EM&Q##}N}o=p~mxFsQE|A+SEYE6;;V*KOnD1VZl>ovJGM zu2T!_!1ZcjRIFjxQ)p&GcmZ{ceDR`ZsPH`?F&2`<*aMuH)KvC-3i#F-d>8O-1_x83 zzZW>aKdrH+fF}(eJ+ouLcSrQ)EOWs3#Ngw=qqPxzeN+>+Z_hT=NX>q&>hN2kKMamP z=2aYp&j2d2-|&KO(#T}CP$&+oY$0DLs-*(r*$L+xpwD>j89&^w z84u>|1PnFffx*TWT*rfkB`zZB>v+J4i(hi~0m9U{^aOEU72;dP3FgGv>Y{J1lg3e+ zCT^~S#+j4oQ-?%9{62R=XqC_WUx}8iQ^UpkFis<*hluB8gq^#R)cMhmtTEN`$y(PU zBImvwuaKP$Z`kBEl%O8YPoGxm3}k*^xRyCfz-Z{+;o4TiFD3Q9+#5*OMUfkv z@#PYsuGka1+Z$rJi=jO+P$&J1O_W2sTYN`tqVp7lA5;OCYJOC5#e679dNAE{_@x|@M*WIhDeD#PgktfpBR{WKr zZ5bO#p9klnFZG~s2-l1CpnP4L$l`JQsnFG*G_h?qwMLH%QNHUja{8e>^B6gEr2OJz z0&2Q9 zxF>z+8sn~!lcYB&Z|#i^U^(=Lwl(h`G3kvsIo}fLjW{{q7wL^SIo}-0*_(W?TK8w~ zB-vXg_Z^E#{l+mL#!rrVbhEb@_XfyG+>3MC6KCGLj82$0K-4j1u$*x71|NdYRMMQS zyjd+e*mnc(E&a>;kw{~q)bYsRd$WmeDsx>+53=T)@vLfZm-w0EDZDq!E&J!*3Gb79 zYa}o1*V~#`A`K@>@s~qWB2BjVT{t*bsvjjqt-8cMkw%igeR}lj&3}$kPI@xb>ByLP zc9?I~qrDZ@eHpp)9PZ$4G-uKE2QZ#@B8{IGq959@w{p*fwv34w`zeve&#D?P9@l$A z&KgS{h_UXhpWG+G_SM)@}|DCjAB8&3> E0KehE3;+NC literal 0 HcmV?d00001 diff --git a/Shaders/WaterVS_PNCT.hlsl b/Shaders/WaterVS_PNCT.hlsl new file mode 100644 index 0000000..be524cc --- /dev/null +++ b/Shaders/WaterVS_PNCT.hlsl @@ -0,0 +1,34 @@ +#include "WaterVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float4 Colour0 : COLOR0; +}; + + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = 0.5;// NormalTransform(float3(1, 0, 0)); //no tangent to use on this vertex type... + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = GetWaterTexcoords(input.Texcoord0); + output.Colour0 = input.Colour0; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + output.Flow = GetWaterFlow(input.Texcoord0, input.Colour0); + return output; +} + diff --git a/Shaders/WaterVS_PNCTX.cso b/Shaders/WaterVS_PNCTX.cso new file mode 100644 index 0000000000000000000000000000000000000000..8bb643c1cf6b13ff4b7596b46e916156d0673745 GIT binary patch literal 5016 zcmai0O=whC6uy}xCedip)KZmD2NAJSLLAd*t=P#VnHZR4hI!*OEd_neJk7{tW_a_` zSdkKf3*D%6AuWaeP!~d^6xxLgp`}RaqKmFtD6UFz)2;%wT@>y2-FMIA<@rnxygB!N z=jWdL-M<-|NsV@&OMfxYNZ+~n^U&5`Kl}dG7Nyh&&nndpJ%sOGhf-cAur8(gf#=7@ z)0cs@!L}F9o1pvgskTRt75YWk?xWjEEF{d$?*YCTK90dWk0DUnwiSAnod}WmM;qAa z)6Jida6F0M8DVF=VlO!7y#?2?ES0X*7AJ)9ap{zN(R9l?4>$+F8 z#;ac0d)IU(oZ7r@vQAK@E+O$x0YW%G@^%-KKMgIyy2-~S5HlzsH0uTZYCnR4c*f-H zg^lx@G5tAcVo8IaH~3}fTm=3;@aw=CLykexJAy4fCG{ z|CcyE&W+M-8vW2WBk%*jZ$;pTfwKk^-prE%@MQom7>5${*Ae&v@H-Ls1>l^U30IQm zDu8bz@Q;Dti@NG43!vUy%}CSkR(2CS2-UiffEy+ z8RXCm;6z~73%xqLadc22!+dyZRlX1$uL^y-uf<#`9q zDrz4z`k>JX^*i!WSTF06dj9}UER6pRJPy1YAN}fVO!l{h;Jn-!i_#WUp3=XBl z{{V2lKjGRFz~crFuGw+mdjtNmmTBPoBk*b9L2krfFICQV?fHfpui9@{9KIF$VQ}23 zTFFs(2EfQcqZ2A$uHzlC>W)(~*de2bjDA^7m1o^rqjtuN@6W#&KasIAaXvMU8y~IB z*UNZ@;===n23{E+92__}eCWuKnzSaSZ=r5(1w7Mg37?3pP7mgAML=lcJY^lguZM7Q z)e46XLpWo4dX)Mkgp+sTxvVu=n9NSA>1=*#B%=!BGo#sTeoT#KGugZCi?4op@~agYF)3v*`^RDf0%~a zE=df|qd=T_=tH4DsB7ZpxM-Yn5`X$o=+F1N14gTO>VK$OS+P!x31m8f} z>8o))Kjx7>n)(P!Uvm+#b6kFJQl0is;LHwCQ1{y>Pbzf^Hn-RBOPdt1odC|9Y_Fot zT+$|YXHnN`+>d39!(8Y~JApRiiPMkq(q_E0+XHQKDLDC)HhE>6`N_c?t}x~}f^Fm~ zzlIyzjlLAu<8o{uoy%f3IO|Ktd|!zt_OQpt(#w84F-QmVOH5G1yGwEhV}k7ju3Par zy0n&eU0d}ojre0J_;<;8QqR6FQx|IH_);_HC-c~MWi2;yY-w^5nDdRcW*$8r<0Th| zms}68t;^Ldxx^kz(p&LYJ{`;2AbLI67JuP`#$g;I@M3^4k@n@M*tsV$a%UfZAyTWZzi&O?v~P;=1FZK5?aeux{Uz&3o2+Nr zbjW%MCVDKe zmPf%0>&Ey`aKU-gMxL9w0%weT1kbXr*~A3b11WTF+GTE{g=dL{i;}$JBiwM!$uq}{ z;#u26Jku9>^tquun2Y&|Me!`P(jH6VCxU1C2+wqodPNJ*w2^0u@VsumX1!t7XOLqu zhu+J}{`3H22bOpNrk9txe{@d7i-Cz8b0_ z{hq%k!(++s;2S=)oU6H8JpedB*@E7b>D!B?lm$C8-LFP|T~_T68{Xs0~q z`?RM_J-f_*geUix&;2UqNG=}W9inFb-+*z=V@dpkgn1al{gr;98Pm?YoO|jh#$zn~ z$R9B|Gr9&~pdk7H2yzYd)0{l-4$u#s?_plm}Y Jj0Nq|{tto>+|d94 literal 0 HcmV?d00001 diff --git a/Shaders/WaterVS_PNCTX.hlsl b/Shaders/WaterVS_PNCTX.hlsl new file mode 100644 index 0000000..4fa48c5 --- /dev/null +++ b/Shaders/WaterVS_PNCTX.hlsl @@ -0,0 +1,34 @@ +#include "WaterVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float4 Colour0 : COLOR0; + float4 Tangent : TANGENT; +}; + + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = NormalTransform(input.Tangent.xyz); + + float4 lightspacepos; + float shadowdepth = ShadowmapSceneDepth(opos, lightspacepos); + output.LightShadow = lightspacepos; + output.Shadows = float4(shadowdepth, 0,0,0); + output.Position = cpos; + output.CamRelPos = opos; + output.Normal = bnorm; + output.Texcoord0 = GetWaterTexcoords(input.Texcoord0); + output.Colour0 = input.Colour0; + output.Tangent = float4(btang, input.Tangent.w); + output.Bitangent = float4(cross(btang, bnorm) * input.Tangent.w, 0); + output.Flow = GetWaterFlow(input.Texcoord0, input.Colour0); + return output; +} \ No newline at end of file diff --git a/Shaders/WaterVS_PT.cso b/Shaders/WaterVS_PT.cso new file mode 100644 index 0000000000000000000000000000000000000000..32f23ace3f3a60932403e8140639618d5683c099 GIT binary patch literal 4092 zcmaJ@Ux-vy7(dRAxvQJInb8_TgM^rft)s0Ln>#zRJGwBtGt3>QEdssmoON%^%pLCB zZA~Hu@j(eRdhnqjf+7Ta2#n}KD8z>z6ng8$rwAeHX+i5jwBPUE^UYqTs~?>CzVrLO z^Zh&L+%r@2+1%~Tf8Nq}_bh(=%K6W(PWHsfK zP3O-6OG5V&jGqGEj-iqd9xBYM(A~zgk5~`UH^&`}1O{W!&qEMcpnDp8m6I5f^$(t) zqs<_HdWi94{k9lA^A&wXpYoSIZCNT`cULUC(W+}tRV`~lH+9wa+R9q8Ywk+JZUwWd zHQn?b{{u5QqTNOyGS6o*&cgApk%q87_U#&qKLIYpyxEVlXw0a9;LI28SG%w%iWiK} zVdz-jyqPb76U!LIdZ)`DHvPtZ^4mcR4_ea>BO`pk)^Z=D@7b)6JU7x?W9tCA(I0nkQ$Srh*^VZVnavJZfQ|Qd!4t zt89JQ%W8i`>!u0RmWV+{GtKuEZm_Of&S||S%`1dTk22o^KRloe29K-Uk7K}zNuT5% z*uYD`xhu4neX9en7#ysN`@rX8@DG8%6N7X6N}l_kdeio`SJex?>#1OOY89uUAvTfw zsNwqzPpd!RkHmbLm*o2waALjqKfqJK2Qg?Le1yP;@m<*iE~jpUA14sbURl>w(Q|au zw|&QLhFP(P;hDl=HiR!=kR!i%(LGdn4@k^~BsmTOCni0Wn9l>>8iVfuK4Ne%CHA|4 z^Zn_~Jq@z&A%1#UKh}F`%X0ZK+A29q?HR~*RZrfe-Q@hG9r;Zk^LW)m~_EI^w(Q@z% zrN;K|-}~Cw=;+>kWBU&sP&3w%xdQTLjd-TjAq*keogvgPDIhp;-m*RjrJ^-cnJLbx z%Jh7$SS(LrbBpk~9R?d=L!bX*kb*U#sPI=nB?%Z3pBu1XQxDGE`f%uoi;DIf^h2C7 ziJW^Wxa=!&9(Uqf#R+8MJg#DIu0(*N>@IGObbzxav8N4*e)z^Rf2(@D+m^Xvd3Lg} z)}36jP%NWI*3qf*IGkos(M9C*7ShgNNCoxLkIW$k`N=%!MMTfI9B-4I2ye;!2wKnz znSGUE}a9pi}1zKXm)BC}6|vo|8MXO!um z^)2DZ(I3uRzo)_+E^RgZY$}M$*g*Qvh~D7LFP{i)Wj(QbLm`$w6Rsx)+CcxZCdy$w zAikq(qH-FaJF$7av*z~^Sq*n4!&nOT0}@a2**ReHLe7jYIkP^gW9Rub-|(@i+mlGm zmy%sSK|HP(Ukoq4?p=Ju*P!?keIi3^#a|i0TIL4o?uXb*Kd2nTHIja;%Mj^IJcBh` zQYN>}hT|*?QNQCcdd8$a`xrfIr2fof^gKhLAZPlD=4|Te=FE9-&g;1bIR|Ua{Uath z$LV>-CFeLj&%NXvr{`Uuo;~9|>W$BuQmk2py?mjQ3htidPmX;b*aAJ}jnI=Ai!#@< zZ``XL#wM&AAnrrjV0q!@dvFjw)2Z;z%h~Ok5`(di;;gRr_{o11<}KeNiH&nT z)EhgIfs@EN7kLvss4$4Yx!PcRkep#Q$pw{2M8ozk`?l|?N=ZwvDlTRW;RH!pS zi9K0GjqK4K+$YvRzrO?HUL-R3=^^U5hWnn#D0S=R%{QV$^xSvqLki=eh6&Mg-xC@9 z0OPL^^&b2)mqZ3XU0TbTdVV+Md>=-wR%No{1LOY-))0+9 zt&&}?Rwzw<+3XB)R|mEM<$;k44T*BV6_ZtPFV}M@bd`wAI-Wopit_S05Ymr)(IH2) zMM#ksJ3@pmr2?J>?gQA<1XS=04)(;1s2(=G2z$zw8&06rfIXmVkUlev#SG?oaQ5zD zjhShH5%sYSdz6T_^0d^lt3Itp^m9>t-=U12UDa%Szq;GlU(P^mX=XF`lS=aXqU==)5 literal 0 HcmV?d00001 diff --git a/Shaders/WidgetPS.hlsl b/Shaders/WidgetPS.hlsl new file mode 100644 index 0000000..ca31ed9 --- /dev/null +++ b/Shaders/WidgetPS.hlsl @@ -0,0 +1,14 @@ + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float4 Colour : COLOR0; + float CullValue : TEXCOORD0; +}; + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + if (input.CullValue < -0.18) discard; + return input.Colour; +} diff --git a/Shaders/WidgetVS.cso b/Shaders/WidgetVS.cso new file mode 100644 index 0000000000000000000000000000000000000000..b2ffd27b8005c65b943b0a4a9cfefa3327956770 GIT binary patch literal 2080 zcmah}&r4KM6h70GP9|nn8wq+u3yTobFq0^C#%YGM8RkusL6p;Y)n}tmW~LuR#2^F} z5iX)#5D^s2KhUy2phb(8Eh<{HmX=a|-@EtfOSBFg&$-|Eedat96C?4{Umt(kaq(-< zr(2!3{pBC65fO1>B2AD3;Cxi%A$S%1tXbqWIF}er?!$W$f1m7XVlA z+yQ2uASWb=I$80t30ZqVRcc;IRmCl-1yv|ks?uOgEBGaN8ElEQ7t^&UYoOwvLPY-w@5Yi-c+q-|?!)<&rlwqiWgWRId=|T?hJ*^BHC$IbfW|SM&UZ zwfgI`y@2mq+C6vSSdd48Ob&FC{SK%{uuivdjVG?|q!W@sOc^*g#Ok~q z61Q%*wi`Nc#}aYciC?!MByqGZk+z^lHshxA>C6R*XT~x)$&XINGnrgM8g6QIVj0du z$nqWjb18{j#)%}KI(Uif1i#|REOIjv?0FLJj&}X#JTrK&IQq?A@O?)4wt5G2_A-l> zC<|C|N3dy;7L%t}WY-#IY)9)3yjfgiFr<%*G+SRv)@d;@_+J(KX7nawYkK6sL+=!I zS}Mk#T+%rHmEm{M{XcKklKrgtZPQrcf%a!VHkP*nYtRq-NE%-&VcU7g^bw8;>*ukL zUh88dQpG~E)rSEvf2XnIXARr6t?s}>?+aSY*0s9}?s`b)If=fOkc(tKKF1J&U!3u_I|0;erO9j>(D;3g`M|G`_dNnDD2#mohQ5}c9guY`@+n->^Je( z%;r1ecVy>3gVEe%x<~&9f&t{_hx0YaPB42S@eXkZ!LIn`EdL@KXMNZ^`G0YL03Tw% Ah5!Hn literal 0 HcmV?d00001 diff --git a/Shaders/WidgetVS.hlsl b/Shaders/WidgetVS.hlsl new file mode 100644 index 0000000..4f72f66 --- /dev/null +++ b/Shaders/WidgetVS.hlsl @@ -0,0 +1,63 @@ + + +cbuffer SceneVars : register(b0) +{ + float4x4 ViewProj; + uint Mode; //0=Vertices, 1=Arc + float Size; //world units + float SegScale; //arc angle / number of segments + float SegOffset; //angle offset of arc + float3 CamRel; //center position + uint CullBack; //culls pixels behind 0,0,0 + float4 Colour; //colour for arc + float3 Axis1; //axis 1 of arc + float WidgetPad2; + float3 Axis2; //axis 2 of arc + float WidgetPad3; +} + +struct WidgetShaderVertex +{ + float4 Position; + float4 Colour; +}; + +StructuredBuffer Vertices : register(t0); + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float4 Colour : COLOR0; + float CullValue : TEXCOORD0; +}; + +VS_OUTPUT main(uint id : SV_VertexID) +{ + float3 ipos; + float4 colour; + float cull; + if (Mode == 0) //Vertices + { + ipos = CamRel + Vertices[id].Position.xyz; + colour = Vertices[id].Colour; + cull = 1; + } + else //(Mode == 1) //Arc + { + float a = SegOffset + (id * SegScale); + float3 a1 = Axis1 * sin(a); + float3 a2 = Axis2 * cos(a); + ipos = CamRel + (a1 + a2) * Size; + colour = Colour; + cull = (CullBack == 1) ? ((length(CamRel) - length(ipos)) / Size) : 1; + } + + float4 opos = mul(float4(ipos, 1), ViewProj); + + VS_OUTPUT output; + output.Position = opos; + output.Colour = colour; + output.CullValue = cull; + return output; +} + diff --git a/Todo.txt b/Todo.txt new file mode 100644 index 0000000..7ba8ab5 --- /dev/null +++ b/Todo.txt @@ -0,0 +1,194 @@ + +CodeWalker todo list + + +update readme!!! + + +---[General bugs]--- + +bug: crash on device suspended (alt-tab...) +bug: crash when other folders present. maybe whitelist folders instead of blacklist! +bug: attach extensions to bones... +bug: delete button on toolbar not enabling when it should +bug: [FIXED?] empty .ynd (+.ymap?) files being saved when they should not be empty, project path problem? +bug: editing world-loaded ymaps won't revert changes after closing project + + +---[General features]--- + +RPF explorer - bulk export metadata files as XML + + + +---[UI stuff]--- + +show areas/zones with their names? popzone etc +world view grid option? + + +---[Editor stuff]--- + +delete key - delete item! + +add entities with preview... asset browser +undo add/delete entities, cargens, path nodes +copy entity extensions when copying entities! + +Path editor: fix: linking to another .ynd in the project +Path editor: fix: update links in other .ynd's when deleting vanilla nodes, add other ynd's to project +Path editor: remap nodes to correct area/.ynd + +Nav mesh editor (YNV) +Interior entities editor (YTYP) +Archetype extension editor (YTYP) +Entity extension editor +Time cycle mod editor +Grass editor +Distant lod lights editor +Mlo instance editor +Water quads editor +Collision editor (YBN) +Timecycle/weather XML editor + +load/convert/save map editor / menyoo xml files, fiveM json files, etc... + + + +---[Rendering stuff]--- + + +model view - improve .ynv rendering (portals etc) +model view - YPT particles - animate particles? do more work on format? + +mapDataGroups - how to isolate one of the grouped ymaps? eg destruction etc. +entitySets - like mapDataGroups but for interiors..... in Mlo data? + +fix LOD switching +fix decal ordering? +fix glass/water render order issues +fix ferris wheel LOD + +Improve shadow cascades configurability + +Finish water rendering - refraction,reflections + +show/hide selection models/geometries - apply not only to selection? - remember setting +select by geometry bounds? (select sub item) - partially built + +vehicles - fix texturing and wheels + +vertex colours/normals/texcoords display for billboards? + +save rotation and zoom for switching model to world view? + + + + +---[Game files stuff]--- + +animations - wind farm / ferris wheel / UFOs... - .ycd files!! +use the base game .meta files to determine which rpf's to load: total conversions +correct moon dir, wobble etc, (timecycle: http://gtaforums.com/topic/830567-v-timecycle-documentation ) +Audio stuff - do more work on .rel format (see https://github.com/CamxxCore/RageAudioTool ) + + + + + + + + +--------------------------- +done: + + +[v.26] +Scenario editor (YMT) +RPF Explorer first edition (OpenIV-style) +Model Viewer window - YDR, YDD, YFT, YBN, YNV, YPT +View YTD, GXT2, FXC, REL, AWC, YWR, YVR files +Metadata>XML - YMT, YMAP, YTYP, CUT etc files (Meta/PSO/RBF) +Collision detection / physics - shoot eggs +First-person mode (press P / Start) +XBOX controller support + + + +[v.25] +entity hierarchy display in selection info window +entity/archetype search window +ydd drawable names replace hashes (mostly) +resize side panel +Path editor: bug: unhandled exceptions for UpDown values (delete existing node / insert invalid value) +Path editor improvements - path links display +open/view scenario .YMT files + + + +[v.24] +Path editor: bug: unhandled exceptions for UpDown values (delete existing node / insert invalid value) +edit entity pivot position/orientation +open/view .YNV files +bug: weather stuff not loading from update.rpf when it should - also try load clouds.xml etc from update.rpf? +bug: paths not shown at all in ymap view... (paths in the current project should!) +bug: mouse ray in 2D map mode! (widgets, mouse select broken) +depth clip option for paths! +Render nav mesh (YNV) +Train path editor +jenkInd can now load additional strings from text files +PropertyGrid fix for Win10 creator update + + +[v.23] +shift key while transforming... clone object! +Paths editor (YND) - see also junctions.xml, junctions.pso, popgroups.ymt +Edit car generators +JenkInd form +render collisions for map mods +hold shift while moving to clone objects. + + +[v.22] +render moon +fix bug: interior entities disappearing when selected +fix bug: project window: ymaps in different path to project +keys to change movement speed for users without mousewheel +configure all key bindings +mouse sensitivity/smoothing settings +export search results list from rpf browser +automatic cache building for custom DLCs without cache files. +select extensions, tc mods, cargens, grass, distant lod lights, mlo instances, waterquads, collisions, paths +(fixed) water quads -> water triangles +(fixed?) bug in GameFileCache causing things to unload repeatedly after stress +don't capture keystrokes in comboboxes.. + +[v.21] +support unencrypted files +setting for maximized window +vehicle shaders +add main toolbar +project window: add multiple ymaps at once +copy/paste entities +finish DLC/updates loading +Map view - XY orthographic, drag to pan instead of rotate.. + +[v.20] +selection xyz widget + draggable version for movement +move selection... +save ymap files... +display camera position/orientation/(+zoom?) somewhere for copy/pasta +render cloth (properly - texcoords - different vertex format) +model mode: current model details in selection info + +[v.18] +HDR rendering +Emissive rendering +Light direction control / time of day? Moonlight? +fix golf course and beach terrain +load mods folder last? (DLC mode) +render bounds mode - render ybn meshes and shapes +render orphan entities - render highest to lowest..? ymt based? +render cables +exclude folders from search +finish vertex colours/texcoords display for basic shader diff --git a/Toolbar/cammode_2D.png b/Toolbar/cammode_2D.png new file mode 100644 index 0000000000000000000000000000000000000000..d4472c92ff6623d2152d84f375563cd1a1844e39 GIT binary patch literal 1309 zcmbVMZA{!`9Ir2#aEj*^Hsc1`^!8y>dVRU}daWGfXgN8yJK#7R!MF9=2k4HrM_af9 zm${(^jWY|w7ziQD2#_qxNLZ$RK->p5anVI|YRobhqx-NJGUE&SK?6Pq9QuLmgH77! z?f?7z{?GrVZ`Q}2DRS*}AqY|wsgdGvd?fc4Y=Pe=ep`{@@R(EG>@=FKPDZu>5>m}1 zKqI=`2I4?gdpfUxas;`rQ%f{E&C&gWV(MNwXXDN4X^2LU^2%&lR#L!0lb}sAg4oY9 z7co>*gV+H!N=DNnXxD0bEzsB-ODMf5g;%l43bZ^cKmr{&GMd#p3|q(su~l9H&U4!Y zhOU}8sUWuIRCBZ*6-^7Ete3?VlBQ6O_fjmwQ&bsBla!C3NP^~ZiV_%3p#13igF!V* zZ585DcwGywf>^ubqy>V=WHR22&udz31jX|_LDB?GB|eXh7`7uD z3dn0~P3hcJA~8SKps5{4Ox(|Aw7DsvI9HdMa?~ z)syb;UF^R4`N{LIXkR>ZXQ4mzeCqFe@uACwwRawVvc;Ktxo6JZ()D}WjUTo>_lZ(6 zdu&Hy>saZh-(G&OqA{~{ZugGSXODO({x#3&t>Wsl4epxo#pP3rAN6e+`7`ll(an|H z%}wCz7y3$XC@+n;vR@5c8+o+zsQbN}yY?+zAHHc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxR5#hc$WX!DQqR!T z#M01EN5ROz&{*HlK;Otx*U-?)#N5izOaTg%fVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD#PU%0_}#n6BP2AO_EVu8M)o`HUDF34YC)x{-2sR(CaRb3oXS&*t9 zlv#J4GnZn%uSMXEsc{6bPbYIj4X{4%`MC)?L297 z?u@1J^~(2?XH4@}iY{r`;`@Mg+Ih=k7y4YkE{)sRBqWua*vur8#GNg1%;KA2OPEfg zxcLk>e!qaT+6Nlc%pWs|ep$#{`L?WAc}oJ@Z83$l2c^$#Snja=V3PGO;dKQ)zO0gt zAOLeOR_un9^b27zm6n2cJJZZ)nmC-cptO$?F%=S>}6lhpc=Y= z&Gx|SbMLRz`|I^FSbbws{EZ#K?Xlt0FKslj`>#Hb2axa1r=GIu6{1-oD!Mc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxR5#hc$WX!DQqR!T z#M01EN5ROz&{*HlK;Otx*U-?)#N5izOaTg%fVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD#PU%0_}#n6BP2AO_EVu8M)o`HUDF34YC)x{-2sR(CaRb3oXS&*t9 zlv#J4GnZn%uSMXEsc{6bPbYIj4X{4%`MCcG8m=7#K}GT^vIyZY{aA*NfRv zqV?fim*!p$Ayr=%ZqBA9LVFlLGUe!Q4SvL$A;tas%gZBPmv3jTR_M6V(fYt&q*>)( zgP~gFegAVEI&4#9D>!D}wX9AnkCA9|oHLOlsqY4(V+yzE>`B>clzaE>XSwmncufN5 zZmwG{+rm5M&pB)pcJaz(?~Fvo-xaQVuUpSJXn1SK5yid@&4y13w63k{2-JQc?ejn| zf5*|ud3!E=P5kn@it)R|#;|<{MU7V7zmg=~{Hr$nwlr&K;AY)l4Z=^pZen|2V!v8U zpDS1M$TPW|({>5`>=DOI+BUTD#%_KUTXJQY@L#U7!%EvWF11`8d2HvrTYoohegE){ zjK%k>H&*p0d+{>q?z;TbBT where TVal : Cacheable + { + public long MaxMemoryUsage = 536870912; //512mb + public long CurrentMemoryUsage = 0; + public double CacheTime = 5.0; //seconds to keep something that's not used + + private LinkedList loadedList = new LinkedList(); + private Dictionary> loadedListDict = new Dictionary>(); + + public Cache() + { + } + public Cache(long maxMemoryUsage, double cacheTime) + { + MaxMemoryUsage = maxMemoryUsage; + CacheTime = cacheTime; + } + + public TVal TryGet(TKey key) + { + LinkedListNode lln = null; + if (loadedListDict.TryGetValue(key, out lln)) + { + loadedList.Remove(lln); + loadedList.AddLast(lln); + lln.Value.LastUseTime = DateTime.Now; + } + return (lln != null) ? lln.Value : null; + } + public bool TryAdd(TKey key, TVal item) + { + if (item.MemoryUsage == 0) + { + } + item.Key = key; + if (CanAdd()) + { + var lln = loadedList.AddLast(item); + loadedListDict.Add(key, lln); + Interlocked.Add(ref CurrentMemoryUsage, item.MemoryUsage); + return true; + } + else + { + //cache full, check the front of the list for oldest.. + var oldlln = loadedList.First; + var cachetime = CacheTime; + int iter = 0, maxiter = 2; + while (!CanAdd() && (iter cachetime)) + { + Interlocked.Add(ref CurrentMemoryUsage, -oldlln.Value.MemoryUsage); + loadedListDict.Remove(oldlln.Value.Key); + loadedList.Remove(oldlln); //gc should free up memory later.. + oldlln.Value = null; + oldlln = null; + //GC.Collect(); + oldlln = loadedList.First; + } + cachetime *= 0.5; + iter++; + } + if (CanAdd()) //see if there's enough memory now... + { + var newlln = loadedList.AddLast(item); + loadedListDict.Add(key, newlln); + Interlocked.Add(ref CurrentMemoryUsage, item.MemoryUsage); + return true; + } + else + { + //really shouldn't get here, but it's possible under stress. + } + } + return false; + } + + public bool CanAdd() + { + return Interlocked.Read(ref CurrentMemoryUsage) < MaxMemoryUsage; + } + + + public void Clear() + { + loadedList.Clear(); + loadedListDict.Clear(); + CurrentMemoryUsage = 0; + } + + public void Remove(TKey key) + { + LinkedListNode n; + if (loadedListDict.TryGetValue(key, out n)) + { + loadedListDict.Remove(key); + loadedList.Remove(n); + CurrentMemoryUsage -= n.Value.MemoryUsage; + } + } + + } + + public abstract class Cacheable + { + public TKey Key; + public DateTime LastUseTime = DateTime.Now; + public long MemoryUsage; + } + +} diff --git a/Utils/DDSIO.cs b/Utils/DDSIO.cs new file mode 100644 index 0000000..d9b5a53 --- /dev/null +++ b/Utils/DDSIO.cs @@ -0,0 +1,2411 @@ +/* + Copyright(c) 2015 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +//DDSIO: stolen and translated + + + + +// #region License +// /* +// Microsoft Public License (Ms-PL) +// MonoGame - Copyright © 2009 The MonoGame Team +// +// All rights reserved. +// +// This license governs use of the accompanying software. If you use the software, you accept this license. If you do not +// accept the license, do not use the software. +// +// 1. Definitions +// The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under +// U.S. copyright law. +// +// A "contribution" is the original software, or any additions or changes to the software. +// A "contributor" is any person that distributes its contribution under this license. +// "Licensed patents" are a contributor's patent claims that read directly on its contribution. +// +// 2. Grant of Rights +// (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, +// each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. +// (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, +// each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. +// +// 3. Conditions and Limitations +// (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +// (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, +// your patent license from such contributor to the software ends automatically. +// (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution +// notices that are present in the software. +// (D) If you distribute any portion of the software in source code form, you may do so only under this license by including +// a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object +// code form, you may only do so under a license that complies with this license. +// (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees +// or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent +// permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular +// purpose and non-infringement. +// */ +// #endregion License + +//DecompressDXT: ripped from MonoGame - todo: reinterpret to remove stupid license + + + +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.Utils +{ + + public static class DDSIO + { + + + public static byte[] GetPixels(Texture texture, int mip) + { + //dexyfex version + var format = GetDXGIFormat(texture.Format); + ImageStruct img = GetImageStruct(texture, format); + Image[] images = GetMipmapImages(img, format); + TexMetadata meta = GetImageMetadata(img, format); + + if (meta.dimension != TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D) + throw new Exception("Can only GetPixels from Texture2D."); + + + var i0 = images[Math.Min(Math.Max(mip, 0), images.Length - 1)]; + + int ddsRowPitch, ddsSlicePitch; + DXTex.ComputePitch(meta.format, i0.width, i0.height, out ddsRowPitch, out ddsSlicePitch, 0); + + if (i0.slicePitch == ddsSlicePitch) + { } + else + { } + + int w = i0.width; + int h = i0.height; + int imglen = i0.slicePitch;// h * i0.rowPitch; + byte[] imgdata = new byte[imglen]; + byte[] px = null;// = new byte[w * h * 4]; + + if (i0.pixels + imglen > img.Data.Length) + { throw new Exception("Mipmap not in texture!"); } + + Buffer.BlockCopy(img.Data, i0.pixels, imgdata, 0, imglen); + + bool swaprb = true; + + switch (format) + { + // compressed + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM: // TextureFormat.D3DFMT_DXT1 + px = DecompressDxt1(imgdata, w, h); + break; + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM: // TextureFormat.D3DFMT_DXT3 + px = DecompressDxt3(imgdata, w, h); + break; + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM: // TextureFormat.D3DFMT_DXT5 + px = DecompressDxt5(imgdata, w, h); + break; + case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM: // TextureFormat.D3DFMT_ATI1 + px = DecompressBC4(imgdata, w, h); + break; + case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM: // TextureFormat.D3DFMT_ATI2 + px = DecompressBC5(imgdata, w, h); + break; + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM: // TextureFormat.D3DFMT_BC7 + //BC7 TODO!! + break; + + // uncompressed + case DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM: // TextureFormat.D3DFMT_A1R5G5B5 + px = ConvertBGR5A1ToRGBA8(imgdata, w, h); //needs testing + break; + case DXGI_FORMAT.DXGI_FORMAT_A8_UNORM: // TextureFormat.D3DFMT_A8 + px = ConvertA8ToRGBA8(imgdata, w, h); + swaprb = false; + break; + case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM: // TextureFormat.D3DFMT_A8B8G8R8 + px = imgdata; + break; + case DXGI_FORMAT.DXGI_FORMAT_R8_UNORM: // TextureFormat.D3DFMT_L8 + px = ConvertR8ToRGBA8(imgdata, w, h); + break; + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM: // TextureFormat.D3DFMT_A8R8G8B8 + px = imgdata; + swaprb = false; + break; + default: + break; //shouldn't get here... + } + + if (swaprb && (px != null)) + { + int pxc = px.Length / 4;// w * h; + for (int i = 0; i < pxc; i++) + { + int ib = i * 4; + byte p2 = px[ib + 2]; + px[ib + 2] = px[ib]; + px[ib] = p2; + } + } + + + return px; + } + + + + public static byte[] GetDDSFile(Texture texture) + { + var format = GetDXGIFormat(texture.Format); + ImageStruct img = GetImageStruct(texture, format); + Image[] images = GetMipmapImages(img, format); + TexMetadata meta = GetImageMetadata(img, format); + + + + + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + + int nimages = img.MipMapLevels; + + // Create DDS Header + int required; + if (!DXTex._EncodeDDSHeader(meta, 0, bw, out required)) + { + throw new Exception("Couldn't make DDS header"); + } + + // Write images + switch (meta.dimension) + { + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D: + { + int index = 0; + for (int item = 0; item < meta.arraySize; ++item) + { + for (int level = 0; level < meta.mipLevels; ++level, ++index) + { + if (index >= nimages) + throw new Exception("Tried to write mip out of range"); + if (images[index].rowPitch <= 0) + throw new Exception("Invalid row pitch."); + if (images[index].slicePitch <= 0) + throw new Exception("Invalid slice pitch."); + //if (images[index].pixels) + // return E_POINTER; + + int ddsRowPitch, ddsSlicePitch; + DXTex.ComputePitch(meta.format, images[index].width, images[index].height, out ddsRowPitch, out ddsSlicePitch, 0);// CP_FLAGS.CP_FLAGS_NONE); + + if (images[index].slicePitch == ddsSlicePitch) + { + int lengt = ddsSlicePitch; + if (images[index].pixels + ddsSlicePitch > img.Data.Length) + { + lengt = img.Data.Length - images[index].pixels; + if (lengt <= 0) + { + //throw new Exception("Not enough data to read..."); + } + } + if (lengt > 0) + { + bw.Write(img.Data, images[index].pixels, lengt); + } + } + else + { + int rowPitch = images[index].rowPitch; + if (rowPitch < ddsRowPitch) + { + // DDS uses 1-byte alignment, so if this is happening then the input pitch isn't actually a full line of data + throw new Exception("Input pitch isn't a full line of data"); + } + + int sPtr = images[index].pixels; + + int lines = DXTex.ComputeScanlines(meta.format, images[index].height); + for (int j = 0; j < lines; ++j) + { + bw.Write(img.Data, sPtr, ddsRowPitch); + sPtr += rowPitch; + } + } + } + } + } + break; + + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE3D: + { + if (meta.arraySize != 1) + throw new Exception("Texture3D must have arraySize == 1"); //return null;// E_FAIL; + + int d = meta.depth; + + int index = 0; + for (int level = 0; level < meta.mipLevels; ++level) + { + for (int slice = 0; slice < d; ++slice, ++index) + { + if (index >= nimages) + throw new Exception("Tried to write mip out of range"); + if (images[index].rowPitch <= 0) + throw new Exception("Invalid row pitch."); + if (images[index].slicePitch <= 0) + throw new Exception("Invalid slice pitch."); + //if (!images[index].pixels) + // return E_POINTER; + + int ddsRowPitch, ddsSlicePitch; + DXTex.ComputePitch(meta.format, images[index].width, images[index].height, out ddsRowPitch, out ddsSlicePitch, 0);// CP_FLAGS_NONE); + + if (images[index].slicePitch == ddsSlicePitch) + { + bw.Write(img.Data, images[index].pixels, ddsSlicePitch); + } + else + { + int rowPitch = images[index].rowPitch; + if (rowPitch < ddsRowPitch) + { + // DDS uses 1-byte alignment, so if this is happening then the input pitch isn't actually a full line of data + throw new Exception("Input pitch isn't a full line of data"); + } + + int sPtr = images[index].pixels; + + int lines = DXTex.ComputeScanlines(meta.format, images[index].height); + for (int j = 0; j < lines; ++j) + { + bw.Write(img.Data, sPtr, ddsRowPitch); + sPtr += rowPitch; + } + } + } + + if (d > 1) + d >>= 1; + } + } + break; + + default: + throw new Exception("Unsupported texture dimension"); + } + + + byte[] buff = ms.GetBuffer(); + byte[] outbuf = new byte[ms.Length]; //need to copy to the right size buffer for File.WriteAllBytes(). + Array.Copy(buff, outbuf, outbuf.Length); + + return outbuf; + } + + + + + private static DXGI_FORMAT GetDXGIFormat(TextureFormat f) + { + var format = DXGI_FORMAT.DXGI_FORMAT_UNKNOWN; + switch (f) + { + // compressed + case TextureFormat.D3DFMT_DXT1: format = DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM; break; + case TextureFormat.D3DFMT_DXT3: format = DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM; break; + case TextureFormat.D3DFMT_DXT5: format = DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM; break; + case TextureFormat.D3DFMT_ATI1: format = DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM; break; + case TextureFormat.D3DFMT_ATI2: format = DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM; break; + case TextureFormat.D3DFMT_BC7: format = DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM; break; + + // uncompressed + case TextureFormat.D3DFMT_A1R5G5B5: format = DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM; break; + case TextureFormat.D3DFMT_A8: format = DXGI_FORMAT.DXGI_FORMAT_A8_UNORM; break; + case TextureFormat.D3DFMT_A8B8G8R8: format = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM; break; + case TextureFormat.D3DFMT_L8: format = DXGI_FORMAT.DXGI_FORMAT_R8_UNORM; break; + case TextureFormat.D3DFMT_A8R8G8B8: format = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM; break; + } + return format; + } + + private static ImageStruct GetImageStruct(Texture texture, DXGI_FORMAT format) + { + ImageStruct img = new ImageStruct(); + img.Data = texture.Data.FullData; + img.Width = texture.Width; + img.Height = texture.Height; + img.MipMapLevels = texture.Levels; + img.Format = (int)format; + return img; + } + + private static Image[] GetMipmapImages(ImageStruct img, DXGI_FORMAT format) + { + Image[] images = new Image[img.MipMapLevels]; + + int buf = 0; + int div = 1; + int add = 0; + for (int i = 0; i < img.MipMapLevels; i++) + { + images[i].width = img.Width / div; + images[i].height = img.Height / div; + images[i].format = format; //(DXGI_FORMAT)img.Format; + images[i].pixels = buf + add; + + DXTex.ComputePitch(images[i].format, images[i].width, images[i].height, out images[i].rowPitch, out images[i].slicePitch, 0); + + add += images[i].slicePitch; + div *= 2; + } + + return images; + } + + private static TexMetadata GetImageMetadata(ImageStruct img, DXGI_FORMAT format) + { + TexMetadata meta = new TexMetadata(); + meta.width = img.Width; + meta.height = img.Height; + meta.depth = 1; + meta.arraySize = 1; // ??? + meta.mipLevels = img.MipMapLevels; + meta.miscFlags = 0; // ??? + meta.miscFlags2 = 0; // ??? + meta.format = format; //(DXGI_FORMAT)img.Format; + meta.dimension = TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D; + return meta; + } + + + public struct TexMetadata + { + public int width; + public int height; // Should be 1 for 1D textures + public int depth; // Should be 1 for 1D or 2D textures + public int arraySize; // For cubemap, this is a multiple of 6 + public int mipLevels; + public uint miscFlags; + public uint miscFlags2; + public DXGI_FORMAT format; + public TEX_DIMENSION dimension; + + // Returns size_t(-1) to indicate an out-of-range error + public int ComputeIndex(int mip, int item, int slice) + { + if (mip >= mipLevels) + return -1; + + switch (dimension) + { + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE1D: + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D: + if (slice > 0) + return -1; + + if (item >= arraySize) + return -1; + + return (item * (mipLevels) + mip); + + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE3D: + if (item > 0) + { + // No support for arrays of volumes + return -1; + } + else + { + int index = 0; + int d = depth; + + for (int level = 0; level < mip; ++level) + { + index += d; + if (d > 1) + d >>= 1; + } + + if (slice >= d) + return -1; + + index += slice; + + return index; + } + //break; + + default: + return -1; + } + } + + // Helper for miscFlags + public bool IsCubemap() + { + return (miscFlags & (uint)TEX_MISC_FLAG.TEX_MISC_TEXTURECUBE) != 0; + } + + public bool IsPMAlpha() + { + return ((miscFlags2 & (uint)TEX_MISC_FLAG.TEX_MISC2_ALPHA_MODE_MASK) == (uint)TEX_ALPHA_MODE.TEX_ALPHA_MODE_PREMULTIPLIED); + } + // Helpers for miscFlags2 + //public void SetAlphaMode(TEX_ALPHA_MODE mode) + //{ + // miscFlags2 = (miscFlags2 & ~TEX_MISC2_ALPHA_MODE_MASK) | static_cast(mode); + //} + + // Helper for dimension + public bool IsVolumemap() + { + return (dimension == TEX_DIMENSION.TEX_DIMENSION_TEXTURE3D); + } + } + + public struct Image + { + public int width; + public int height; + public DXGI_FORMAT format; + public int rowPitch; + public int slicePitch; + public int pixels; //offset into data array... + }; + + public static class DXTex + { + public static void ComputePitch(DXGI_FORMAT fmt, int width, int height, out int rowPitch, out int slicePitch, uint flags) + { + switch (fmt) + { + case DXGI_FORMAT.DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM: + assert(IsCompressed(fmt)); + { + int nbw = Math.Max(1, (width + 3) / 4); + int nbh = Math.Max(1, (height + 3) / 4); + rowPitch = nbw * 8; + + slicePitch = rowPitch * nbh; + } + break; + + case DXGI_FORMAT.DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT.DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB: + assert(IsCompressed(fmt)); + { + int nbw = Math.Max(1, (width + 3) / 4); + int nbh = Math.Max(1, (height + 3) / 4); + rowPitch = nbw * 16; + + slicePitch = rowPitch * nbh; + } + break; + + case DXGI_FORMAT.DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_YUY2: + assert(IsPacked(fmt)); + rowPitch = ((width + 1) >> 1) * 4; + slicePitch = rowPitch * height; + break; + + case DXGI_FORMAT.DXGI_FORMAT_Y210: + case DXGI_FORMAT.DXGI_FORMAT_Y216: + assert(IsPacked(fmt)); + rowPitch = ((width + 1) >> 1) * 8; + slicePitch = rowPitch * height; + break; + + case DXGI_FORMAT.DXGI_FORMAT_NV12: + case DXGI_FORMAT.DXGI_FORMAT_420_OPAQUE: + assert(IsPlanar(fmt)); + rowPitch = ((width + 1) >> 1) * 2; + slicePitch = rowPitch * (height + ((height + 1) >> 1)); + break; + + case DXGI_FORMAT.DXGI_FORMAT_P010: + case DXGI_FORMAT.DXGI_FORMAT_P016: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + assert(IsPlanar(fmt)); + rowPitch = ((width + 1) >> 1) * 4; + slicePitch = rowPitch * (height + ((height + 1) >> 1)); + break; + + case DXGI_FORMAT.DXGI_FORMAT_NV11: + assert(IsPlanar(fmt)); + rowPitch = ((width + 3) >> 2) * 4; + slicePitch = rowPitch * height * 2; + break; + + case DXGI_FORMAT.WIN10_DXGI_FORMAT_P208: + assert(IsPlanar(fmt)); + rowPitch = ((width + 1) >> 1) * 2; + slicePitch = rowPitch * height * 2; + break; + + case DXGI_FORMAT.WIN10_DXGI_FORMAT_V208: + assert(IsPlanar(fmt)); + rowPitch = width; + slicePitch = rowPitch * (height + (((height + 1) >> 1) * 2)); + break; + + case DXGI_FORMAT.WIN10_DXGI_FORMAT_V408: + assert(IsPlanar(fmt)); + rowPitch = width; + slicePitch = rowPitch * (height + ((height >> 1) * 4)); + break; + + default: + assert(IsValid(fmt)); + assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt)); + { + + int bpp; + + if ((flags & (uint)CP_FLAGS.CP_FLAGS_24BPP) != 0) + bpp = 24; + else if ((flags & (uint)CP_FLAGS.CP_FLAGS_16BPP) != 0) + bpp = 16; + else if ((flags & (uint)CP_FLAGS.CP_FLAGS_8BPP) != 0) + bpp = 8; + else + bpp = BitsPerPixel(fmt); + + if ((flags & (uint)(CP_FLAGS.CP_FLAGS_LEGACY_DWORD | CP_FLAGS.CP_FLAGS_PARAGRAPH | CP_FLAGS.CP_FLAGS_YMM | CP_FLAGS.CP_FLAGS_ZMM | CP_FLAGS.CP_FLAGS_PAGE4K)) != 0) + { + if ((flags & (uint)CP_FLAGS.CP_FLAGS_PAGE4K) != 0) + { + rowPitch = ((width * bpp + 32767) / 32768) * 4096; + slicePitch = rowPitch * height; + } + else if ((flags & (uint)CP_FLAGS.CP_FLAGS_ZMM) != 0) + { + rowPitch = ((width * bpp + 511) / 512) * 64; + slicePitch = rowPitch * height; + } + else if ((flags & (uint)CP_FLAGS.CP_FLAGS_YMM) != 0) + { + rowPitch = ((width * bpp + 255) / 256) * 32; + slicePitch = rowPitch * height; + } + else if ((flags & (uint)CP_FLAGS.CP_FLAGS_PARAGRAPH) != 0) + { + rowPitch = ((width * bpp + 127) / 128) * 16; + slicePitch = rowPitch * height; + } + else // DWORD alignment + { + // Special computation for some incorrectly created DDS files based on + // legacy DirectDraw assumptions about pitch alignment + rowPitch = ((width * bpp + 31) / 32) * 4;// sizeof(uint32_t); + slicePitch = rowPitch * height; + } + } + else + { + // Default byte alignment + rowPitch = (width * bpp + 7) / 8; + slicePitch = rowPitch * height; + } + } + break; + } + } + + public static bool IsCompressed(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT.DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT.DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB: + return true; + + default: + return false; + } + } + + public static bool IsPlanar(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT.DXGI_FORMAT_NV12: // 4:2:0 8-bit + case DXGI_FORMAT.DXGI_FORMAT_P010: // 4:2:0 10-bit + case DXGI_FORMAT.DXGI_FORMAT_P016: // 4:2:0 16-bit + case DXGI_FORMAT.DXGI_FORMAT_420_OPAQUE:// 4:2:0 8-bit + case DXGI_FORMAT.DXGI_FORMAT_NV11: // 4:1:1 8-bit + + case DXGI_FORMAT.WIN10_DXGI_FORMAT_P208: // 4:2:2 8-bit + case DXGI_FORMAT.WIN10_DXGI_FORMAT_V208: // 4:4:0 8-bit + case DXGI_FORMAT.WIN10_DXGI_FORMAT_V408: // 4:4:4 8-bit + // These are JPEG Hardware decode formats (DXGI 1.4) + + case DXGI_FORMAT.XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + // These are Xbox One platform specific types + return true; + + default: + return false; + } + + } + + public static bool IsPacked(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT.DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_YUY2: // 4:2:2 8-bit + case DXGI_FORMAT.DXGI_FORMAT_Y210: // 4:2:2 10-bit + case DXGI_FORMAT.DXGI_FORMAT_Y216: // 4:2:2 16-bit + return true; + + default: + return false; + } + } + + public static void assert(bool b) + { + if (!b) + { + throw new Exception(); + } + } + + + + public static bool IsValid(DXGI_FORMAT fmt) + { + return (((int)fmt) >= 1 && ((int)fmt) <= 190); + } + public static bool IsPalettized(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT.DXGI_FORMAT_AI44: + case DXGI_FORMAT.DXGI_FORMAT_IA44: + case DXGI_FORMAT.DXGI_FORMAT_P8: + case DXGI_FORMAT.DXGI_FORMAT_A8P8: + return true; + + default: + return false; + } + } + + + public static int BitsPerPixel(DXGI_FORMAT fmt) + { + switch (fmt) + { + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_SINT: + return 128; + + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32_SINT: + return 96; + + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT.DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT.DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT.DXGI_FORMAT_Y416: + case DXGI_FORMAT.DXGI_FORMAT_Y210: + case DXGI_FORMAT.DXGI_FORMAT_Y216: + return 64; + + case DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT.DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT.DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT.DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT.DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_AYUV: + case DXGI_FORMAT.DXGI_FORMAT_Y410: + case DXGI_FORMAT.DXGI_FORMAT_YUY2: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM: + return 32; + + case DXGI_FORMAT.DXGI_FORMAT_P010: + case DXGI_FORMAT.DXGI_FORMAT_P016: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + case DXGI_FORMAT.WIN10_DXGI_FORMAT_V408: + return 24; + + case DXGI_FORMAT.DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT.DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT.DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_A8P8: + case DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM: + case DXGI_FORMAT.WIN10_DXGI_FORMAT_P208: + case DXGI_FORMAT.WIN10_DXGI_FORMAT_V208: + return 16; + + case DXGI_FORMAT.DXGI_FORMAT_NV12: + case DXGI_FORMAT.DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT.DXGI_FORMAT_NV11: + return 12; + + case DXGI_FORMAT.DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT.DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT.DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_AI44: + case DXGI_FORMAT.DXGI_FORMAT_IA44: + case DXGI_FORMAT.DXGI_FORMAT_P8: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_R4G4_UNORM: + return 8; + + case DXGI_FORMAT.DXGI_FORMAT_R1_UNORM: + return 1; + + case DXGI_FORMAT.DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM: + return 4; + + case DXGI_FORMAT.DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT.DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB: + return 8; + + default: + return 0; + } + } + + + + public static int ComputeScanlines(DXGI_FORMAT fmt, int height) + { + switch (fmt) + { + case DXGI_FORMAT.DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT.DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT.DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT.DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB: + assert(IsCompressed(fmt)); + return Math.Max(1, (height + 3) / 4); + + case DXGI_FORMAT.DXGI_FORMAT_NV11: + case DXGI_FORMAT.WIN10_DXGI_FORMAT_P208: + assert(IsPlanar(fmt)); + return height * 2; + + case DXGI_FORMAT.WIN10_DXGI_FORMAT_V208: + assert(IsPlanar(fmt)); + return height + (((height + 1) >> 1) * 2); + + case DXGI_FORMAT.WIN10_DXGI_FORMAT_V408: + assert(IsPlanar(fmt)); + return height + ((height >> 1) * 4); + + case DXGI_FORMAT.DXGI_FORMAT_NV12: + case DXGI_FORMAT.DXGI_FORMAT_P010: + case DXGI_FORMAT.DXGI_FORMAT_P016: + case DXGI_FORMAT.DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS: + case DXGI_FORMAT.XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT: + assert(IsPlanar(fmt)); + return height + ((height + 1) >> 1); + + default: + assert(IsValid(fmt)); + assert(!IsCompressed(fmt) && !IsPlanar(fmt)); + return height; + } + } + + + + + + public static uint DDS_HEADER_FLAGS_TEXTURE = 0x00001007; // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT + public static uint DDS_HEADER_FLAGS_MIPMAP = 0x00020000; // DDSD_MIPMAPCOUNT + public static uint DDS_HEADER_FLAGS_VOLUME = 0x00800000; // DDSD_DEPTH + public static uint DDS_HEADER_FLAGS_PITCH = 0x00000008; // DDSD_PITCH + public static uint DDS_HEADER_FLAGS_LINEARSIZE = 0x00080000; // DDSD_LINEARSIZE + + public static uint DDS_HEIGHT = 0x00000002; // DDSD_HEIGHT + public static uint DDS_WIDTH = 0x00000004; // DDSD_WIDTH + + public static uint DDS_SURFACE_FLAGS_TEXTURE = 0x00001000; // DDSCAPS_TEXTURE + public static uint DDS_SURFACE_FLAGS_MIPMAP = 0x00400008; // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP + public static uint DDS_SURFACE_FLAGS_CUBEMAP = 0x00000008; // DDSCAPS_COMPLEX + + public static uint DDS_CUBEMAP_POSITIVEX = 0x00000600; // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX + public static uint DDS_CUBEMAP_NEGATIVEX = 0x00000a00; // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX + public static uint DDS_CUBEMAP_POSITIVEY = 0x00001200; // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY + public static uint DDS_CUBEMAP_NEGATIVEY = 0x00002200; // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY + public static uint DDS_CUBEMAP_POSITIVEZ = 0x00004200; // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ + public static uint DDS_CUBEMAP_NEGATIVEZ = 0x00008200; // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + + public static uint DDS_CUBEMAP_ALLFACES = (DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX | + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY | + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ); + + public static uint DDS_CUBEMAP = 0x00000200; // DDSCAPS2_CUBEMAP + + public static uint DDS_FLAGS_VOLUME = 0x00200000; // DDSCAPS2_VOLUME + + + + + //------------------------------------------------------------------------------------- + // Encodes DDS file header (magic value, header, optional DX10 extended header) + //------------------------------------------------------------------------------------- + public static bool _EncodeDDSHeader(TexMetadata metadata, uint flags, BinaryWriter bw, out int required) + { + //const uint MAX_HEADER_SIZE = sizeof(uint) + 31*4/*sizeof(DDS_HEADER)*/ + 5*4/*sizeof(DDS_HEADER_DXT10)*/; + //byte header[MAX_HEADER_SIZE]; + + required = 0; + if (!IsValid(metadata.format)) + return false; + + if (IsPalettized(metadata.format)) + return false;// HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + if (metadata.arraySize > 1) + { + if ((metadata.arraySize != 6) || (metadata.dimension != TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D) || !(metadata.IsCubemap())) + { + // Texture1D arrays, Texture2D arrays, and Cubemap arrays must be stored using 'DX10' extended header + flags |= (uint)DDS_FLAGS.DDS_FLAGS_FORCE_DX10_EXT; + } + } + + if ((flags & (uint)DDS_FLAGS.DDS_FLAGS_FORCE_DX10_EXT_MISC2)!=0) + { + flags |= (uint)DDS_FLAGS.DDS_FLAGS_FORCE_DX10_EXT; + } + + DDS_PIXELFORMAT ddpf = new DDS_PIXELFORMAT(0); + if (!((flags & (uint)DDS_FLAGS.DDS_FLAGS_FORCE_DX10_EXT)!=0)) + { + switch (metadata.format) + { + case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_A8B8G8R8; break; + case DXGI_FORMAT.DXGI_FORMAT_R16G16_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_G16R16; break; + case DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_A8L8; break; + case DXGI_FORMAT.DXGI_FORMAT_R16_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_L16; break; + case DXGI_FORMAT.DXGI_FORMAT_R8_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_L8; break; + case DXGI_FORMAT.DXGI_FORMAT_A8_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_A8; break; + case DXGI_FORMAT.DXGI_FORMAT_R8G8_B8G8_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_R8G8_B8G8; break; + case DXGI_FORMAT.DXGI_FORMAT_G8R8_G8B8_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_G8R8_G8B8; break; + case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_DXT1; break; + case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM: ddpf = metadata.IsPMAlpha() ? (DDS_PIXELFORMAT.DDSPF_DXT2) : (DDS_PIXELFORMAT.DDSPF_DXT3); break; + case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM: ddpf = metadata.IsPMAlpha() ? (DDS_PIXELFORMAT.DDSPF_DXT4) : (DDS_PIXELFORMAT.DDSPF_DXT5); break; + case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_BC4_UNORM; break; + case DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM: ddpf = DDS_PIXELFORMAT.DDSPF_BC4_SNORM; break; + case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_BC5_UNORM; break; + case DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM: ddpf = DDS_PIXELFORMAT.DDSPF_BC5_SNORM; break; + case DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_R5G6B5; break; + case DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_A1R5G5B5; break; + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_A8R8G8B8; break; // DXGI 1.1 + case DXGI_FORMAT.DXGI_FORMAT_B8G8R8X8_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_X8R8G8B8; break; // DXGI 1.1 + case DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM: ddpf = DDS_PIXELFORMAT.DDSPF_A4R4G4B4; break; // DXGI 1.2 + case DXGI_FORMAT.DXGI_FORMAT_YUY2: ddpf = DDS_PIXELFORMAT.DDSPF_YUY2; break; // DXGI 1.2 + + // Legacy D3DX formats using D3DFMT enum value as FourCC + case DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT: + ddpf.dwSize = 32/*sizeof(DDS_PIXELFORMAT)*/; ddpf.dwFlags = DDS_PIXELFORMAT.DDS_FOURCC; ddpf.dwFourCC = 116; // D3DFMT_A32B32G32R32F + break; + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT: + ddpf.dwSize = 32/*sizeof(DDS_PIXELFORMAT)*/; ddpf.dwFlags = DDS_PIXELFORMAT.DDS_FOURCC; ddpf.dwFourCC = 113; // D3DFMT_A16B16G16R16F + break; + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_UNORM: + ddpf.dwSize = 32/*sizeof(DDS_PIXELFORMAT)*/; ddpf.dwFlags = DDS_PIXELFORMAT.DDS_FOURCC; ddpf.dwFourCC = 36; // D3DFMT_A16B16G16R16 + break; + case DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_SNORM: + ddpf.dwSize = 32/*sizeof(DDS_PIXELFORMAT)*/; ddpf.dwFlags = DDS_PIXELFORMAT.DDS_FOURCC; ddpf.dwFourCC = 110; // D3DFMT_Q16W16V16U16 + break; + case DXGI_FORMAT.DXGI_FORMAT_R32G32_FLOAT: + ddpf.dwSize = 32/*sizeof(DDS_PIXELFORMAT)*/; ddpf.dwFlags = DDS_PIXELFORMAT.DDS_FOURCC; ddpf.dwFourCC = 115; // D3DFMT_G32R32F + break; + case DXGI_FORMAT.DXGI_FORMAT_R16G16_FLOAT: + ddpf.dwSize = 32/*sizeof(DDS_PIXELFORMAT)*/; ddpf.dwFlags = DDS_PIXELFORMAT.DDS_FOURCC; ddpf.dwFourCC = 112; // D3DFMT_G16R16F + break; + case DXGI_FORMAT.DXGI_FORMAT_R32_FLOAT: + ddpf.dwSize = 32/*sizeof(DDS_PIXELFORMAT)*/; ddpf.dwFlags = DDS_PIXELFORMAT.DDS_FOURCC; ddpf.dwFourCC = 114; // D3DFMT_R32F + break; + case DXGI_FORMAT.DXGI_FORMAT_R16_FLOAT: + ddpf.dwSize = 32/*sizeof(DDS_PIXELFORMAT)*/; ddpf.dwFlags = DDS_PIXELFORMAT.DDS_FOURCC; ddpf.dwFourCC = 111; // D3DFMT_R16F + break; + } + } + + int sizeofddsheader = 31 * 4; + int sizeofddsheader10 = 5 * 4; + const uint DDS_MAGIC = 0x20534444; // "DDS " + + required = 4/*sizeof(uint32_t)*/ + sizeofddsheader/*sizeof(DDS_HEADER)*/; + + if (ddpf.dwSize == 0) + required += sizeofddsheader10;// sizeof(DDS_HEADER_DXT10); + + //if (!pDestination) + // return S_OK; + + //if (maxsize < required) + // return E_NOT_SUFFICIENT_BUFFER; + + //*reinterpret_cast(pDestination) = DDS_MAGIC; + //bw.Write(DDS_MAGIC); + + var header = new DDS_HEADER(); + //auto header = reinterpret_cast(reinterpret_cast(pDestination) + sizeof(uint32_t)); + //assert(header); + + //memset(header, 0, sizeof(DDS_HEADER)); + header.dwSize = (uint)sizeofddsheader;// sizeof(DDS_HEADER); + header.dwFlags = DDS_HEADER_FLAGS_TEXTURE; + header.dwCaps = DDS_SURFACE_FLAGS_TEXTURE; + + if (metadata.mipLevels > 0) + { + header.dwFlags |= DDS_HEADER_FLAGS_MIPMAP; + +//# ifdef _M_X64 +// if (metadata.mipLevels > 0xFFFFFFFF) +// return E_INVALIDARG; +//#endif + + header.dwMipMapCount = (uint)(metadata.mipLevels); + + if (header.dwMipMapCount > 1) + header.dwCaps |= DDS_SURFACE_FLAGS_MIPMAP; + } + + switch (metadata.dimension) + { + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE1D: +//# ifdef _M_X64 +// if (metadata.width > 0xFFFFFFFF) +// return E_INVALIDARG; +//#endif + + header.dwWidth = (uint)(metadata.width); + header.dwHeight = header.dwDepth = 1; + break; + + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE2D: +//# ifdef _M_X64 +// if (metadata.height > 0xFFFFFFFF +// || metadata.width > 0xFFFFFFFF) +// return E_INVALIDARG; +//#endif + + header.dwHeight = (uint)(metadata.height); + header.dwWidth = (uint)(metadata.width); + header.dwDepth = 1; + + if (metadata.IsCubemap()) + { + header.dwCaps |= DDS_SURFACE_FLAGS_CUBEMAP; + header.dwCaps2 |= DDS_CUBEMAP_ALLFACES; + } + break; + + case TEX_DIMENSION.TEX_DIMENSION_TEXTURE3D: +//# ifdef _M_X64 +// if (metadata.height > 0xFFFFFFFF +// || metadata.width > 0xFFFFFFFF +// || metadata.depth > 0xFFFFFFFF) +// return E_INVALIDARG; +//#endif + + header.dwFlags |= DDS_HEADER_FLAGS_VOLUME; + header.dwCaps2 |= DDS_FLAGS_VOLUME; + header.dwHeight = (uint)(metadata.height); + header.dwWidth = (uint)(metadata.width); + header.dwDepth = (uint)(metadata.depth); + break; + + default: + return false;// E_FAIL; + } + + int rowPitch, slicePitch; + ComputePitch(metadata.format, metadata.width, metadata.height, out rowPitch, out slicePitch, 0);// (uint)CP_FLAGS.CP_FLAGS_NONE); + +//# ifdef _M_X64 +// if (slicePitch > 0xFFFFFFFF +// || rowPitch > 0xFFFFFFFF) +// return E_FAIL; +//#endif + + if (IsCompressed(metadata.format)) + { + header.dwFlags |= DDS_HEADER_FLAGS_LINEARSIZE; + header.dwPitchOrLinearSize = (uint)(slicePitch); + } + else + { + header.dwFlags |= DDS_HEADER_FLAGS_PITCH; + header.dwPitchOrLinearSize = (uint)(rowPitch); + } + + var ext = new DDS_HEADER_DXT10(); + if (ddpf.dwSize == 0) + { + header.ddspf = DDS_PIXELFORMAT.DDSPF_DX10; + //memcpy_s(&header->ddspf, sizeof(header->ddspf), &DDSPF_DX10, sizeof(DDS_PIXELFORMAT) ); + + //auto ext = reinterpret_cast(reinterpret_cast(header) + sizeof(DDS_HEADER)); + //assert(ext); + //var ext = new DDS_HEADER_DXT10(); + + //memset(ext, 0, sizeof(DDS_HEADER_DXT10)); + ext.dxgiFormat = metadata.format; + ext.resourceDimension = (uint)metadata.dimension; + +//# ifdef _M_X64 +// if (metadata.arraySize > 0xFFFFFFFF) +// return E_INVALIDARG; +//#endif + + //static_assert(TEX_MISC_TEXTURECUBE == DDS_RESOURCE_MISC_TEXTURECUBE, "DDS header mismatch"); + + ext.miscFlag = metadata.miscFlags & ~((uint)TEX_MISC_FLAG.TEX_MISC_TEXTURECUBE); + + if ((metadata.miscFlags & (uint)TEX_MISC_FLAG.TEX_MISC_TEXTURECUBE)!=0) + { + ext.miscFlag |= (uint)TEX_MISC_FLAG.TEX_MISC_TEXTURECUBE; + assert((metadata.arraySize % 6) == 0); + ext.arraySize = (uint)(metadata.arraySize / 6); + } + else + { + ext.arraySize = (uint)(metadata.arraySize); + } + + //static_assert(TEX_MISC2_ALPHA_MODE_MASK == DDS_MISC_FLAGS2_ALPHA_MODE_MASK, "DDS header mismatch"); + //static_assert(TEX_ALPHA_MODE_UNKNOWN == DDS_ALPHA_MODE_UNKNOWN, "DDS header mismatch"); + //static_assert(TEX_ALPHA_MODE_STRAIGHT == DDS_ALPHA_MODE_STRAIGHT, "DDS header mismatch"); + //static_assert(TEX_ALPHA_MODE_PREMULTIPLIED == DDS_ALPHA_MODE_PREMULTIPLIED, "DDS header mismatch"); + //static_assert(TEX_ALPHA_MODE_OPAQUE == DDS_ALPHA_MODE_OPAQUE, "DDS header mismatch"); + //static_assert(TEX_ALPHA_MODE_CUSTOM == DDS_ALPHA_MODE_CUSTOM, "DDS header mismatch"); + + if ((flags & (uint)DDS_FLAGS.DDS_FLAGS_FORCE_DX10_EXT_MISC2)!=0) + { + // This was formerly 'reserved'. D3DX10 and D3DX11 will fail if this value is anything other than 0 + ext.miscFlags2 = metadata.miscFlags2; + } + } + else + { + header.ddspf = ddpf; + //memcpy_s(&header.ddspf, sizeof(header.ddspf), &ddpf, sizeof(ddpf) ); + } + + + //magic write + bw.Write(DDS_MAGIC); + + //write header + bw.Write(header.dwSize); + bw.Write(header.dwFlags); + bw.Write(header.dwHeight); + bw.Write(header.dwWidth); + bw.Write(header.dwPitchOrLinearSize); + bw.Write(header.dwDepth); // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags + bw.Write(header.dwMipMapCount); + + //public uint dwReserved1[11]; //x11 + for (int i = 0; i < 11; i++) bw.Write(0); + + //bw.Write(header.ddspf); + bw.Write(header.ddspf.dwSize); + bw.Write(header.ddspf.dwFlags); + bw.Write(header.ddspf.dwFourCC); + bw.Write(header.ddspf.dwRGBBitCount); + bw.Write(header.ddspf.dwRBitMask); + bw.Write(header.ddspf.dwGBitMask); + bw.Write(header.ddspf.dwBBitMask); + bw.Write(header.ddspf.dwABitMask); + + bw.Write(header.dwCaps); + bw.Write(header.dwCaps2); + bw.Write(header.dwCaps3); + bw.Write(header.dwCaps4); + bw.Write(header.dwReserved2); + + + if (ddpf.dwSize == 0) + { + //write ext + bw.Write((uint)ext.dxgiFormat); + bw.Write(ext.resourceDimension); + bw.Write(ext.miscFlag); // see DDS_RESOURCE_MISC_FLAG + bw.Write(ext.arraySize); + bw.Write(ext.miscFlags2); // see DDS_MISC_FLAGS2 + } + + return true; //S_OK + } + + + + + } + + public enum CP_FLAGS : uint + { + CP_FLAGS_NONE = 0x0, // Normal operation + CP_FLAGS_LEGACY_DWORD = 0x1, // Assume pitch is DWORD aligned instead of BYTE aligned + CP_FLAGS_PARAGRAPH = 0x2, // Assume pitch is 16-byte aligned instead of BYTE aligned + CP_FLAGS_YMM = 0x4, // Assume pitch is 32-byte aligned instead of BYTE aligned + CP_FLAGS_ZMM = 0x8, // Assume pitch is 64-byte aligned instead of BYTE aligned + CP_FLAGS_PAGE4K = 0x200, // Assume pitch is 4096-byte aligned instead of BYTE aligned + CP_FLAGS_24BPP = 0x10000, // Override with a legacy 24 bits-per-pixel format size + CP_FLAGS_16BPP = 0x20000, // Override with a legacy 16 bits-per-pixel format size + CP_FLAGS_8BPP = 0x40000, // Override with a legacy 8 bits-per-pixel format size + } + + + public class ImageStruct + { + public int Width; + public int Height; + //property int Stride; + public int Format; + public int MipMapLevels; + public byte[] Data; + + int GetRowPitch() + { + int rowPitch; + int slicePitch; + DXTex.ComputePitch((DXGI_FORMAT)Format, Width, Height, out rowPitch, out slicePitch, 0); + return rowPitch; + } + + int GetSlicePitch() + { + int rowPitch; + int slicePitch; + DXTex.ComputePitch((DXGI_FORMAT)Format, Width, Height, out rowPitch, out slicePitch, 0); + return slicePitch; + } + + + } + + public enum DXGI_FORMAT : uint + { + DXGI_FORMAT_UNKNOWN = 0, + DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, + DXGI_FORMAT_R32G32B32A32_FLOAT = 2, + DXGI_FORMAT_R32G32B32A32_UINT = 3, + DXGI_FORMAT_R32G32B32A32_SINT = 4, + DXGI_FORMAT_R32G32B32_TYPELESS = 5, + DXGI_FORMAT_R32G32B32_FLOAT = 6, + DXGI_FORMAT_R32G32B32_UINT = 7, + DXGI_FORMAT_R32G32B32_SINT = 8, + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + DXGI_FORMAT_R32G32_TYPELESS = 15, + DXGI_FORMAT_R32G32_FLOAT = 16, + DXGI_FORMAT_R32G32_UINT = 17, + DXGI_FORMAT_R32G32_SINT = 18, + DXGI_FORMAT_R32G8X24_TYPELESS = 19, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, + DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, + DXGI_FORMAT_R10G10B10A2_UNORM = 24, + DXGI_FORMAT_R10G10B10A2_UINT = 25, + DXGI_FORMAT_R11G11B10_FLOAT = 26, + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + DXGI_FORMAT_R16G16_TYPELESS = 33, + DXGI_FORMAT_R16G16_FLOAT = 34, + DXGI_FORMAT_R16G16_UNORM = 35, + DXGI_FORMAT_R16G16_UINT = 36, + DXGI_FORMAT_R16G16_SNORM = 37, + DXGI_FORMAT_R16G16_SINT = 38, + DXGI_FORMAT_R32_TYPELESS = 39, + DXGI_FORMAT_D32_FLOAT = 40, + DXGI_FORMAT_R32_FLOAT = 41, + DXGI_FORMAT_R32_UINT = 42, + DXGI_FORMAT_R32_SINT = 43, + DXGI_FORMAT_R24G8_TYPELESS = 44, + DXGI_FORMAT_D24_UNORM_S8_UINT = 45, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, + DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, + DXGI_FORMAT_R8G8_TYPELESS = 48, + DXGI_FORMAT_R8G8_UNORM = 49, + DXGI_FORMAT_R8G8_UINT = 50, + DXGI_FORMAT_R8G8_SNORM = 51, + DXGI_FORMAT_R8G8_SINT = 52, + DXGI_FORMAT_R16_TYPELESS = 53, + DXGI_FORMAT_R16_FLOAT = 54, + DXGI_FORMAT_D16_UNORM = 55, + DXGI_FORMAT_R16_UNORM = 56, + DXGI_FORMAT_R16_UINT = 57, + DXGI_FORMAT_R16_SNORM = 58, + DXGI_FORMAT_R16_SINT = 59, + DXGI_FORMAT_R8_TYPELESS = 60, + DXGI_FORMAT_R8_UNORM = 61, + DXGI_FORMAT_R8_UINT = 62, + DXGI_FORMAT_R8_SNORM = 63, + DXGI_FORMAT_R8_SINT = 64, + DXGI_FORMAT_A8_UNORM = 65, + DXGI_FORMAT_R1_UNORM = 66, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, + DXGI_FORMAT_R8G8_B8G8_UNORM = 68, + DXGI_FORMAT_G8R8_G8B8_UNORM = 69, + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B5G5R5A1_UNORM = 86, + DXGI_FORMAT_B8G8R8A8_UNORM = 87, + DXGI_FORMAT_B8G8R8X8_UNORM = 88, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_AYUV = 100, + DXGI_FORMAT_Y410 = 101, + DXGI_FORMAT_Y416 = 102, + DXGI_FORMAT_NV12 = 103, + DXGI_FORMAT_P010 = 104, + DXGI_FORMAT_P016 = 105, + DXGI_FORMAT_420_OPAQUE = 106, + DXGI_FORMAT_YUY2 = 107, + DXGI_FORMAT_Y210 = 108, + DXGI_FORMAT_Y216 = 109, + DXGI_FORMAT_NV11 = 110, + DXGI_FORMAT_AI44 = 111, + DXGI_FORMAT_IA44 = 112, + DXGI_FORMAT_P8 = 113, + DXGI_FORMAT_A8P8 = 114, + DXGI_FORMAT_B4G4R4A4_UNORM = 115, + DXGI_FORMAT_FORCE_UINT = 0xffffffff, + + + XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT = 116, + XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT = 117, + XBOX_DXGI_FORMAT_D16_UNORM_S8_UINT = 118, + XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS = 119, + XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT = 120, + + WIN10_DXGI_FORMAT_P208 = 130, + WIN10_DXGI_FORMAT_V208 = 131, + WIN10_DXGI_FORMAT_V408 = 132, + + XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM = 189, + XBOX_DXGI_FORMAT_R4G4_UNORM = 190, + + + } + + public enum TEX_DIMENSION : uint + { // Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION + TEX_DIMENSION_TEXTURE1D = 2, + TEX_DIMENSION_TEXTURE2D = 3, + TEX_DIMENSION_TEXTURE3D = 4, + } + + public enum TEX_MISC_FLAG : long // Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG + { + TEX_MISC_TEXTURECUBE = 0x4L, + TEX_MISC2_ALPHA_MODE_MASK = 0x7L, + } + + public enum TEX_ALPHA_MODE // Matches DDS_ALPHA_MODE, encoded in MISC_FLAGS2 + { + TEX_ALPHA_MODE_UNKNOWN = 0, + TEX_ALPHA_MODE_STRAIGHT = 1, + TEX_ALPHA_MODE_PREMULTIPLIED = 2, + TEX_ALPHA_MODE_OPAQUE = 3, + TEX_ALPHA_MODE_CUSTOM = 4, + } + + + public struct DDS_HEADER + { + public uint dwSize; + public uint dwFlags; + public uint dwHeight; + public uint dwWidth; + public uint dwPitchOrLinearSize; + public uint dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags + public uint dwMipMapCount; + //public uint dwReserved1[11]; //x11 + public DDS_PIXELFORMAT ddspf; + public uint dwCaps; + public uint dwCaps2; + public uint dwCaps3; + public uint dwCaps4; + public uint dwReserved2; + }; + + public struct DDS_HEADER_DXT10 + { + public DXGI_FORMAT dxgiFormat; + public uint resourceDimension; + public uint miscFlag; // see DDS_RESOURCE_MISC_FLAG + public uint arraySize; + public uint miscFlags2; // see DDS_MISC_FLAGS2 + }; + + public struct DDS_PIXELFORMAT + { + public uint dwSize; + public uint dwFlags; + public uint dwFourCC; + public uint dwRGBBitCount; + public uint dwRBitMask; + public uint dwGBitMask; + public uint dwBBitMask; + public uint dwABitMask; + + public DDS_PIXELFORMAT(uint val) + { + dwSize = val; + dwFlags = val; + dwFourCC = val; + dwRGBBitCount = val; + dwRBitMask = val; + dwGBitMask = val; + dwBBitMask = val; + dwABitMask = val; + } + public DDS_PIXELFORMAT(uint size, uint flags, uint fourcc, uint rgbbitcount, uint rmask, uint gmask, uint bmask, uint amask) + { + dwSize = size; + dwFlags = flags; + dwFourCC = fourcc; + dwRGBBitCount = rgbbitcount; + dwRBitMask = rmask; + dwGBitMask = gmask; + dwBBitMask = bmask; + dwABitMask = amask; + } + + + public static uint MAKEFOURCC(char ch0, char ch1, char ch2, char ch3) + { + return + ((uint)(byte)(ch0) | ((uint)(byte)(ch1) << 8) | + ((uint)(byte)(ch2) << 16) | ((uint)(byte)(ch3) << 24)); + } + public static uint DDS_FOURCC = 0x00000004; // DDPF_FOURCC + public static uint DDS_RGB = 0x00000040; // DDPF_RGB + public static uint DDS_RGBA = 0x00000041; // DDPF_RGB | DDPF_ALPHAPIXELS + public static uint DDS_LUMINANCE = 0x00020000; // DDPF_LUMINANCE + public static uint DDS_LUMINANCEA = 0x00020001; // DDPF_LUMINANCE | DDPF_ALPHAPIXELS + public static uint DDS_ALPHA = 0x00000002; // DDPF_ALPHA + public static uint DDS_PAL8 = 0x00000020; // DDPF_PALETTEINDEXED8 + + + public static DDS_PIXELFORMAT DDSPF_DXT1 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 ); + + public static DDS_PIXELFORMAT DDSPF_DXT2 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_DXT3 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_DXT4 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_DXT5 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_BC4_UNORM = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_BC4_SNORM = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_BC5_UNORM = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_BC5_SNORM = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_YUY2 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0); + + public static DDS_PIXELFORMAT DDSPF_A8R8G8B8 = new DDS_PIXELFORMAT( + 32, DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); + + public static DDS_PIXELFORMAT DDSPF_X8R8G8B8 = new DDS_PIXELFORMAT( + 32, DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000); + + public static DDS_PIXELFORMAT DDSPF_A8B8G8R8 = new DDS_PIXELFORMAT( + 32, DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); + + public static DDS_PIXELFORMAT DDSPF_X8B8G8R8 = new DDS_PIXELFORMAT( + 32, DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000); + + public static DDS_PIXELFORMAT DDSPF_G16R16 = new DDS_PIXELFORMAT( + 32, DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000); + + public static DDS_PIXELFORMAT DDSPF_R5G6B5 = new DDS_PIXELFORMAT( + 32, DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000); + + public static DDS_PIXELFORMAT DDSPF_A1R5G5B5 = new DDS_PIXELFORMAT( + 32, DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000); + + public static DDS_PIXELFORMAT DDSPF_A4R4G4B4 = new DDS_PIXELFORMAT( + 32, DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000); + + public static DDS_PIXELFORMAT DDSPF_R8G8B8 = new DDS_PIXELFORMAT( + 32, DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000); + + public static DDS_PIXELFORMAT DDSPF_L8 = new DDS_PIXELFORMAT( + 32, DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00); + + public static DDS_PIXELFORMAT DDSPF_L16 = new DDS_PIXELFORMAT( + 32, DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000); + + public static DDS_PIXELFORMAT DDSPF_A8L8 = new DDS_PIXELFORMAT( + 32, DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00); + + public static DDS_PIXELFORMAT DDSPF_A8 = new DDS_PIXELFORMAT( + 32, DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff); + + // D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue + + // This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) + public static DDS_PIXELFORMAT DDSPF_DX10 = new DDS_PIXELFORMAT( + 32, DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0); + + + }; + + public enum DDS_FLAGS : uint + { + DDS_FLAGS_NONE = 0x0, + + DDS_FLAGS_LEGACY_DWORD = 0x1, + // Assume pitch is DWORD aligned instead of BYTE aligned (used by some legacy DDS files) + + DDS_FLAGS_NO_LEGACY_EXPANSION = 0x2, + // Do not implicitly convert legacy formats that result in larger pixel sizes (24 bpp, 3:3:2, A8L8, A4L4, P8, A8P8) + + DDS_FLAGS_NO_R10B10G10A2_FIXUP = 0x4, + // Do not use work-around for long-standing D3DX DDS file format issue which reversed the 10:10:10:2 color order masks + + DDS_FLAGS_FORCE_RGB = 0x8, + // Convert DXGI 1.1 BGR formats to DXGI_FORMAT_R8G8B8A8_UNORM to avoid use of optional WDDM 1.1 formats + + DDS_FLAGS_NO_16BPP = 0x10, + // Conversions avoid use of 565, 5551, and 4444 formats and instead expand to 8888 to avoid use of optional WDDM 1.2 formats + + DDS_FLAGS_EXPAND_LUMINANCE = 0x20, + // When loading legacy luminance formats expand replicating the color channels rather than leaving them packed (L8, L16, A8L8) + + DDS_FLAGS_FORCE_DX10_EXT = 0x10000, + // Always use the 'DX10' header extension for DDS writer (i.e. don't try to write DX9 compatible DDS files) + + DDS_FLAGS_FORCE_DX10_EXT_MISC2 = 0x20000, + // DDS_FLAGS_FORCE_DX10_EXT including miscFlags2 information (result may not be compatible with D3DX10 or D3DX11) + }; + + + + + + + + + + + + + + + + + + + + + + internal static byte[] DecompressDxt1(byte[] imageData, int width, int height) + { + using (MemoryStream imageStream = new MemoryStream(imageData)) + return DecompressDxt1(imageStream, width, height); + } + + internal static byte[] DecompressDxt1(Stream imageStream, int width, int height) + { + byte[] imageData = new byte[width * height * 4]; + + using (BinaryReader imageReader = new BinaryReader(imageStream)) + { + int blockCountX = (width + 3) / 4; + int blockCountY = (height + 3) / 4; + + for (int y = 0; y < blockCountY; y++) + { + for (int x = 0; x < blockCountX; x++) + { + DecompressDxt1Block(imageReader, x, y, blockCountX, width, height, imageData); + } + } + } + + return imageData; + } + + private static void DecompressDxt1Block(BinaryReader imageReader, int x, int y, int blockCountX, int width, int height, byte[] imageData) + { + ushort c0 = imageReader.ReadUInt16(); + ushort c1 = imageReader.ReadUInt16(); + + byte r0, g0, b0; + byte r1, g1, b1; + ConvertRgb565ToRgb888(c0, out r0, out g0, out b0); + ConvertRgb565ToRgb888(c1, out r1, out g1, out b1); + + uint lookupTable = imageReader.ReadUInt32(); + + for (int blockY = 0; blockY < 4; blockY++) + { + for (int blockX = 0; blockX < 4; blockX++) + { + byte r = 0, g = 0, b = 0, a = 255; + uint index = (lookupTable >> 2 * (4 * blockY + blockX)) & 0x03; + + if (c0 > c1) + { + switch (index) + { + case 0: + r = r0; + g = g0; + b = b0; + break; + case 1: + r = r1; + g = g1; + b = b1; + break; + case 2: + r = (byte)((2 * r0 + r1) / 3); + g = (byte)((2 * g0 + g1) / 3); + b = (byte)((2 * b0 + b1) / 3); + break; + case 3: + r = (byte)((r0 + 2 * r1) / 3); + g = (byte)((g0 + 2 * g1) / 3); + b = (byte)((b0 + 2 * b1) / 3); + break; + } + } + else + { + switch (index) + { + case 0: + r = r0; + g = g0; + b = b0; + break; + case 1: + r = r1; + g = g1; + b = b1; + break; + case 2: + r = (byte)((r0 + r1) / 2); + g = (byte)((g0 + g1) / 2); + b = (byte)((b0 + b1) / 2); + break; + case 3: + r = 0; + g = 0; + b = 0; + a = 0; + break; + } + } + + int px = (x << 2) + blockX; + int py = (y << 2) + blockY; + if ((px < width) && (py < height)) + { + int offset = ((py * width) + px) << 2; + imageData[offset] = r; + imageData[offset + 1] = g; + imageData[offset + 2] = b; + imageData[offset + 3] = a; + } + } + } + } + + + internal static byte[] DecompressDxt3(byte[] imageData, int width, int height) + { + using (MemoryStream imageStream = new MemoryStream(imageData)) + return DecompressDxt3(imageStream, width, height); + } + + internal static byte[] DecompressDxt3(Stream imageStream, int width, int height) + { + byte[] imageData = new byte[width * height * 4]; + + using (BinaryReader imageReader = new BinaryReader(imageStream)) + { + int blockCountX = (width + 3) / 4; + int blockCountY = (height + 3) / 4; + + for (int y = 0; y < blockCountY; y++) + { + for (int x = 0; x < blockCountX; x++) + { + DecompressDxt3Block(imageReader, x, y, blockCountX, width, height, imageData); + } + } + } + + return imageData; + } + + private static void DecompressDxt3Block(BinaryReader imageReader, int x, int y, int blockCountX, int width, int height, byte[] imageData) + { + byte a0 = imageReader.ReadByte(); + byte a1 = imageReader.ReadByte(); + byte a2 = imageReader.ReadByte(); + byte a3 = imageReader.ReadByte(); + byte a4 = imageReader.ReadByte(); + byte a5 = imageReader.ReadByte(); + byte a6 = imageReader.ReadByte(); + byte a7 = imageReader.ReadByte(); + + ushort c0 = imageReader.ReadUInt16(); + ushort c1 = imageReader.ReadUInt16(); + + byte r0, g0, b0; + byte r1, g1, b1; + ConvertRgb565ToRgb888(c0, out r0, out g0, out b0); + ConvertRgb565ToRgb888(c1, out r1, out g1, out b1); + + uint lookupTable = imageReader.ReadUInt32(); + + int alphaIndex = 0; + for (int blockY = 0; blockY < 4; blockY++) + { + for (int blockX = 0; blockX < 4; blockX++) + { + byte r = 0, g = 0, b = 0, a = 0; + + uint index = (lookupTable >> 2 * (4 * blockY + blockX)) & 0x03; + + switch (alphaIndex) + { + case 0: + a = (byte)((a0 & 0x0F) | ((a0 & 0x0F) << 4)); + break; + case 1: + a = (byte)((a0 & 0xF0) | ((a0 & 0xF0) >> 4)); + break; + case 2: + a = (byte)((a1 & 0x0F) | ((a1 & 0x0F) << 4)); + break; + case 3: + a = (byte)((a1 & 0xF0) | ((a1 & 0xF0) >> 4)); + break; + case 4: + a = (byte)((a2 & 0x0F) | ((a2 & 0x0F) << 4)); + break; + case 5: + a = (byte)((a2 & 0xF0) | ((a2 & 0xF0) >> 4)); + break; + case 6: + a = (byte)((a3 & 0x0F) | ((a3 & 0x0F) << 4)); + break; + case 7: + a = (byte)((a3 & 0xF0) | ((a3 & 0xF0) >> 4)); + break; + case 8: + a = (byte)((a4 & 0x0F) | ((a4 & 0x0F) << 4)); + break; + case 9: + a = (byte)((a4 & 0xF0) | ((a4 & 0xF0) >> 4)); + break; + case 10: + a = (byte)((a5 & 0x0F) | ((a5 & 0x0F) << 4)); + break; + case 11: + a = (byte)((a5 & 0xF0) | ((a5 & 0xF0) >> 4)); + break; + case 12: + a = (byte)((a6 & 0x0F) | ((a6 & 0x0F) << 4)); + break; + case 13: + a = (byte)((a6 & 0xF0) | ((a6 & 0xF0) >> 4)); + break; + case 14: + a = (byte)((a7 & 0x0F) | ((a7 & 0x0F) << 4)); + break; + case 15: + a = (byte)((a7 & 0xF0) | ((a7 & 0xF0) >> 4)); + break; + } + ++alphaIndex; + + switch (index) + { + case 0: + r = r0; + g = g0; + b = b0; + break; + case 1: + r = r1; + g = g1; + b = b1; + break; + case 2: + r = (byte)((2 * r0 + r1) / 3); + g = (byte)((2 * g0 + g1) / 3); + b = (byte)((2 * b0 + b1) / 3); + break; + case 3: + r = (byte)((r0 + 2 * r1) / 3); + g = (byte)((g0 + 2 * g1) / 3); + b = (byte)((b0 + 2 * b1) / 3); + break; + } + + int px = (x << 2) + blockX; + int py = (y << 2) + blockY; + if ((px < width) && (py < height)) + { + int offset = ((py * width) + px) << 2; + imageData[offset] = r; + imageData[offset + 1] = g; + imageData[offset + 2] = b; + imageData[offset + 3] = a; + } + } + } + } + + + internal static byte[] DecompressDxt5(byte[] imageData, int width, int height) + { + using (MemoryStream imageStream = new MemoryStream(imageData)) + return DecompressDxt5(imageStream, width, height); + } + + internal static byte[] DecompressDxt5(Stream imageStream, int width, int height) + { + byte[] imageData = new byte[width * height * 4]; + + using (BinaryReader imageReader = new BinaryReader(imageStream)) + { + int blockCountX = (width + 3) / 4; + int blockCountY = (height + 3) / 4; + + for (int y = 0; y < blockCountY; y++) + { + for (int x = 0; x < blockCountX; x++) + { + DecompressDxt5Block(imageReader, x, y, blockCountX, width, height, imageData); + } + } + } + + return imageData; + } + + private static void DecompressDxt5Block(BinaryReader imageReader, int x, int y, int blockCountX, int width, int height, byte[] imageData) + { + byte alpha0 = imageReader.ReadByte(); + byte alpha1 = imageReader.ReadByte(); + + ulong alphaMask = (ulong)imageReader.ReadByte(); + alphaMask += (ulong)imageReader.ReadByte() << 8; + alphaMask += (ulong)imageReader.ReadByte() << 16; + alphaMask += (ulong)imageReader.ReadByte() << 24; + alphaMask += (ulong)imageReader.ReadByte() << 32; + alphaMask += (ulong)imageReader.ReadByte() << 40; + + ushort c0 = imageReader.ReadUInt16(); + ushort c1 = imageReader.ReadUInt16(); + + byte r0, g0, b0; + byte r1, g1, b1; + ConvertRgb565ToRgb888(c0, out r0, out g0, out b0); + ConvertRgb565ToRgb888(c1, out r1, out g1, out b1); + + uint lookupTable = imageReader.ReadUInt32(); + + for (int blockY = 0; blockY < 4; blockY++) + { + for (int blockX = 0; blockX < 4; blockX++) + { + byte r = 0, g = 0, b = 0, a = 255; + uint index = (lookupTable >> 2 * (4 * blockY + blockX)) & 0x03; + + uint alphaIndex = (uint)((alphaMask >> 3 * (4 * blockY + blockX)) & 0x07); + if (alphaIndex == 0) + { + a = alpha0; + } + else if (alphaIndex == 1) + { + a = alpha1; + } + else if (alpha0 > alpha1) + { + a = (byte)(((8 - alphaIndex) * alpha0 + (alphaIndex - 1) * alpha1) / 7); + } + else if (alphaIndex == 6) + { + a = 0; + } + else if (alphaIndex == 7) + { + a = 0xff; + } + else + { + a = (byte)(((6 - alphaIndex) * alpha0 + (alphaIndex - 1) * alpha1) / 5); + } + + switch (index) + { + case 0: + r = r0; + g = g0; + b = b0; + break; + case 1: + r = r1; + g = g1; + b = b1; + break; + case 2: + r = (byte)((2 * r0 + r1) / 3); + g = (byte)((2 * g0 + g1) / 3); + b = (byte)((2 * b0 + b1) / 3); + break; + case 3: + r = (byte)((r0 + 2 * r1) / 3); + g = (byte)((g0 + 2 * g1) / 3); + b = (byte)((b0 + 2 * b1) / 3); + break; + } + + int px = (x << 2) + blockX; + int py = (y << 2) + blockY; + if ((px < width) && (py < height)) + { + int offset = ((py * width) + px) << 2; + imageData[offset] = r; + imageData[offset + 1] = g; + imageData[offset + 2] = b; + imageData[offset + 3] = a; + } + } + } + } + + private static void ConvertRgb565ToRgb888(ushort color, out byte r, out byte g, out byte b) + { + int temp; + temp = (color >> 11) * 255 + 16; + r = (byte)((temp / 32 + temp) / 32); + temp = ((color & 0x07E0) >> 5) * 255 + 32; + g = (byte)((temp / 64 + temp) / 64); + temp = (color & 0x001F) * 255 + 16; + b = (byte)((temp / 32 + temp) / 32); + } + + private static void ConvertBgra5551ToRgba8(ushort color, out byte r, out byte g, out byte b, out byte a) + { + //added by dexy + int temp; + temp = ((color >> 11) & 0x1F) * 255 + 16; + r = (byte)((temp / 32 + temp) / 32); + temp = ((color >> 6) & 0x1F) * 255 + 32; + g = (byte)((temp / 32 + temp) / 32); + temp = ((color >> 1) & 0x1F) * 255 + 16; + b = (byte)((temp / 32 + temp) / 32); + a = (byte)((color & 1) * 255); + } + + + + + //these ones added by dexy - based on DecompressDxt + + internal static byte[] DecompressBC4(byte[] imageData, int width, int height) + { + using (MemoryStream imageStream = new MemoryStream(imageData)) + return DecompressBC4(imageStream, width, height); + } + + internal static byte[] DecompressBC4(Stream imageStream, int width, int height) + { + byte[] imageData = new byte[width * height * 4]; + + using (BinaryReader imageReader = new BinaryReader(imageStream)) + { + int blockCountX = (width + 3) / 4; + int blockCountY = (height + 3) / 4; + + for (int y = 0; y < blockCountY; y++) + { + for (int x = 0; x < blockCountX; x++) + { + DecompressBC4Block(imageReader, x, y, blockCountX, width, height, imageData); + } + } + } + + return imageData; + } + + private static void DecompressBC4Block(BinaryReader imageReader, int x, int y, int blockCountX, int width, int height, byte[] imageData) + { + byte r0 = imageReader.ReadByte(); + byte r1 = imageReader.ReadByte(); + + ulong rMask = (ulong)imageReader.ReadByte(); + rMask += (ulong)imageReader.ReadByte() << 8; + rMask += (ulong)imageReader.ReadByte() << 16; + rMask += (ulong)imageReader.ReadByte() << 24; + rMask += (ulong)imageReader.ReadByte() << 32; + rMask += (ulong)imageReader.ReadByte() << 40; + + for (int blockY = 0; blockY < 4; blockY++) + { + for (int blockX = 0; blockX < 4; blockX++) + { + byte r = 255; + + uint rIndex = (uint)((rMask >> 3 * (4 * blockY + blockX)) & 0x07); + if (rIndex == 0) + { + r = r0; + } + else if (rIndex == 1) + { + r = r1; + } + else if (r0 > r1) + { + r = (byte)(((8 - rIndex) * r0 + (rIndex - 1) * r1) / 7); + } + else if (rIndex == 6) + { + r = 0; + } + else if (rIndex == 7) + { + r = 0xff; + } + else + { + r = (byte)(((6 - rIndex) * r0 + (rIndex - 1) * r1) / 5); + } + + int px = (x << 2) + blockX; + int py = (y << 2) + blockY; + if ((px < width) && (py < height)) + { + int offset = ((py * width) + px) << 2; + imageData[offset] = r; + imageData[offset + 1] = 0; + imageData[offset + 2] = 0; + imageData[offset + 3] = 255; + } + } + } + } + + + internal static byte[] DecompressBC5(byte[] imageData, int width, int height) + { + using (MemoryStream imageStream = new MemoryStream(imageData)) + return DecompressBC5(imageStream, width, height); + } + + internal static byte[] DecompressBC5(Stream imageStream, int width, int height) + { + byte[] imageData = new byte[width * height * 4]; + + using (BinaryReader imageReader = new BinaryReader(imageStream)) + { + int blockCountX = (width + 3) / 4; + int blockCountY = (height + 3) / 4; + + for (int y = 0; y < blockCountY; y++) + { + for (int x = 0; x < blockCountX; x++) + { + DecompressBC5Block(imageReader, x, y, blockCountX, width, height, imageData); + } + } + } + + return imageData; + } + + private static void DecompressBC5Block(BinaryReader imageReader, int x, int y, int blockCountX, int width, int height, byte[] imageData) + { + byte r0 = imageReader.ReadByte(); + byte r1 = imageReader.ReadByte(); + + ulong rMask = (ulong)imageReader.ReadByte(); + rMask += (ulong)imageReader.ReadByte() << 8; + rMask += (ulong)imageReader.ReadByte() << 16; + rMask += (ulong)imageReader.ReadByte() << 24; + rMask += (ulong)imageReader.ReadByte() << 32; + rMask += (ulong)imageReader.ReadByte() << 40; + + byte g0 = imageReader.ReadByte(); + byte g1 = imageReader.ReadByte(); + + ulong gMask = (ulong)imageReader.ReadByte(); + gMask += (ulong)imageReader.ReadByte() << 8; + gMask += (ulong)imageReader.ReadByte() << 16; + gMask += (ulong)imageReader.ReadByte() << 24; + gMask += (ulong)imageReader.ReadByte() << 32; + gMask += (ulong)imageReader.ReadByte() << 40; + + for (int blockY = 0; blockY < 4; blockY++) + { + for (int blockX = 0; blockX < 4; blockX++) + { + byte r = 255; + uint rIndex = (uint)((rMask >> 3 * (4 * blockY + blockX)) & 0x07); + if (rIndex == 0) + { + r = r0; + } + else if (rIndex == 1) + { + r = r1; + } + else if (r0 > r1) + { + r = (byte)(((8 - rIndex) * r0 + (rIndex - 1) * r1) / 7); + } + else if (rIndex == 6) + { + r = 0; + } + else if (rIndex == 7) + { + r = 0xff; + } + else + { + r = (byte)(((6 - rIndex) * r0 + (rIndex - 1) * r1) / 5); + } + + + byte g = 255; + uint gIndex = (uint)((gMask >> 3 * (4 * blockY + blockX)) & 0x07); + if (gIndex == 0) + { + r = r0; + } + else if (gIndex == 1) + { + r = r1; + } + else if (r0 > r1) + { + r = (byte)(((8 - gIndex) * r0 + (gIndex - 1) * r1) / 7); + } + else if (gIndex == 6) + { + r = 0; + } + else if (gIndex == 7) + { + r = 0xff; + } + else + { + r = (byte)(((6 - gIndex) * r0 + (gIndex - 1) * r1) / 5); + } + + + int px = (x << 2) + blockX; + int py = (y << 2) + blockY; + if ((px < width) && (py < height)) + { + int offset = ((py * width) + px) << 2; + imageData[offset] = r; + imageData[offset + 1] = g; + imageData[offset + 2] = 0; + imageData[offset + 3] = 255; + } + } + } + } + + + + private static byte[] ConvertA8ToRGBA8(byte[] imgdata, int w, int h) + { + var px = new byte[w * h * 4]; + var pxmax = px.Length - 3; + for (int i = 0; i < imgdata.Length; i++) + { + byte av = imgdata[i]; + int pxi = i * 4; + if (pxi < pxmax) + { + px[pxi] = av; + px[pxi + 1] = av; + px[pxi + 2] = av; + px[pxi + 3] = 255; + } + } + return px; + } + private static byte[] ConvertR8ToRGBA8(byte[] imgdata, int w, int h) + { + var px = new byte[w * h * 4]; + var pxmax = px.Length - 3; + for (int i = 0; i < imgdata.Length; i++) + { + byte av = imgdata[i]; + int pxi = i * 4; + if (pxi < pxmax) + { + px[pxi] = av; + px[pxi + 1] = 0; + px[pxi + 2] = 0; + px[pxi + 3] = 255; + } + } + return px; + } + private static byte[] ConvertBGR5A1ToRGBA8(byte[] imgdata, int w, int h) + { + var px = new byte[w * h * 4]; + var pxmax = px.Length - 3; + for (int i = 0; i < imgdata.Length; i+=2) + { + byte v0 = imgdata[i]; + byte v1 = imgdata[i + 1]; + ushort vu = (ushort)(v1 * 255 + v0); + int pxi = i * 4; + if (pxi < pxmax) + { + ConvertBgra5551ToRgba8(vu, out px[pxi], out px[pxi + 1], out px[pxi + 2], out px[pxi + 3]); + } + } + return px; + } + + } +} diff --git a/Utils/Matrices.cs b/Utils/Matrices.cs new file mode 100644 index 0000000..f259b6f --- /dev/null +++ b/Utils/Matrices.cs @@ -0,0 +1,42 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker +{ + public static class MatrixExtensions + { + + public static Vector3 MultiplyW(this Matrix m, Vector3 v) + { + float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41; + float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42; + float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43; + float w = (((m.M14 * v.X) + (m.M24 * v.Y)) + (m.M34 * v.Z)) + m.M44; + float iw = 1.0f / Math.Abs(w); + return new Vector3(x * iw, y * iw, z * iw); + } + public static Vector3 Multiply(this Matrix m, Vector3 v) + { + float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41; + float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42; + float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43; + return new Vector3(x, y, z); + //this quick mul ignores W... + } + + public static Vector4 Multiply(this Matrix m, Vector4 v) + { + float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41; + float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42; + float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43; + float w = (((m.M14 * v.X) + (m.M24 * v.Y)) + (m.M34 * v.Z)) + m.M44; + return new Vector4(x, y, z, w); + } + + + } +} diff --git a/Utils/Quaternions.cs b/Utils/Quaternions.cs new file mode 100644 index 0000000..2fa924d --- /dev/null +++ b/Utils/Quaternions.cs @@ -0,0 +1,74 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker +{ + + + + public static class QuaternionExtension + { + public static Vector3 Multiply(this Quaternion a, Vector3 b) + { + float axx = a.X * 2.0f; + float ayy = a.Y * 2.0f; + float azz = a.Z * 2.0f; + float awxx = a.W * axx; + float awyy = a.W * ayy; + float awzz = a.W * azz; + float axxx = a.X * axx; + float axyy = a.X * ayy; + float axzz = a.X * azz; + float ayyy = a.Y * ayy; + float ayzz = a.Y * azz; + float azzz = a.Z * azz; + return new Vector3(((b.X * ((1.0f - ayyy) - azzz)) + (b.Y * (axyy - awzz))) + (b.Z * (axzz + awyy)), + ((b.X * (axyy + awzz)) + (b.Y * ((1.0f - axxx) - azzz))) + (b.Z * (ayzz - awxx)), + ((b.X * (axzz - awyy)) + (b.Y * (ayzz + awxx))) + (b.Z * ((1.0f - axxx) - ayyy))); + } + + public static Matrix ToMatrix(this Quaternion q) + { + float xx = q.X * q.X; + float yy = q.Y * q.Y; + float zz = q.Z * q.Z; + float xy = q.X * q.Y; + float zw = q.Z * q.W; + float zx = q.Z * q.X; + float yw = q.Y * q.W; + float yz = q.Y * q.Z; + float xw = q.X * q.W; + Matrix result = new Matrix(); + result.M11 = 1.0f - (2.0f * (yy + zz)); + result.M12 = 2.0f * (xy + zw); + result.M13 = 2.0f * (zx - yw); + result.M14 = 0.0f; + result.M21 = 2.0f * (xy - zw); + result.M22 = 1.0f - (2.0f * (zz + xx)); + result.M23 = 2.0f * (yz + xw); + result.M24 = 0.0f; + result.M31 = 2.0f * (zx + yw); + result.M32 = 2.0f * (yz - xw); + result.M33 = 1.0f - (2.0f * (yy + xx)); + result.M34 = 0.0f; + result.M41 = 0.0f; + result.M42 = 0.0f; + result.M43 = 0.0f; + result.M44 = 1.0f; + return result; + } + + public static Vector4 ToVector4(this Quaternion q) + { + return new Vector4(q.X, q.Y, q.Z, q.W); + } + + } + + + +} diff --git a/Utils/TextureLoader.cs b/Utils/TextureLoader.cs new file mode 100644 index 0000000..e5ceb9b --- /dev/null +++ b/Utils/TextureLoader.cs @@ -0,0 +1,186 @@ +using SharpDX; +using SharpDX.Direct3D11; +using SharpDX.WIC; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.Utils +{ + public class TextureLoader + { + /// + /// Loads a bitmap using WIC. + /// + /// + /// + /// + public static BitmapSource LoadBitmap(ImagingFactory2 factory, string filename) + { + var bitmapDecoder = new BitmapDecoder( + factory, + filename, + DecodeOptions.CacheOnDemand + ); + + var formatConverter = new FormatConverter(factory); + + formatConverter.Initialize( + bitmapDecoder.GetFrame(0), + PixelFormat.Format32bppPRGBA, + BitmapDitherType.None, + null, + 0.0, + BitmapPaletteType.Custom); + + return formatConverter; + } + + /// + /// Creates a from a WIC + /// + /// The Direct3D11 device + /// The WIC bitmap source + /// A Texture2D + public static SharpDX.Direct3D11.Texture2D CreateTexture2DFromBitmap(Device device, SharpDX.WIC.BitmapSource bitmapSource) + { + // Allocate DataStream to receive the WIC image pixels + int stride = bitmapSource.Size.Width * 4; + using (var buffer = new SharpDX.DataStream(bitmapSource.Size.Height * stride, true, true)) + { + // Copy the content of the WIC to the buffer + bitmapSource.CopyPixels(stride, buffer); + return new Texture2D(device, new Texture2DDescription() + { + Width = bitmapSource.Size.Width, + Height = bitmapSource.Size.Height, + ArraySize = 1, + BindFlags = BindFlags.ShaderResource, + Usage = ResourceUsage.Immutable, + CpuAccessFlags = CpuAccessFlags.None, + Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm, + MipLevels = 1, + OptionFlags = ResourceOptionFlags.None, + SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), + }, new SharpDX.DataRectangle(buffer.DataPointer, stride)); + } + } + + + + //create a bitmap from a texture2D. DOES NOT WORK + public static System.Drawing.Bitmap GetTextureBitmap(Device device, Texture2D tex, int mipSlice) + { + int w = tex.Description.Width; + int h = tex.Description.Height; + + var textureCopy = new Texture2D(device, new Texture2DDescription + { + Width = w, + Height = h, + MipLevels = tex.Description.MipLevels, + ArraySize = 1, + Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm, + Usage = ResourceUsage.Staging, + SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), + BindFlags = BindFlags.None, + CpuAccessFlags = CpuAccessFlags.Read, + OptionFlags = ResourceOptionFlags.None + }); + DataStream dataStream;// = new DataStream(8 * tex.Description.Width * tex.Description.Height, true, true); + + DeviceContext context = device.ImmediateContext; + + //context.CopyResource(tex, textureCopy); + context.CopySubresourceRegion(tex, mipSlice, null, textureCopy, 0); + + + var dataBox = context.MapSubresource( + textureCopy, + mipSlice, + 0, + MapMode.Read, + SharpDX.Direct3D11.MapFlags.None, + out dataStream); + + //int bytesize = w * h * 4; + //byte[] pixels = new byte[bytesize]; + //dataStream.Read(pixels, 0, bytesize); + //dataStream.Position = 0; + + var dataRectangle = new DataRectangle + { + DataPointer = dataStream.DataPointer, + Pitch = dataBox.RowPitch + }; + + + ImagingFactory wicf = new ImagingFactory(); + + var b = new SharpDX.WIC.Bitmap(wicf, w, h, SharpDX.WIC.PixelFormat.Format32bppBGRA, dataRectangle); + + + var s = new MemoryStream(); + using (var bitmapEncoder = new PngBitmapEncoder(wicf, s)) + { + using (var bitmapFrameEncode = new BitmapFrameEncode(bitmapEncoder)) + { + bitmapFrameEncode.Initialize(); + bitmapFrameEncode.SetSize(b.Size.Width, b.Size.Height); + var pixelFormat = PixelFormat.FormatDontCare; + bitmapFrameEncode.SetPixelFormat(ref pixelFormat); + bitmapFrameEncode.WriteSource(b); + bitmapFrameEncode.Commit(); + bitmapEncoder.Commit(); + } + } + + context.UnmapSubresource(textureCopy, 0); + textureCopy.Dispose(); + b.Dispose(); + + + + s.Position = 0; + var bmp = new System.Drawing.Bitmap(s); + + + + //Palette pal = new Palette(wf); + //b.CopyPalette(pal); + + //byte[] pixels = new byte[w * h * 4]; + //b.CopyPixels(pixels, w * 4); + //GCHandle handle = GCHandle.Alloc(pixels, GCHandleType.Pinned); + //var hptr = handle.AddrOfPinnedObject(); + //System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(w, h, w * 4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, hptr); + //handle.Free(); + + //System.Threading.Thread.Sleep(1000); + + //System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); + //System.Drawing.Imaging.BitmapData data = bmp.LockBits( + // new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), + // System.Drawing.Imaging.ImageLockMode.WriteOnly, + // System.Drawing.Imaging.PixelFormat.Format32bppPArgb); + ////b.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride); + //b.CopyPixels(data.Stride, data.Scan0, data.Height * data.Stride); + //bmp.UnlockBits(data); + + + var c1 = bmp.GetPixel(10, 2); + + + //dataStream.Dispose(); + + + return bmp; + } + + + } +} diff --git a/Utils/Utils.cs b/Utils/Utils.cs new file mode 100644 index 0000000..cfe41ec --- /dev/null +++ b/Utils/Utils.cs @@ -0,0 +1,448 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Globalization; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Point = System.Drawing.Point; + +namespace CodeWalker +{ + ////public static class Utils + ////{ + + + + //// //unused + //// //public static Bitmap ResizeImage(Image image, int width, int height) + //// //{ + //// // var destRect = new Rectangle(0, 0, width, height); + //// // var destImage = new Bitmap(width, height); + //// // destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); + //// // using (var graphics = Graphics.FromImage(destImage)) + //// // { + //// // graphics.CompositingMode = CompositingMode.SourceCopy; + //// // graphics.CompositingQuality = CompositingQuality.HighQuality; + //// // graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + //// // graphics.SmoothingMode = SmoothingMode.HighQuality; + //// // graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + //// // using (var wrapMode = new ImageAttributes()) + //// // { + //// // wrapMode.SetWrapMode(WrapMode.TileFlipXY); + //// // graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode); + //// // } + //// // } + //// // return destImage; + //// //} + + + ////} + + + + [EditorBrowsable(EditorBrowsableState.Never)] + public static class ListViewExtensions + { + //from stackoverflow: + //https://stackoverflow.com/questions/254129/how-to-i-display-a-sort-arrow-in-the-header-of-a-list-view-column-using-c + + [StructLayout(LayoutKind.Sequential)] + public struct HDITEM + { + public Mask mask; + public int cxy; + [MarshalAs(UnmanagedType.LPTStr)] public string pszText; + public IntPtr hbm; + public int cchTextMax; + public Format fmt; + public IntPtr lParam; + // _WIN32_IE >= 0x0300 + public int iImage; + public int iOrder; + // _WIN32_IE >= 0x0500 + public uint type; + public IntPtr pvFilter; + // _WIN32_WINNT >= 0x0600 + public uint state; + + [Flags] + public enum Mask + { + Format = 0x4, // HDI_FORMAT + }; + + [Flags] + public enum Format + { + SortDown = 0x200, // HDF_SORTDOWN + SortUp = 0x400, // HDF_SORTUP + }; + }; + + public const int LVM_FIRST = 0x1000; + public const int LVM_GETHEADER = LVM_FIRST + 31; + + public const int HDM_FIRST = 0x1200; + public const int HDM_GETITEM = HDM_FIRST + 11; + public const int HDM_SETITEM = HDM_FIRST + 12; + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref HDITEM lParam); + + public static void SetSortIcon(this ListView listViewControl, int columnIndex, SortOrder order) + { + IntPtr columnHeader = SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero); + for (int columnNumber = 0; columnNumber <= listViewControl.Columns.Count - 1; columnNumber++) + { + var columnPtr = new IntPtr(columnNumber); + var item = new HDITEM + { + mask = HDITEM.Mask.Format + }; + + if (SendMessage(columnHeader, HDM_GETITEM, columnPtr, ref item) == IntPtr.Zero) + { + throw new Win32Exception(); + } + + if (order != SortOrder.None && columnNumber == columnIndex) + { + switch (order) + { + case SortOrder.Ascending: + item.fmt &= ~HDITEM.Format.SortDown; + item.fmt |= HDITEM.Format.SortUp; + break; + case SortOrder.Descending: + item.fmt &= ~HDITEM.Format.SortUp; + item.fmt |= HDITEM.Format.SortDown; + break; + } + } + else + { + item.fmt &= ~HDITEM.Format.SortDown & ~HDITEM.Format.SortUp; + } + + if (SendMessage(columnHeader, HDM_SETITEM, columnPtr, ref item) == IntPtr.Zero) + { + throw new Win32Exception(); + } + } + } + + + + + + + + + + + + //private const int LVM_FIRST = 0x1000; + private const int LVM_SETITEMSTATE = LVM_FIRST + 43; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct LVITEM + { + public int mask; + public int iItem; + public int iSubItem; + public int state; + public int stateMask; + [MarshalAs(UnmanagedType.LPTStr)] + public string pszText; + public int cchTextMax; + public int iImage; + public IntPtr lParam; + public int iIndent; + public int iGroupId; + public int cColumns; + public IntPtr puColumns; + }; + + [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)] + public static extern IntPtr SendMessageLVItem(IntPtr hWnd, int msg, int wParam, ref LVITEM lvi); + + /// + /// Select all rows on the given listview + /// + /// The listview whose items are to be selected + public static void SelectAllItems(this ListView list) + { + SetItemState(list, -1, 2, 2); + } + + /// + /// Deselect all rows on the given listview + /// + /// The listview whose items are to be deselected + public static void DeselectAllItems(this ListView list) + { + SetItemState(list, -1, 2, 0); + } + + /// + /// Set the item state on the given item + /// + /// The listview whose item's state is to be changed + /// The index of the item to be changed + /// Which bits of the value are to be set? + /// The value to be set + public static void SetItemState(ListView list, int itemIndex, int mask, int value) + { + LVITEM lvItem = new LVITEM(); + lvItem.stateMask = mask; + lvItem.state = value; + SendMessageLVItem(list.Handle, LVM_SETITEMSTATE, itemIndex, ref lvItem); + } + + + } + + + public static class TextBoxExtension + { + private const int EM_SETTABSTOPS = 0x00CB; + + [DllImport("User32.dll", CharSet = CharSet.Auto)] + private static extern IntPtr SendMessage(IntPtr h, int msg, int wParam, int[] lParam); + + public static Point GetCaretPosition(this TextBox textBox) + { + Point point = new Point(0, 0); + + if (textBox.Focused) + { + point.X = textBox.SelectionStart - textBox.GetFirstCharIndexOfCurrentLine() + 1; + point.Y = textBox.GetLineFromCharIndex(textBox.SelectionStart) + 1; + } + + return point; + } + + public static void SetTabStopWidth(this TextBox textbox, int width) + { + SendMessage(textbox.Handle, EM_SETTABSTOPS, 1, new int[] { width * 4 }); + } + } + + + + public static class TextUtil + { + + public static string GetBytesReadable(long i) + { + //shamelessly stolen from stackoverflow, and a bit mangled + + // Returns the human-readable file size for an arbitrary, 64-bit file size + // The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB" + // Get absolute value + long absolute_i = (i < 0 ? -i : i); + // Determine the suffix and readable value + string suffix; + double readable; + if (absolute_i >= 0x1000000000000000) // Exabyte + { + suffix = "EB"; + readable = (i >> 50); + } + else if (absolute_i >= 0x4000000000000) // Petabyte + { + suffix = "PB"; + readable = (i >> 40); + } + else if (absolute_i >= 0x10000000000) // Terabyte + { + suffix = "TB"; + readable = (i >> 30); + } + else if (absolute_i >= 0x40000000) // Gigabyte + { + suffix = "GB"; + readable = (i >> 20); + } + else if (absolute_i >= 0x100000) // Megabyte + { + suffix = "MB"; + readable = (i >> 10); + } + else if (absolute_i >= 0x400) // Kilobyte + { + suffix = "KB"; + readable = i; + } + else + { + return i.ToString("0 bytes"); // Byte + } + // Divide by 1024 to get fractional value + readable = (readable / 1024); + + string fmt = "0.### "; + if (readable > 1000) + { + fmt = "0"; + } + else if (readable > 100) + { + fmt = "0.#"; + } + else if (readable > 10) + { + fmt = "0.##"; + } + + // Return formatted number with suffix + return readable.ToString(fmt) + suffix; + } + } + + + + public static class FloatUtil + { + public static bool TryParse(string s, out float f) + { + f = 0.0f; + if (float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out f)) + { + return true; + } + return false; + } + public static float Parse(string s) + { + float f; + TryParse(s, out f); + return f; + } + public static string ToString(float f) + { + var c = CultureInfo.InvariantCulture; + return f.ToString(c); + } + + + public static string GetVector2String(Vector2 v) + { + var c = CultureInfo.InvariantCulture; + return v.X.ToString(c) + ", " + v.Y.ToString(c); + } + public static string GetVector3String(Vector3 v) + { + var c = CultureInfo.InvariantCulture; + return v.X.ToString(c) + ", " + v.Y.ToString(c) + ", " + v.Z.ToString(c); + } + public static string GetVector3String(Vector3 v, string format) + { + var c = CultureInfo.InvariantCulture; + return v.X.ToString(format, c) + ", " + v.Y.ToString(format, c) + ", " + v.Z.ToString(format, c); + } + + public static Vector3 ParseVector3String(string s) + { + Vector3 p = new Vector3(0.0f); + string[] ss = s.Split(','); + if (ss.Length > 0) + { + FloatUtil.TryParse(ss[0].Trim(), out p.X); + } + if (ss.Length > 1) + { + FloatUtil.TryParse(ss[1].Trim(), out p.Y); + } + if (ss.Length > 2) + { + FloatUtil.TryParse(ss[2].Trim(), out p.Z); + } + return p; + } + + + + public static string GetVector4String(Vector4 v) + { + var c = CultureInfo.InvariantCulture; + return v.X.ToString(c) + ", " + v.Y.ToString(c) + ", " + v.Z.ToString(c) + ", " + v.W.ToString(c); + } + public static Vector4 ParseVector4String(string s) + { + Vector4 p = new Vector4(0.0f); + string[] ss = s.Split(','); + if (ss.Length > 0) + { + FloatUtil.TryParse(ss[0].Trim(), out p.X); + } + if (ss.Length > 1) + { + FloatUtil.TryParse(ss[1].Trim(), out p.Y); + } + if (ss.Length > 2) + { + FloatUtil.TryParse(ss[2].Trim(), out p.Z); + } + if (ss.Length > 3) + { + FloatUtil.TryParse(ss[3].Trim(), out p.W); + } + return p; + } + + + } + + + + + + //unused + //public class AccurateTimer + //{ + // private delegate void TimerEventDel(int id, int msg, IntPtr user, int dw1, int dw2); + // private const int TIME_PERIODIC = 1; + // private const int EVENT_TYPE = TIME_PERIODIC;// + 0x100; // TIME_KILL_SYNCHRONOUS causes a hang ?! + // [DllImport("winmm.dll")] + // private static extern int timeBeginPeriod(int msec); + // [DllImport("winmm.dll")] + // private static extern int timeEndPeriod(int msec); + // [DllImport("winmm.dll")] + // private static extern int timeSetEvent(int delay, int resolution, TimerEventDel handler, IntPtr user, int eventType); + // [DllImport("winmm.dll")] + // private static extern int timeKillEvent(int id); + // Action mAction; + // Form mForm; + // private int mTimerId; + // private TimerEventDel mHandler; // NOTE: declare at class scope so garbage collector doesn't release it!!! + // public AccurateTimer(Form form, Action action, int delay) + // { + // mAction = action; + // mForm = form; + // timeBeginPeriod(1); + // mHandler = new TimerEventDel(TimerCallback); + // mTimerId = timeSetEvent(delay, 0, mHandler, IntPtr.Zero, EVENT_TYPE); + // } + // public void Stop() + // { + // int err = timeKillEvent(mTimerId); + // timeEndPeriod(1); + // System.Threading.Thread.Sleep(100);// Ensure callbacks are drained + // } + // private void TimerCallback(int id, int msg, IntPtr user, int dw1, int dw2) + // { + // if (mTimerId != 0) mForm.BeginInvoke(mAction); + // } + //} + +} diff --git a/Utils/Vectors.cs b/Utils/Vectors.cs new file mode 100644 index 0000000..e0418f7 --- /dev/null +++ b/Utils/Vectors.cs @@ -0,0 +1,60 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker +{ + public static class Vectors + { + + public static Vector3 XYZ(this Vector4 v) + { + return new Vector3(v.X, v.Y, v.Z); + } + + + public static Vector4 Floor(this Vector4 v) + { + return new Vector4((float)Math.Floor(v.X), (float)Math.Floor(v.Y), (float)Math.Floor(v.Z), (float)Math.Floor(v.W)); + } + + } + + + public struct Vector2I + { + public int X; + public int Y; + + public Vector2I(int x, int y) + { + X = x; + Y = y; + } + public Vector2I(Vector2 v) + { + X = (int)Math.Floor(v.X); + Y = (int)Math.Floor(v.Y); + } + + public override string ToString() + { + return X.ToString() + ", " + Y.ToString(); + } + + + public static Vector2I operator +(Vector2I a, Vector2I b) + { + return new Vector2I(a.X + b.X, a.Y + b.Y); + } + + public static Vector2I operator -(Vector2I a, Vector2I b) + { + return new Vector2I(a.X - b.X, a.Y - b.Y); + } + + } +} \ No newline at end of file diff --git a/Utils/Xml.cs b/Utils/Xml.cs new file mode 100644 index 0000000..77a74ab --- /dev/null +++ b/Utils/Xml.cs @@ -0,0 +1,113 @@ +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker +{ + public static class Xml + { + + public static string GetStringAttribute(XmlNode node, string attribute) + { + if (node == null) return null; + return node.Attributes[attribute]?.InnerText; + } + public static bool GetBoolAttribute(XmlNode node, string attribute) + { + if (node == null) return false; + string val = node.Attributes[attribute]?.InnerText; + bool b; + bool.TryParse(val, out b); + return b; + } + public static int GetIntAttribute(XmlNode node, string attribute) + { + if (node == null) return 0; + string val = node.Attributes[attribute]?.InnerText; + int i; + int.TryParse(val, out i); + return i; + } + public static float GetFloatAttribute(XmlNode node, string attribute) + { + if (node == null) return 0; + string val = node.Attributes[attribute]?.InnerText; + float f; + FloatUtil.TryParse(val, out f); + return f; + } + + public static string GetChildInnerText(XmlNode node, string name) + { + if (node == null) return null; + return node.SelectSingleNode(name)?.InnerText; + } + + public static bool GetChildBoolAttribute(XmlNode node, string name, string attribute) + { + if (node == null) return false; + string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText; + bool b; + bool.TryParse(val, out b); + return b; + } + public static int GetChildIntAttribute(XmlNode node, string name, string attribute) + { + if (node == null) return 0; + string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText; + int i; + int.TryParse(val, out i); + return i; + } + public static float GetChildFloatAttribute(XmlNode node, string name, string attribute) + { + if (node == null) return 0; + string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText; + float f; + FloatUtil.TryParse(val, out f); + return f; + } + public static string GetChildStringAttribute(XmlNode node, string name, string attribute) + { + if (node == null) return string.Empty; + string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText; + return val; + } + public static Vector3 GetChildVector3Attributes(XmlNode node, string name, string x, string y, string z) + { + float fx = GetChildFloatAttribute(node, name, x); + float fy = GetChildFloatAttribute(node, name, y); + float fz = GetChildFloatAttribute(node, name, z); + return new Vector3(fx, fy, fz); + } + + public static XmlElement GetChild(XmlElement element, string name) + { + return element.SelectSingleNode(name) as XmlElement; + } + + public static XmlElement AddChild(XmlDocument doc, XmlNode node, string name) + { + XmlElement child = doc.CreateElement(name); + node.AppendChild(child); + return child; + } + public static XmlElement AddChildWithInnerText(XmlDocument doc, XmlNode node, string name, string innerText) + { + XmlElement child = AddChild(doc, node, name); + child.InnerText = innerText; + return child; + } + public static XmlElement AddChildWithAttribute(XmlDocument doc, XmlNode node, string name, string attributeName, string attributeValue) + { + XmlElement child = AddChild(doc, node, name); + child.SetAttribute(attributeName, attributeValue); + return child; + } + + } +} diff --git a/World/Camera.cs b/World/Camera.cs new file mode 100644 index 0000000..f263509 --- /dev/null +++ b/World/Camera.cs @@ -0,0 +1,364 @@ +using CodeWalker.Properties; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.World +{ + public class Camera + { + public Vector3 TargetRotation = Vector3.Zero; + public Vector3 CurrentRotation = Vector3.Zero; + public float Smoothness = Settings.Default.CameraSmoothing;// 10.0f;//0.15f; + public float Sensitivity = Settings.Default.CameraSensitivity;// 0.005f; + public float TargetDistance = 1.0f; + public float CurrentDistance = 1.0f; + public float ZoomCurrentTime = 0.0f; + public float ZoomTargetTime = 2.0f; + public float ZoomVelocity = 0.0f; + public float ZoomSpeed = 0.1f; + public float Width = 1920.0f; + public float Height = 1080.0f; + public float FieldOfView = Settings.Default.CameraFieldOfView;// 1.0f; + public float FieldOfViewFactor = 0.5f / (float)Math.Tan(/*FieldOfView*/ 1.0f * 0.5f); + public float AspectRatio = 1920.0f / 1080.0f; + public float ZNear = 0.5f; + public float ZFar = 12000.0f; + public Entity FollowEntity = null; + public Vector3 LocalLookAt = Vector3.ForwardLH; + public float VOffset = 0.0f; + public bool UpdateProj = true; + public bool IsMapView = false; + public bool IsOrthographic = false; + public float OrthographicSize = 20.0f; + public float OrthographicTargetSize = 20.0f; + public Matrix ProjMatrix = Matrix.Identity; + public Vector3 Position = Vector3.Zero; + public Vector3 UpDirection = Vector3.Up; + public Vector3 ViewDirection = Vector3.ForwardLH; + public Quaternion ViewQuaternion = Quaternion.Identity; + public Quaternion ViewInvQuaternion = Quaternion.Identity; + public Matrix ViewMatrix = Matrix.Identity; + public Matrix ViewInvMatrix = Matrix.Identity; + public Matrix ViewProjMatrix = Matrix.Identity; + public Matrix ViewProjInvMatrix = Matrix.Identity; + public Frustum ViewFrustum = new Frustum(); + public Vector3 MouseRayNear = Vector3.Zero; + public Vector3 MouseRayFar = Vector3.Zero; + public Ray MouseRay; + private float MouseX = 0; + private float MouseY = 0; + private object syncRoot = new object(); + + + public void SetMousePosition(int x, int y) + { + MouseX = (x / Width) * 2.0f - 1.0f; + MouseY = (y / Height) * -2.0f + 1.0f; + } + + public void SetFollowEntity(Entity e) + { + FollowEntity = e; + } + + public void Update(float elapsed) + { + lock (syncRoot) + { + UpdateFollow(elapsed); + if (UpdateProj) UpdateProjMatrix(); + + //float mx = (LastMouseX / Width) * 2.0f; + //float my = (LastMouseY / Height) * -2.0f; + + ////MousedItem = nullptr; + ////MousedThing = nullptr; + ////MousedItemSpace = nullptr; + + UpdateProjection();//, mx, my); + } + } + private void UpdateFollow(float elapsed) + { + const float ythresh = 1.55f; + const float nythresh = -1.55f; + Vector3 up = Vector3.Up;// new Vector3(0.0f, 1.0f, 0.0f); + if (TargetRotation.Y > ythresh) TargetRotation.Y = ythresh; + if (TargetRotation.Y < nythresh) TargetRotation.Y = nythresh; + float sv = Math.Min(Smoothness * elapsed, 1.0f); + CurrentRotation = CurrentRotation + ((TargetRotation - CurrentRotation) * sv); + + if (TargetDistance > 11000.0f) TargetDistance = 11000.0f; //11km max zoom dist + if (TargetDistance < 0.0001f) TargetDistance = 0.0001f; //0.1mm min zoom dist... + ZoomCurrentTime += elapsed; + if (ZoomCurrentTime > ZoomTargetTime) ZoomCurrentTime = ZoomTargetTime; + float currentTime = ZoomCurrentTime / ZoomTargetTime; + float deltaDist = TargetDistance - CurrentDistance; + if (currentTime < 1.0f && deltaDist > 0.0f) + { + //TODO: when to properly reset ZoomCurrentTime? + float y = currentTime*currentTime*currentTime; //powf(currentTime, 3.0f); + deltaDist *= y; + } + CurrentDistance = CurrentDistance + deltaDist * ZoomSpeed; + + if (IsOrthographic || IsMapView) + { + if (OrthographicTargetSize > 20000.0f) OrthographicTargetSize = 20000.0f; + if (OrthographicTargetSize < 1.0f) OrthographicTargetSize = 1.0f; + OrthographicSize = OrthographicSize + ((OrthographicTargetSize - OrthographicSize) * sv); + UpdateProj = true; + } + + + + + if (IsMapView) + { + //in map view, need a constant view matrix aligned to XY. + + Vector3 cpos = new Vector3(); + if (FollowEntity != null) + { + cpos = FollowEntity.Position; + } + LocalLookAt = Vector3.Zero; + Position = cpos; + //Position.Z = 1000.0f; + ViewDirection = -Vector3.UnitZ; + UpDirection = Vector3.UnitY; + } + else + { + //normal view mode + + Vector3 rdir = new Vector3(); + float cryd = (float)Math.Cos(CurrentRotation.Y); + rdir.X = -(float)Math.Sin(-CurrentRotation.X) * cryd; + rdir.Z = -(float)Math.Cos(-CurrentRotation.X) * cryd; + rdir.Y = (float)Math.Sin(CurrentRotation.Y); + Vector3 lookat = new Vector3(0.0f, VOffset, 0.0f); + Vector3 cpos = new Vector3(); + if (FollowEntity != null) + { + up = FollowEntity.Orientation.Multiply(up); + lookat = FollowEntity.Orientation.Multiply(lookat); + rdir = FollowEntity.Orientation.Multiply(rdir); + cpos = FollowEntity.Position; + } + LocalLookAt = (rdir * CurrentDistance) + lookat; + Position = cpos + LocalLookAt; + ViewDirection = Vector3.Normalize(-rdir); + UpDirection = up; + } + + + //M16FLookAt(LocalProjection.ViewMatrix, V3F(0.0f, 0.0f, 0.0f), LocalProjection.ViewDirection, LocalProjection.UpDirection); + ViewQuaternion = Quaternion.LookAtRH(Vector3.Zero, ViewDirection, UpDirection); + ViewInvQuaternion = Quaternion.Invert(ViewQuaternion); + ViewMatrix = ViewQuaternion.ToMatrix(); + ViewInvMatrix = Matrix.Invert(ViewMatrix); + + } + private void UpdateProjMatrix() + { + if (IsMapView) + { + ProjMatrix = Matrix.OrthoRH(AspectRatio * OrthographicSize, OrthographicSize, 1.0f, 3000.0f); + } + else if (IsOrthographic) + { + ProjMatrix = Matrix.OrthoRH(AspectRatio * OrthographicSize, OrthographicSize, ZNear, ZFar); + } + else + { + ProjMatrix = Matrix.PerspectiveFovRH(FieldOfView, AspectRatio, ZNear, ZFar); + } + //ProjMatrix._33/=ZFar; + //ProjMatrix._43/=ZFar; + UpdateProj = false; + } + private void UpdateProjection() //CameraSpaceProjection& p, float mx, float my) + { + float mx = MouseX; + float my = MouseY; + ViewProjMatrix = Matrix.Multiply(ViewMatrix, ProjMatrix); + ViewProjInvMatrix = Matrix.Invert(ViewProjMatrix); + MouseRayNear = ViewProjInvMatrix.MultiplyW(new Vector3(mx, my, 0.0f)); + MouseRayFar = ViewProjInvMatrix.MultiplyW(new Vector3(mx, my, 1.0f)); + MouseRay.Position = Vector3.Zero; + MouseRay.Direction = Vector3.Normalize(MouseRayFar - MouseRayNear); + if (IsMapView || IsOrthographic) + { + MouseRay.Position = MouseRayNear; + } + ViewFrustum.Update(ref ViewProjMatrix); + ViewFrustum.Position = Position; + } + private void UpdateMousedItem() + { + //////MousedItem = nullptr; + //////MousedThing = nullptr; + //////MousedItemSpace = nullptr; + ////int i = 0; + //////var cp = &SpaceProjections[i++]; + //////auto item = cp->MousedItem; + //////auto thing = cp->MousedThing; + ////auto count = cp->MouseTestedItems; + //////while((item==nullptr) && (thing==nullptr) && (iMoused.HasValue) Moused.Set(cp->Moused); + ////while (!Moused.HasValue && (i < SpaceProjections.size())) + ////{ + //// cp = &SpaceProjections[i++]; + //// //item = cp->MousedItem; + //// //thing = cp->MousedThing; + //// if (cp->Moused.HasValue) + //// { + //// Moused.Set(cp->Moused); + //// } + //// count += cp->MouseTestedItems; + ////} + //////if((item!=nullptr) || (thing!=nullptr)) + //////{ + ////// MousedItem = item; + ////// MousedThing = thing; + ////// MousedItemSpace = cp->MousedItemSpace; + //////} + } + public void OnWindowResize(int w, int h) + { + lock (syncRoot) + { + Width = (float)w; + Height = (float)h; + AspectRatio = Width / Height; + UpdateProj = true; + } + } + + public void ControllerRotate(float x, float y) + { + lock (syncRoot) + { + TargetRotation.X += x; + TargetRotation.Y += y; + } + } + + public void ControllerZoom(float z) + { + lock (syncRoot) + { + float v = (z < 0) ? (1.0f - z) : (z > 0) ? (1.0f / (1.0f + z)) : 1.0f; + TargetDistance *= v; + OrthographicTargetSize *= v; + } + } + + public void MouseRotate(int x, int y) + { + lock (syncRoot) + { + TargetRotation.X += x * Sensitivity; + TargetRotation.Y += y * Sensitivity; + } + } + + public void MouseZoom(int z) + { + lock (syncRoot) + { + float v = (z < 0) ? 1.1f : (z > 0) ? 1.0f / 1.1f : 1.0f; + TargetDistance *= v; + OrthographicTargetSize *= v; + } + } + + } + + public class Frustum + { + public Plane[] Planes = new Plane[6]; + public Vector3 Position; + + public void Update(ref Matrix vp) + { + //left, right, top, bottom, near, far + Planes[0] = Plane.Normalize(new Plane((vp.M14 + vp.M11), (vp.M24 + vp.M21), (vp.M34 + vp.M31), (vp.M44 + vp.M41))); + Planes[1] = Plane.Normalize(new Plane((vp.M14 - vp.M11), (vp.M24 - vp.M21), (vp.M34 - vp.M31), (vp.M44 - vp.M41))); + Planes[2] = Plane.Normalize(new Plane((vp.M14 - vp.M12), (vp.M24 - vp.M22), (vp.M34 - vp.M32), (vp.M44 - vp.M42))); + Planes[3] = Plane.Normalize(new Plane((vp.M14 + vp.M12), (vp.M24 + vp.M22), (vp.M34 + vp.M32), (vp.M44 + vp.M42))); + Planes[4] = Plane.Normalize(new Plane((vp.M13), (vp.M23), (vp.M33), 0.0f));//(vp.M43)); + Planes[5] = Plane.Normalize(new Plane((vp.M14 - vp.M13), (vp.M24 - vp.M23), (vp.M34 - vp.M33), (vp.M44 - vp.M43))); + } + + public bool ContainsSphere(ref Vector3 c, float cls, float r) + { + //cls = c length squared, for optimization + if (cls < (r * r)) + { + return true; //frustrum center is in the sphere + } + float nr = -r; + for (int i = 0; i < 6; i++) + { + if (Plane.DotCoordinate(Planes[i], c) < nr) + { + return false; + } + } + return true; + } + public bool ContainsSphereNoClip(ref Vector3 c, float cls, float r) + { + //cls = c length squared, for optimization + if (cls < (r * r)) + { + return true; //frustrum center is in the sphere + } + float nr = -r; + for (int i = 0; i < 5; i++) + { + if (Plane.DotCoordinate(Planes[i], c) < nr) + { + return false; + } + } + return true; + } + public bool ContainsSphereNoFrontClip(ref Vector3 c, float cls, float r) + { + //cls = c length squared, for optimization + if (cls < (r * r)) + { + return true; //frustrum center is in the sphere + } + float nr = -r; + for (int i = 0; i < 6; i++) + { + if ((i != 4) && (Plane.DotCoordinate(Planes[i], c) < nr)) + { + return false; + } + } + return true; + } + public bool ContainsSphereNoClipNoOpt(ref Vector3 c, float r) + { + float nr = -r; + for (int i = 0; i < 5; i++) + { + if (Plane.DotCoordinate(Planes[i], c) < nr) + { + return false; + } + } + return true; + } + } +} diff --git a/World/Clouds.cs b/World/Clouds.cs new file mode 100644 index 0000000..6017f96 --- /dev/null +++ b/World/Clouds.cs @@ -0,0 +1,459 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + + +namespace CodeWalker.World +{ + public class Clouds + { + public volatile bool Inited = false; + + public Weather Weather; + public Timecycle Timecycle; + public Dictionary AnimSettings { get; set; } + public CloudAnimOverrides AnimOverrides = new CloudAnimOverrides(); + + public CloudHatManager HatManager; + public CloudSettingsMap SettingsMap; + + + public Clouds() + { + AnimSettings = new Dictionary(); + AddAnimSetting(new CloudAnimSetting("UVOffset1.X", "UV Offset 1 X", -1.0f, 1.0f, 0.0f)); + AddAnimSetting(new CloudAnimSetting("UVOffset1.Y", "UV Offset 1 Y", -1.0f, 1.0f, 0.0f)); + AddAnimSetting(new CloudAnimSetting("UVOffset2.X", "UV Offset 2 X", -1.0f, 1.0f, 0.0f)); + AddAnimSetting(new CloudAnimSetting("UVOffset2.Y", "UV Offset 2 Y", -1.0f, 1.0f, 0.0f)); + AddAnimSetting(new CloudAnimSetting("UVOffset3.X", "UV Offset 3 X", -1.0f, 1.0f, 0.0f)); + AddAnimSetting(new CloudAnimSetting("UVOffset3.Y", "UV Offset 3 Y", -1.0f, 1.0f, 0.0f)); + //AddAnimSetting(new CloudAnimSetting("RescaleUV1.X", "Rescale UV 1 X", 0.0f, 50.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("RescaleUV1.Y", "Rescale UV 1 Y", 0.0f, 50.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("RescaleUV2.X", "Rescale UV 2 X", 0.0f, 50.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("RescaleUV2.Y", "Rescale UV 2 Y", 0.0f, 50.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("RescaleUV3.X", "Rescale UV 3 X", 0.0f, 50.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("RescaleUV3.Y", "Rescale UV 3 Y", 0.0f, 50.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale1.X", "Anim Scale 1 X", 0.0f, 8.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale1.Y", "Anim Scale 1 Y", 0.0f, 8.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale2.X", "Anim Scale 2 X", 0.0f, 8.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale2.Y", "Anim Scale 2 Y", 0.0f, 8.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale3.X", "Anim Scale 3 X", 0.0f, 8.0f, 1.0f)); + //AddAnimSetting(new CloudAnimSetting("cloudLayerAnimScale3.Y", "Anim Scale 3 Y", 0.0f, 8.0f, 1.0f)); + } + private void AddAnimSetting(CloudAnimSetting setting) + { + AnimSettings[setting.Name] = setting; + } + private void UpdateAnimOverrides() + { + AnimOverrides.UVOffset1.X = AnimSettings["UVOffset1.X"].CurrentValue; + AnimOverrides.UVOffset1.Y = AnimSettings["UVOffset1.Y"].CurrentValue; + AnimOverrides.UVOffset2.X = AnimSettings["UVOffset2.X"].CurrentValue; + AnimOverrides.UVOffset2.Y = AnimSettings["UVOffset2.Y"].CurrentValue; + AnimOverrides.UVOffset3.X = AnimSettings["UVOffset3.X"].CurrentValue; + AnimOverrides.UVOffset3.Y = AnimSettings["UVOffset3.Y"].CurrentValue; + //AnimOverrides.RescaleUV1.X = AnimSettings["RescaleUV1.X"].CurrentValue; + //AnimOverrides.RescaleUV1.Y = AnimSettings["RescaleUV1.Y"].CurrentValue; + //AnimOverrides.RescaleUV2.X = AnimSettings["RescaleUV2.X"].CurrentValue; + //AnimOverrides.RescaleUV2.Y = AnimSettings["RescaleUV2.Y"].CurrentValue; + //AnimOverrides.RescaleUV3.X = AnimSettings["RescaleUV3.X"].CurrentValue; + //AnimOverrides.RescaleUV3.Y = AnimSettings["RescaleUV3.Y"].CurrentValue; + //AnimOverrides.cloudLayerAnimScale1.X = AnimSettings["cloudLayerAnimScale1.X"].CurrentValue; + //AnimOverrides.cloudLayerAnimScale1.Y = AnimSettings["cloudLayerAnimScale1.Y"].CurrentValue; + //AnimOverrides.cloudLayerAnimScale2.X = AnimSettings["cloudLayerAnimScale2.X"].CurrentValue; + //AnimOverrides.cloudLayerAnimScale2.Y = AnimSettings["cloudLayerAnimScale2.Y"].CurrentValue; + //AnimOverrides.cloudLayerAnimScale3.X = AnimSettings["cloudLayerAnimScale3.X"].CurrentValue; + //AnimOverrides.cloudLayerAnimScale3.Y = AnimSettings["cloudLayerAnimScale3.Y"].CurrentValue; + } + + public void Init(GameFileCache gameFileCache, Action updateStatus, Weather weather) + { + Weather = weather; + Timecycle = weather.Timecycle; + var rpfman = gameFileCache.RpfMan; + + string filename = "common.rpf\\data\\clouds.xml"; + + //TODO: RpfMan should be able to get the right version? or maybe let gameFileCache do it! + string kffilename = "common.rpf\\data\\cloudkeyframes.xml"; + if (gameFileCache.EnableDlc) + { + kffilename = "update\\update.rpf\\common\\data\\cloudkeyframes.xml"; + } + + XmlDocument cloudsxml = rpfman.GetFileXml(filename); + XmlDocument cloudskfxml = rpfman.GetFileXml(kffilename); + + HatManager = new CloudHatManager(); + HatManager.Init(cloudsxml.DocumentElement); //CloudHatManager + + SettingsMap = new CloudSettingsMap(); + SettingsMap.Init(cloudskfxml.DocumentElement); //CloudSettingsMap + + Inited = true; + } + + + public void Update(float elapsed) + { + UpdateAnimOverrides(); + } + + + } + + + public class CloudHatManager + { + public CloudHatFrag[] CloudHatFrags { get; set; } + public float DesiredTransitionTimeSec { get; set; } + public Vector3 CamPositionScaler { get; set; } + public float AltitudeScrollScaler { get; set; } + + public void Init(XmlElement xml) + { + List fraglist = new List(); + XmlNodeList frags = xml.SelectNodes("mCloudHatFrags/Item"); + foreach (XmlNode node in frags) + { + XmlElement fragel = node as XmlElement; + if (fragel != null) + { + CloudHatFrag frag = new CloudHatFrag(); + frag.Init(fragel); + fraglist.Add(frag); + } + } + CloudHatFrags = fraglist.ToArray(); + + DesiredTransitionTimeSec = Xml.GetChildFloatAttribute(xml, "mDesiredTransitionTimeSec", "value"); + CamPositionScaler = Xml.GetChildVector3Attributes(xml, "mCamPositionScaler", "x", "y", "z"); + AltitudeScrollScaler = Xml.GetChildFloatAttribute(xml, "mAltitudeScrollScaler", "value"); + } + + public CloudHatFrag FindFrag(string name) + { + for (int i = 0; i < CloudHatFrags.Length; i++) + { + CloudHatFrag f = CloudHatFrags[i]; + if (f.Name == name) + { + return f; + } + } + return null; + } + + } + + public class CloudHatFrag + { + public Vector3 Position { get; set; } + public Vector3 Rotation { get; set; } + public Vector3 Scale { get; set; } + public string Name { get; set; } + public CloudHatFragLayer[] Layers { get; set; } + public float TransitionAlphaRange { get; set; } + public float TransitionMidPoint { get; set; } + public bool Enabled { get; set; } + public Vector3 AngularVelocity { get; set; } + public Vector3 AnimBlendWeights { get; set; } + public Vector2[] UVVelocity { get; set; } + public byte[] AnimMode { get; set; } + public bool[] ShowLayer { get; set; } + public bool EnableAnimations { get; set; } + + public void Init(XmlElement xml) + { + Position = Xml.GetChildVector3Attributes(xml, "mPosition", "x", "y", "z"); + Rotation = Xml.GetChildVector3Attributes(xml, "mRotation", "x", "y", "z"); + Scale = Xml.GetChildVector3Attributes(xml, "mScale", "x", "y", "z"); + Name = Xml.GetChildInnerText(xml, "mName"); + + List layerlist = new List(); + XmlNodeList layersxml = xml.SelectNodes("mLayers/Item"); + foreach (XmlNode node in layersxml) + { + XmlElement layerel = node as XmlElement; + if (layerel != null) + { + CloudHatFragLayer layer = new CloudHatFragLayer(); + layer.Init(layerel); + layerlist.Add(layer); + } + } + Layers = layerlist.ToArray(); + + TransitionAlphaRange = Xml.GetChildFloatAttribute(xml, "mTransitionAlphaRange", "value"); + TransitionMidPoint = Xml.GetChildFloatAttribute(xml, "mTransitionMidPoint", "value"); + Enabled = Xml.GetChildBoolAttribute(xml, "mEnabled", "value"); + AngularVelocity = Xml.GetChildVector3Attributes(xml, "mAngularVelocity", "x", "y", "z"); + AnimBlendWeights = Xml.GetChildVector3Attributes(xml, "mAnimBlendWeights", "x", "y", "z"); + + string uvvelocitystr = Xml.GetChildInnerText(xml, "mUVVelocity").Trim(); + string[] uvvelocities = uvvelocitystr.Split('\n'); + UVVelocity = new Vector2[uvvelocities.Length]; + for (int i = 0; i < uvvelocities.Length; i++) + { + Vector2 vel = Vector2.Zero; + string uvvel = uvvelocities[i].Trim(); + string[] uvvelc = uvvel.Split('\t'); + if (uvvelc.Length == 2) + { + FloatUtil.TryParse(uvvelc[0].Trim(), out vel.X); + FloatUtil.TryParse(uvvelc[1].Trim(), out vel.Y); + } + UVVelocity[i] = vel; + } + + string animmodestr = Xml.GetChildInnerText(xml, "mAnimMode").Trim(); + string[] animmodes = animmodestr.Split('\n'); + AnimMode = new byte[animmodes.Length]; + for (int i = 0; i < animmodes.Length; i++) + { + byte.TryParse(animmodes[i].Trim(), out AnimMode[i]); + } + + + //string showlayerstr = Xml.GetChildInnerText(xml, "mShowLayer").Trim(); + XmlNodeList showlayersxml = xml.SelectNodes("mShowLayer/Item"); + ShowLayer = new bool[showlayersxml.Count]; + for (int i = 0; i < showlayersxml.Count; i++) + { + XmlNode slnode = showlayersxml[i]; + if (slnode is XmlElement) + { + ShowLayer[i] = Xml.GetBoolAttribute(slnode, "value"); + } + } + + + EnableAnimations = Xml.GetChildBoolAttribute(xml, "mEnableAnimations", "value"); + + } + + public override string ToString() + { + return Name; + } + } + + public class CloudHatFragLayer + { + public string Filename { get; set; } + public float CostFactor { get; set; } + public float RotationScale { get; set; } + public float CamPositionScalerAdjust { get; set; } + public float TransitionInTimePercent { get; set; } + public float TransitionOutTimePercent { get; set; } + public float TransitionInDelayPercent { get; set; } + public float TransitionOutDelayPercent { get; set; } + public float HeightTigger { get; set; } + public float HeightFadeRange { get; set; } + + public void Init(XmlElement xml) + { + Filename = Xml.GetChildInnerText(xml, "mFilename"); + CostFactor = Xml.GetChildFloatAttribute(xml, "mCostFactor", "value"); + RotationScale = Xml.GetChildFloatAttribute(xml, "mRotationScale", "value"); + CamPositionScalerAdjust = Xml.GetChildFloatAttribute(xml, "mCamPositionScalerAdjust", "value"); + TransitionInTimePercent = Xml.GetChildFloatAttribute(xml, "mTransitionInTimePercent", "value"); + TransitionOutTimePercent = Xml.GetChildFloatAttribute(xml, "mTransitionOutTimePercent", "value"); + TransitionInDelayPercent = Xml.GetChildFloatAttribute(xml, "mTransitionInDelayPercent", "value"); + TransitionOutDelayPercent = Xml.GetChildFloatAttribute(xml, "mTransitionOutDelayPercent", "value"); + HeightTigger = Xml.GetChildFloatAttribute(xml, "mHeightTigger", "value"); + HeightFadeRange = Xml.GetChildFloatAttribute(xml, "mHeightFadeRange", "value"); + } + + public override string ToString() + { + return Filename; + } + } + + + public class CloudSettingsMap + { + public float[] KeyframeTimes { get; set; } + public Dictionary SettingsMap { get; set; } + + public void Init(XmlElement xml) + { + + string kftstr = Xml.GetChildInnerText(xml, "KeyframeTimes").Trim(); + string[] kftarr = kftstr.Split('\n'); + KeyframeTimes = new float[kftarr.Length]; + for (int i = 0; i < kftarr.Length; i++) + { + FloatUtil.TryParse(kftarr[i].Trim(), out KeyframeTimes[i]); + } + + + SettingsMap = new Dictionary(); + XmlNodeList mapxml = xml.SelectNodes("SettingsMap/Item"); + foreach (XmlNode node in mapxml) + { + XmlElement itemel = node as XmlElement; + if (itemel != null) + { + CloudSettingsMapItem item = new CloudSettingsMapItem(); + item.Init(itemel); + SettingsMap[item.Name] = item; + } + } + + } + } + + public class CloudSettingsMapItem + { + public string Name { get; set; } + public CloudSettingsMapCloudList CloudList { get; set; } = new CloudSettingsMapCloudList(); + public CloudSettingsMapKeyData CloudColor { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudLightColor { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudAmbientColor { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudSkyColor { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudBounceColor { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudEastColor { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudWestColor { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudScaleFillColors { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudDensityShift_Scale_ScatteringConst_Scale { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudPiercingLightPower_Strength_NormalStrength_Thickness { get; set; } = new CloudSettingsMapKeyData(); + public CloudSettingsMapKeyData CloudScaleDiffuseFillAmbient_WrapAmount { get; set; } = new CloudSettingsMapKeyData(); + + public void Init(XmlNode xml) + { + Name = Xml.GetChildInnerText(xml, "Name"); + var snode = xml.SelectSingleNode("Settings"); + CloudList.Init(snode.SelectSingleNode("CloudList")); + CloudColor.Init(snode.SelectSingleNode("CloudColor")); + CloudLightColor.Init(snode.SelectSingleNode("CloudLightColor")); + CloudAmbientColor.Init(snode.SelectSingleNode("CloudAmbientColor")); + CloudSkyColor.Init(snode.SelectSingleNode("CloudSkyColor")); + CloudBounceColor.Init(snode.SelectSingleNode("CloudBounceColor")); + CloudEastColor.Init(snode.SelectSingleNode("CloudEastColor")); + CloudWestColor.Init(snode.SelectSingleNode("CloudWestColor")); + CloudScaleFillColors.Init(snode.SelectSingleNode("CloudScaleFillColors")); + CloudDensityShift_Scale_ScatteringConst_Scale.Init(snode.SelectSingleNode("CloudDensityShift_Scale_ScatteringConst_Scale")); + CloudPiercingLightPower_Strength_NormalStrength_Thickness.Init(snode.SelectSingleNode("CloudPiercingLightPower_Strength_NormalStrength_Thickness")); + CloudScaleDiffuseFillAmbient_WrapAmount.Init(snode.SelectSingleNode("CloudScaleDiffuseFillAmbient_WrapAmount")); + } + + + public override string ToString() + { + return Name; + } + } + + public class CloudSettingsMapCloudList + { + public int[] Probability { get; set; } + public int[] Bits { get; set; } //one bit for each cloud hat frag + + public void Init(XmlNode xml) + { + string pstr = Xml.GetChildInnerText(xml, "mProbability").Trim(); + string bstr = Xml.GetChildInnerText(xml, "mBits").Trim(); + + string[] parr = pstr.Split('\n'); + string[] barr = bstr.Split('\n'); + + Probability = new int[parr.Length]; + Bits = new int[barr.Length]; + + for (int i = 0; i < parr.Length; i++) + { + int.TryParse(parr[i].Trim(), out Probability[i]); + } + for (int i = 0; i < barr.Length; i++) + { + Bits[i] = Convert.ToInt32(barr[i].Trim(), 16); + } + } + + } + + public class CloudSettingsMapKeyData + { + public int numKeyEntries { get; set; } + public Dictionary keyEntryData { get; set; } + + public void Init(XmlNode xml) + { + var kdxml = xml.SelectSingleNode("keyData"); + + numKeyEntries = Xml.GetChildIntAttribute(kdxml, "numKeyEntries", "value"); + + string kestr = Xml.GetChildInnerText(kdxml, "keyEntryData").Trim(); + string[] kearr = kestr.Split('\n'); + keyEntryData = new Dictionary(); + for (int i = 0; i < kearr.Length; i++) + { + string kvstr = kearr[i].Trim(); + string[] kvarr = kvstr.Split('\t'); + float key = 0.0f; + Vector4 val = Vector4.Zero; + if (kvarr.Length >= 5) + { + FloatUtil.TryParse(kvarr[0].Trim(), out key); + FloatUtil.TryParse(kvarr[1].Trim(), out val.X); + FloatUtil.TryParse(kvarr[2].Trim(), out val.Y); + FloatUtil.TryParse(kvarr[3].Trim(), out val.Z); + FloatUtil.TryParse(kvarr[4].Trim(), out val.W); + } + else + { } + keyEntryData[key] = val; + } + + } + + } + + + public class CloudAnimSetting + { + public string Name { get; set; } + public string DisplayName { get; set; } + public float MinValue { get; set; } + public float MaxValue { get; set; } + public float DefaultValue { get; set; } + public float CurrentValue { get; set; } + + + public CloudAnimSetting(string name, string displayname, float minval, float maxval, float defaultval) + { + Name = name; + DisplayName = displayname; + MinValue = minval; + MaxValue = maxval; + DefaultValue = defaultval; + CurrentValue = defaultval; + } + + public override string ToString() + { + return DisplayName; + } + } + + public class CloudAnimOverrides + { + public Vector2 UVOffset1 = Vector2.Zero; + public Vector2 UVOffset2 = Vector2.Zero; + public Vector2 UVOffset3 = Vector2.Zero; + public Vector2 RescaleUV1 = Vector2.One; + public Vector2 RescaleUV2 = Vector2.One; + public Vector2 RescaleUV3 = Vector2.One; + public Vector2 cloudLayerAnimScale1 = Vector2.One; + public Vector2 cloudLayerAnimScale2 = Vector2.One; + public Vector2 cloudLayerAnimScale3 = Vector2.One; + } + +} diff --git a/World/Entity.cs b/World/Entity.cs new file mode 100644 index 0000000..ff5180f --- /dev/null +++ b/World/Entity.cs @@ -0,0 +1,179 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.World +{ + public class Entity + { + public Space Space; + public YmapEntityDef EntityDef; + + public float Radius; + public Vector3 Center; + public Vector3 Position; + public Quaternion Orientation = Quaternion.Identity; + public Quaternion OrientationInv = Quaternion.Identity; + + public float Mass; + public Matrix MomentOfInertia; + public Vector3 Momentum; + public Vector3 Velocity; + public Vector3 AngularMomentum; + public Vector3 AngularVelocity; + + public bool WasColliding; + + public bool EnableCollisions; + public bool Enabled; + + + //public CollisionShape .. + + public virtual void PreUpdate(float elapsed) + { } + + } + + + + public class PedEntity : Entity + { + + public Vector2 ControlMovement; + public bool ControlJump; + public bool ControlBoost; + + public Vector3 ForwardVec; + + public Quaternion CameraOrientation = Quaternion.LookAtLH(Vector3.Zero, Vector3.Up, Vector3.ForwardLH); + public Entity CameraEntity = new Entity(); + + public bool OnGround = false; + + + public PedEntity() + { + Radius = 0.5f; + Center = new Vector3(0.0f, 0.0f, -1.2f); //base collision point is 1.7m below center... for camera offset + + Mass = 80.0f; + + ForwardVec = Vector3.UnitY; + CameraEntity.Orientation = CameraOrientation; + CameraEntity.OrientationInv = Quaternion.Invert(Orientation); + } + + public override void PreUpdate(float elapsed) + { + + //float rotspd = 0.5f; + float movspd = 10.0f; + float velspd = 10.0f; + float jmpvel = 3.0f; + float boostmult = 10.0f; + if (ControlBoost) movspd *= boostmult; + + Quaternion rot = Quaternion.Identity;// .RotationAxis(Vector3.UnitZ, -ControlMovement.X * rotspd * elapsed); + Quaternion ori = Quaternion.Multiply(Orientation, rot); + SetOrientation(ori); + + + float jmpamt = (ControlJump ? jmpvel : 0); + Vector3 curvel = Velocity; + Vector3 controlvel = new Vector3(ControlMovement * movspd, jmpamt); + Vector3 targetvel = controlvel + new Vector3(0, 0, curvel.Z); + Vector3 newvel = curvel + (targetvel - curvel) * velspd * elapsed; + Velocity = newvel; + var coll = Space.FindFirstCollision(this, elapsed); + if (coll.Hit) + { + Vector3 collpos = coll.PrePos; //last known ok position + Vector3 disp = Velocity * elapsed; + Vector3 oldpos = Position; + Vector3 targetpos = Position + disp; + float displ = disp.Length(); + + //////BoundingSphere sph = new BoundingSphere(targetpos + Center, Radius); + //////r.SphereHit = SphereIntersect(sph); + + if ((disp.Z > -0.25f))/* && (displ < Radius * 2.0f)*/ + { + Vector3 raydir = new Vector3(0.0f, 0.0f, -1.0f); + Vector3 rayoff = new Vector3(0.0f, 0.0f, 0.0f); + Ray ray = new Ray(targetpos + Center + rayoff, raydir); + var rayhit = Space.RayIntersect(ray, 1.0f); + if (rayhit.Hit) + { + if (rayhit.HitDist > 0) + { + Position = rayhit.Position - Center + new Vector3(0, 0, Radius); + //collpos = Position;//targetpos;// + } + else + { + //the start of the ray was a collision... can't move here + Position = collpos; + } + } + else //might happen when about to go off a big drop? + { + Position = targetpos;// collpos; + //collpos = targetpos; + } + } + else //moving fast... + { + Position = collpos; //last known ok position + } + //Position = collpos; //last known ok position + + + + bool wasOnGround = OnGround; + OnGround = (Vector3.Dot(coll.SphereHit.Normal, Vector3.UnitZ) > 0.8f); + if (OnGround) + { + } + + + Vector3 findisp = Position - oldpos; + float findispl = findisp.Length(); + float fdisp = Math.Min(displ, findispl); + Vector3 dispdir = findisp / Math.Max(findispl, 0.0001f); + float absvel = fdisp / Math.Max(elapsed, 0.0001f); + Velocity = dispdir * absvel; + + //Vector3 veldir = Vector3.Normalize(Position - oldpos); + //float vellen = (collpos - oldpos).Length() / Math.Max(elapsed, 0.0001f); + //Velocity = veldir * vellen; + + //Velocity = (Position - oldpos) / Math.Max(elapsed, 0.0001f); + + } + else + { + Position = coll.HitPos; //hitpos is the end pos if not hit + OnGround = false; + } + + CameraEntity.Position = Position; + } + + + private void SetOrientation(Quaternion ori) + { + Orientation = ori; + OrientationInv = Quaternion.Invert(Orientation); + CameraEntity.Orientation = Quaternion.Multiply(Orientation, CameraOrientation); + CameraEntity.OrientationInv = Quaternion.Invert(Orientation); + } + + } + + +} diff --git a/World/PopZone.cs b/World/PopZone.cs new file mode 100644 index 0000000..27f323c --- /dev/null +++ b/World/PopZone.cs @@ -0,0 +1,166 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.World +{ + public class PopZones : BasePathData + { + public volatile bool Inited = false; + public GameFileCache GameFileCache; + + public Dictionary Groups = new Dictionary(); + + public Vector4[] GetNodePositions() + { + return null; + } + public VertexTypePC[] GetPathVertices() + { + return null; + } + public VertexTypePC[] GetTriangleVertices() + { + return TriangleVerts; + } + + public VertexTypePC[] TriangleVerts; + + + + public void Init(GameFileCache gameFileCache, Action updateStatus) + { + Inited = false; + + GameFileCache = gameFileCache; + + var rpfman = gameFileCache.RpfMan; + + string filename = "common.rpf\\data\\levels\\gta5\\popzone.ipl"; + if (gameFileCache.EnableDlc) + { + filename = "update\\update.rpf\\common\\data\\levels\\gta5\\popzone.ipl"; + } + + string ipltext = rpfman.GetFileUTF8Text(filename); + + if (string.IsNullOrEmpty(ipltext)) + { + ipltext = ""; + } + + Groups.Clear(); + + var ipllines = ipltext.Split('\n'); + bool inzone = false; + foreach (var iplline in ipllines) + { + var linet = iplline.Trim(); + if (linet == "zone") + { + inzone = true; + } + else if (linet == "end") + { + inzone = false; + } + else if (inzone) + { + PopZoneBox box = new PopZoneBox(); + box.Init(linet); + + PopZone group; + if (!Groups.TryGetValue(box.NameLabel, out group)) + { + group = new PopZone(); + group.NameLabel = box.NameLabel; + Groups[box.NameLabel] = group; + } + + group.Boxes.Add(box); + } + } + + + foreach (var group in Groups.Values) + { + var hash = JenkHash.GenHash(group.NameLabel.ToLowerInvariant()); + group.Name = GlobalText.TryGetString(hash); + } + + + BuildVertices(); + + Inited = true; + } + + + + public void BuildVertices() + { + + foreach (var group in Groups.Values) + { + + + } + + + } + + } + + + + + public class PopZone + { + public string NameLabel { get; set; } + public string Name { get; set; } //lookup from gxt2 with label..? + public List Boxes { get; set; } = new List(); + + public override string ToString() + { + return NameLabel + ": " + Name; + } + } + + + public class PopZoneBox + { + public string ID { get; set; } + public BoundingBox Box { get; set; } + public string NameLabel { get; set; } + public float UnkVal { get; set; } + + + public void Init(string iplline) + { + var parts = iplline.Split(','); + if (parts.Length >= 9) + { + ID = parts[0].Trim(); + BoundingBox b = new BoundingBox(); + b.Minimum.X = FloatUtil.Parse(parts[1].Trim()); + b.Minimum.Y = FloatUtil.Parse(parts[2].Trim()); + b.Minimum.Z = FloatUtil.Parse(parts[3].Trim()); + b.Maximum.X = FloatUtil.Parse(parts[4].Trim()); + b.Maximum.Y = FloatUtil.Parse(parts[5].Trim()); + b.Maximum.Z = FloatUtil.Parse(parts[6].Trim()); + Box = b; + NameLabel = parts[7].Trim(); + UnkVal = FloatUtil.Parse(parts[8].Trim()); + } + } + + public override string ToString() + { + return ID + ": " + NameLabel + ": " + Box.ToString(); + } + } + +} diff --git a/World/Scenarios.cs b/World/Scenarios.cs new file mode 100644 index 0000000..111b071 --- /dev/null +++ b/World/Scenarios.cs @@ -0,0 +1,1856 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpDX; +using System.Xml; +using System.ComponentModel; + +namespace CodeWalker.World +{ + public class Scenarios + { + public volatile bool Inited = false; + + public Timecycle Timecycle { get; set; } + public GameFileCache GameFileCache { get; set; } + + public static ScenarioTypes ScenarioTypes { get; set; } + + public List ScenarioRegions { get; set; } + + + public void Init(GameFileCache gameFileCache, Action updateStatus, Timecycle timecycle) + { + Timecycle = timecycle; + GameFileCache = gameFileCache; + + + EnsureScenarioTypes(gameFileCache); + + + ScenarioRegions = new List(); + + + //Vector2I maxgrid = new Vector2I(0, 0); + //List griddims = new List(); + //int maxcells = 0; + + var rpfman = gameFileCache.RpfMan; + string manifestfilename = "update\\update.rpf\\x64\\levels\\gta5\\sp_manifest.ymt"; + YmtFile manifestymt = rpfman.GetFile(manifestfilename); + if ((manifestymt != null) && (manifestymt.CScenarioPointManifest != null)) + { + + foreach (var region in manifestymt.CScenarioPointManifest.RegionDefs) + { + string regionfilename = region.Name.ToString() + ".ymt"; //JenkIndex lookup... ymt should have already loaded path strings into it! maybe change this... + string basefilename = regionfilename.Replace("platform:", "x64a.rpf"); + string updfilename = regionfilename.Replace("platform:", "update\\update.rpf\\x64"); + string usefilename = updfilename; + + if (!gameFileCache.EnableDlc) + { + usefilename = basefilename; + } + YmtFile regionymt = rpfman.GetFile(usefilename); + + if (regionymt == null) + { + regionymt = rpfman.GetFile(basefilename); + } + + if (regionymt != null) + { + var sregion = regionymt.ScenarioRegion; + if (sregion != null) + { + ScenarioRegions.Add(regionymt); + + + + ////testing stuff... + + //var gd = regionymt?.CScenarioPointRegion?.Data.AccelGrid.Dimensions ?? new Vector2I(); + //griddims.Add(gd); + //maxgrid = new Vector2I(Math.Max(maxgrid.X, gd.X), Math.Max(maxgrid.Y, gd.Y)); + //maxcells = Math.Max(maxcells, gd.X * gd.Y); + + //byte[] data = regionymt.Save(); + //System.IO.File.WriteAllBytes("C:\\CodeWalker.Projects\\YmtTest\\AllYmts\\" + regionymt.Name, data); + } + } + + + } + + } + + + Inited = true; + } + + + public static void EnsureScenarioTypes(GameFileCache gfc) + { + //if (ScenarioTypes == null) + //{ + var stypes = new ScenarioTypes(); + stypes.Load(gfc); + ScenarioTypes = stypes; + //} + } + + + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ScenarioRegion : BasePathData + { + public VertexTypePC[] PathVerts { get; set; } + public VertexTypePC[] TriangleVerts { get; set; } + public Vector4[] NodePositions { get; set; } + + public VertexTypePC[] GetPathVertices() + { + return PathVerts; + } + public VertexTypePC[] GetTriangleVertices() + { + return TriangleVerts; + } + public Vector4[] GetNodePositions() + { + return NodePositions; + } + + public YmtFile Ymt { get; set; } + public MCScenarioPointRegion Region { get; set; } + + private Dictionary NodeDict { get; set; } + public List Nodes { get; set; } + + public PathBVH BVH { get; set; } + + + public bool Loaded { get; set; } + + + + + public void Load(YmtFile ymt) + { + Ymt = ymt; + Region = ymt?.CScenarioPointRegion; + + BuildNodes(); + + BuildBVH(); + + BuildVertices(); + + LoadTypes(); + + Loaded = true; + } + + + public void LoadTypes() + { + if ((Ymt == null) || (Region == null)) + { return; } + + if (Region.LookUps == null) + { return; } + + if (Scenarios.ScenarioTypes == null) //these are loaded by Scenarios.Init + { return; } + + if (Nodes == null) //nodes not loaded yet - BuildVertices needs to be called first! + { return; } + + foreach (var node in Nodes) + { + LoadTypes(Region, node.MyPoint); + LoadTypes(Region, node.ClusterMyPoint); + LoadTypes(Region, node.ChainingNode); + } + } + + private void LoadTypes(MCScenarioPointRegion r, MCScenarioPoint scp) + { + if (scp == null) return; + + var types = Scenarios.ScenarioTypes; //these are loaded by Scenarios.Init + if (types == null) + { return; } + + var typhashes = r.LookUps.TypeNames; + var pedhashes = r.LookUps.PedModelSetNames; + var vehhashes = r.LookUps.VehicleModelSetNames; + var inthashes = r.LookUps.InteriorNames; + var grphashes = r.LookUps.GroupNames; + var maphashes = r.LookUps.RequiredIMapNames; + + bool isveh = false; + var tpind = scp.TypeId; + if (tpind < typhashes.Length) + { + var hash = typhashes[tpind]; + scp.Type = types.GetScenarioType(hash); + if (scp.Type != null) + { + isveh = scp.Type.IsVehicle; + } + else + { } + } + else + { } + + var msind = scp.ModelSetId; + if (isveh) + { + if (msind < vehhashes.Length) + { + var hash = vehhashes[msind]; + scp.ModelSet = types.GetVehicleModelSet(hash); + if (scp.ModelSet != null) + { } + else if (hash != 493038497)//"None" + { } + } + else + { } + } + else + { + if (msind < pedhashes.Length) + { + var hash = pedhashes[msind]; + scp.ModelSet = types.GetPedModelSet(hash); + if (scp.ModelSet != null) + { } + else if (hash != 493038497)//"None" + { } + } + else + { } + } + + var intind = scp.InteriorId; + if (intind < inthashes.Length) + { + var hash = inthashes[intind]; + scp.InteriorName = hash; + } + + var grpid = scp.GroupId; + if (grpid < grphashes.Length) + { + var hash = grphashes[grpid]; + scp.GroupName = hash; + } + + var mapid = scp.IMapId; + if (mapid < maphashes.Length) + { + var hash = maphashes[mapid]; + scp.IMapName = hash; + } + + } + private void LoadTypes(MCScenarioPointRegion r, MCScenarioChainingNode spn) + { + if (spn == null) return; + var types = Scenarios.ScenarioTypes; //these are loaded by Scenarios.Init + if (types == null) + { return; } + + uint hash = spn._Data.ScenarioType; + if ((hash != 0) && (hash != 493038497)) + { + bool isveh = false; + spn.Type = types.GetScenarioType(hash); + if (spn.Type != null) + { + isveh = spn.Type.IsVehicle; + } + else + { } + if (isveh) + { } + else + { } + } + } + + + + public void BuildNodes() + { + + NodeDict = new Dictionary(); + Nodes = new List(); + + if ((Ymt != null) && (Ymt.CScenarioPointRegion != null)) + { + var r = Ymt.CScenarioPointRegion; + + if ((r.Paths != null) && (r.Paths.Nodes != null)) + { + foreach (var node in r.Paths.Nodes) + { + EnsureNode(node); + } + + + List chainedges = new List(); + + if ((r.Paths.Chains != null) && (r.Paths.Edges != null)) + { + var rp = r.Paths; + var rpc = rp.Chains; + var rpe = rp.Edges; + var rpn = rp.Nodes; + + foreach (var chain in rpc) + { + chainedges.Clear(); + + foreach (var edgeId in chain.EdgeIds) + { + if (edgeId >= rpe.Length) + { continue; } + var edge = rpe[edgeId]; + + if (edge.NodeIndexFrom >= rpn.Length) + { continue; } + if (edge.NodeIndexTo >= rpn.Length) + { continue; } + + edge.NodeFrom = rpn[edge.NodeIndexFrom]; + edge.NodeTo = rpn[edge.NodeIndexTo]; + + var nfc = edge.NodeFrom?.Chain; + var ntc = edge.NodeTo?.Chain; + + if ((nfc != null) && (nfc != chain)) + { } + if ((ntc != null) && (ntc != chain)) + { } + + if (edge.NodeFrom != null) edge.NodeFrom.Chain = chain; + if (edge.NodeTo != null) edge.NodeTo.Chain = chain; + + chainedges.Add(edge); + } + + chain.Edges = chainedges.ToArray(); + } + } + + } + + if (r.Points != null) + { + if (r.Points.MyPoints != null) + { + foreach (var point in r.Points.MyPoints) + { + EnsureNode(point); + } + } + if (r.Points.LoadSavePoints != null) + { + foreach (var point in r.Points.LoadSavePoints) + { + EnsureNode(point); //no hits here - not used? + } + } + } + + if (r.Clusters != null) //spawn groups + { + foreach (var cluster in r.Clusters) + { + EnsureClusterNode(cluster); + + if (cluster.Points != null) + { + if (cluster.Points.MyPoints != null) + { + foreach (var point in cluster.Points.MyPoints) + { + var node = EnsureClusterNode(point); + node.Cluster = cluster; + } + } + if (cluster.Points.LoadSavePoints != null) + { + foreach (var point in cluster.Points.LoadSavePoints) + { + var node = EnsureClusterNode(point); //no hits here - not used? + node.Cluster = cluster; + } + } + } + } + } + + if (r.EntityOverrides != null) + { + foreach (var overr in r.EntityOverrides) + { + EnsureEntityNode(overr); + + if (overr.ScenarioPoints != null) + { + foreach (var point in overr.ScenarioPoints) + { + var node = EnsureEntityNode(point); + node.Entity = overr; + } + } + } + } + + } + + + //Nodes = NodeDict.Values.ToList(); + + } + + public void BuildBVH() + { + BVH = new PathBVH(Nodes, 10); + } + + public void BuildVertices() + { + + List pathverts = new List(); + + uint cred = (uint)Color.Red.ToRgba(); + uint cblu = (uint)Color.Blue.ToRgba(); + uint cgrn = (uint)Color.Green.ToBgra(); + uint cblk = (uint)Color.Black.ToBgra(); + + if ((Ymt != null) && (Ymt.CScenarioPointRegion != null)) + { + var r = Ymt.CScenarioPointRegion; + VertexTypePC pv1 = new VertexTypePC(); + VertexTypePC pv2 = new VertexTypePC(); + + if ((r.Paths != null) && (r.Paths.Nodes != null)) + { + if ((r.Paths.Chains != null) && (r.Paths.Edges != null)) + { + foreach (var chain in r.Paths.Chains) + { + if (chain.Edges == null) continue; + foreach (var edge in chain.Edges) + { + var vid1 = edge._Data.NodeIndexFrom; + var vid2 = edge._Data.NodeIndexTo; + if ((vid1 >= r.Paths.Nodes.Length) || (vid2 >= r.Paths.Nodes.Length)) continue; + var v1 = r.Paths.Nodes[vid1]; + var v2 = r.Paths.Nodes[vid2]; + byte cr1 = (v1.NotFirst) ? (byte)255 : (byte)0; + byte cr2 = (v2.NotFirst) ? (byte)255 : (byte)0; + byte cg = 0;// (chain._Data.Unk_1156691834 > 1) ? (byte)255 : (byte)0; + //cg = ((v1.Unk1 != 0) || (v2.Unk1 != 0)) ? (byte)255 : (byte)0; + //cg = (edge.Action == Unk_3609807418.Unk_7865678) ? (byte)255 : (byte)0; + //cg = ((v1.UnkValTest != 0) || (v2.UnkValTest != 0)) ? (byte)255 : (byte)0; + + byte cb1 = (byte)(255 - cr1); + byte cb2 = (byte)(255 - cr2); + pv1.Position = v1.Position; + pv2.Position = v2.Position; + pv1.Colour = (uint)new Color(cr1, cg, cb1, (byte)255).ToRgba();// (v1._Data.Unk_407126079 == 1) ? cred : cblu; + pv2.Colour = (uint)new Color(cr2, cg, cb2, (byte)255).ToRgba();// (v2._Data.Unk_407126079 == 1) ? cred : cblu; + pathverts.Add(pv1); + pathverts.Add(pv2); + } + } + } + } + + //if (r.Unk_3844724227 != null) //visualise AccelGrid... + //{ + // var grid = r._Data.AccelGrid; + // var minx = grid.Unk_MinX_860552138; + // var maxx = grid.Unk_MaxX_3824598937; + // var miny = grid.Unk_MinY_496029782; + // var maxy = grid.Unk_MaxY_3374647798; + // var cntx = (maxx - minx) + 1; + // var cnty = (maxy - miny) + 1; + // var calclen = cntx * cnty; //==r.Unk_3844724227.Length; + // var gscale = grid.Scale; + // var posz = BVH?.Box.Maximum.Z ?? 0; + // var minpos = new Vector3(grid.Min, posz); + // var sizx = cntx * gscale.X; + // var sizy = cnty * gscale.Y; + // for (var x = 0; x <= cntx; x++) + // { + // var fx = x * gscale.X; + // pv1.Position = minpos + new Vector3(fx, 0, 0); + // pv2.Position = pv1.Position + new Vector3(0, sizy, 0); + // pv1.Colour = cblk; + // pv2.Colour = cblk; + // pathverts.Add(pv1); + // pathverts.Add(pv2); + // } + // for (var y = 0; y <= cnty; y++) + // { + // var fy = y * gscale.Y; + // pv1.Position = minpos + new Vector3(0, fy, 0); + // pv2.Position = pv1.Position + new Vector3(sizx, 0, 0); + // pv1.Colour = cblk; + // pv2.Colour = cblk; + // pathverts.Add(pv1); + // pathverts.Add(pv2); + // } + //} + + + } + + + if (pathverts.Count > 0) + { + PathVerts = pathverts.ToArray(); + } + else + { + PathVerts = null; + } + + + + List nodes = new List(Nodes.Count); + foreach (var node in Nodes) + { + nodes.Add(new Vector4(node.Position, 1.0f)); + } + if (nodes.Count > 0) + { + NodePositions = nodes.ToArray(); + } + else + { + NodePositions = null; + } + + } + + + + + + + private ScenarioNode EnsureNode(MCScenarioChainingNode cnode) + { + ScenarioNode exnode; + if (NodeDict.TryGetValue(cnode.Position, out exnode) && (exnode.ChainingNode == null)) + { + exnode.ChainingNode = cnode; + } + else + { + exnode = new ScenarioNode(cnode.Region?.Ymt); + exnode.ChainingNode = cnode; + exnode.Position = cnode.Position; + NodeDict[cnode.Position] = exnode; + Nodes.Add(exnode); + } + return exnode; + } + private ScenarioNode EnsureNode(MCScenarioPoint point) + { + ScenarioNode exnode; + if (NodeDict.TryGetValue(point.Position, out exnode) && (exnode.MyPoint == null)) + { + exnode.MyPoint = point; + exnode.Orientation = point.Orientation; + } + else + { + exnode = new ScenarioNode(point.Region?.Ymt); + exnode.MyPoint = point; + exnode.Position = point.Position; + exnode.Orientation = point.Orientation; + NodeDict[point.Position] = exnode; + Nodes.Add(exnode); + } + return exnode; + } + private ScenarioNode EnsureNode(MCExtensionDefSpawnPoint point) + { + ScenarioNode exnode; + if (NodeDict.TryGetValue(point.Position, out exnode) && (exnode.LoadSavePoint == null)) + { + exnode.LoadSavePoint = point; + } + else + { + exnode = new ScenarioNode(point.ScenarioRegion?.Ymt); + exnode.LoadSavePoint = point; + exnode.Position = point.Position; + exnode.Orientation = point.Orientation; + NodeDict[point.Position] = exnode; + Nodes.Add(exnode); + } + return exnode; + } + private ScenarioNode EnsureClusterNode(MCScenarioPointCluster cluster) + { + ScenarioNode exnode; + if (NodeDict.TryGetValue(cluster.Position, out exnode) && (exnode.Cluster == null)) + { + exnode.Cluster = cluster; + } + else + { + exnode = new ScenarioNode(cluster.Region?.Ymt); + exnode.Cluster = cluster; + exnode.Position = cluster.Position; + NodeDict[cluster.Position] = exnode; + Nodes.Add(exnode); + } + return exnode; + } + private ScenarioNode EnsureClusterNode(MCScenarioPoint point) + { + ScenarioNode exnode; + if (NodeDict.TryGetValue(point.Position, out exnode) && (exnode.ClusterMyPoint == null)) + { + exnode.ClusterMyPoint = point; + exnode.Orientation = point.Orientation; + } + else + { + exnode = new ScenarioNode(point.Region?.Ymt); + exnode.ClusterMyPoint = point; + exnode.Position = point.Position; + exnode.Orientation = point.Orientation; + NodeDict[point.Position] = exnode; + Nodes.Add(exnode); + } + return exnode; + } + private ScenarioNode EnsureClusterNode(MCExtensionDefSpawnPoint point) + { + ScenarioNode exnode; + if (NodeDict.TryGetValue(point.Position, out exnode) && (exnode.ClusterLoadSavePoint == null)) + { + exnode.ClusterLoadSavePoint = point; + } + else + { + exnode = new ScenarioNode(point.ScenarioRegion?.Ymt); + exnode.ClusterLoadSavePoint = point; + exnode.Position = point.Position; + NodeDict[point.Position] = exnode; + Nodes.Add(exnode); + } + return exnode; + } + private ScenarioNode EnsureEntityNode(MCExtensionDefSpawnPoint point) + { + ScenarioNode exnode; + if (NodeDict.TryGetValue(point.Position, out exnode) && (exnode.EntityPoint == null)) + { + exnode.EntityPoint = point; + } + else + { + exnode = new ScenarioNode(point.ScenarioRegion?.Ymt); + exnode.EntityPoint = point; + exnode.Position = point.Position; + exnode.Orientation = point.Orientation; + NodeDict[point.Position] = exnode; + Nodes.Add(exnode); + } + return exnode; + } + private ScenarioNode EnsureEntityNode(MCScenarioEntityOverride entity) + { + ScenarioNode exnode; + if (NodeDict.TryGetValue(entity.Position, out exnode) && (exnode.Entity == null)) + { + exnode.Entity = entity; + } + else + { + exnode = new ScenarioNode(entity.Region?.Ymt); + exnode.Entity = entity; + exnode.Position = entity.Position; + NodeDict[entity.Position] = exnode; + Nodes.Add(exnode); + } + return exnode; + } + + + + + + + public ScenarioNode AddNode(ScenarioNode copy = null) + { + var n = new ScenarioNode(Ymt); + + var rgn = Ymt.CScenarioPointRegion; + + if (copy != null) + { + if (copy.MyPoint != null) n.MyPoint = new MCScenarioPoint(rgn, copy.MyPoint); + if (copy.LoadSavePoint != null) n.LoadSavePoint = new MCExtensionDefSpawnPoint(rgn, copy.LoadSavePoint); + if (copy.ClusterMyPoint != null) + { + n.Cluster = copy.Cluster; + n.ClusterMyPoint = new MCScenarioPoint(rgn, copy.ClusterMyPoint); + } + else if (copy.ClusterLoadSavePoint != null) + { + n.Cluster = copy.Cluster; + n.ClusterLoadSavePoint = new MCExtensionDefSpawnPoint(rgn, copy.ClusterLoadSavePoint); + } + else if (copy.Cluster != null) + { + n.Cluster = new MCScenarioPointCluster(rgn, copy.Cluster); + } + if (copy.EntityPoint != null) + { + n.Entity = copy.Entity; + n.EntityPoint = new MCExtensionDefSpawnPoint(rgn, copy.EntityPoint); + } + else if (copy.Entity != null) + { + n.Entity = new MCScenarioEntityOverride(rgn, copy.Entity); + } + if (copy.ChainingNode != null) + { + n.ChainingNode = new MCScenarioChainingNode(rgn, copy.ChainingNode); + } + } + else + { + n.MyPoint = new MCScenarioPoint(rgn); + n.MyPoint.InteriorName = 493038497; //JenkHash.GenHash("none"); + n.MyPoint.GroupName = 493038497; + n.MyPoint.IMapName = 493038497; + n.MyPoint.TimeStart = 0; + n.MyPoint.TimeEnd = 24; + } + + + if ((Region != null) && (Region.Points != null)) + { + if (n.MyPoint != null) Region.Points.AddMyPoint(n.MyPoint); + if (n.LoadSavePoint != null) Region.Points.AddLoadSavePoint(n.LoadSavePoint); + if ((n.Cluster != null) && (n.Cluster.Points != null)) + { + if (n.ClusterMyPoint != null) n.Cluster.Points.AddMyPoint(n.ClusterMyPoint); + if (n.ClusterLoadSavePoint != null) n.Cluster.Points.AddLoadSavePoint(n.ClusterLoadSavePoint); + } + if ((n.Entity != null) && (n.Entity.ScenarioPoints != null)) + { + if (n.EntityPoint != null) n.Entity.AddScenarioPoint(n.EntityPoint); + } + } + if ((Region != null) && (Region.Paths != null)) + { + if (n.ChainingNode != null) + { + Region.Paths.AddNode(n.ChainingNode); + + n.ChainingNode.Chain = copy?.ChainingNode?.Chain; + + //create a new edge connecting from the existing node... + if ((copy?.ChainingNode != null) && (Region.Paths.Edges != null)) + { + MCScenarioChainingEdge exEdge = null; + foreach (var edge in Region.Paths.Edges) + { + if (edge.NodeTo == copy.ChainingNode) + { + exEdge = edge; + break; + } + } + if (exEdge != null) + { + MCScenarioChainingEdge newEdge = new MCScenarioChainingEdge(rgn, exEdge); + newEdge.NodeFrom = copy.ChainingNode; + newEdge.NodeIndexFrom = (ushort)copy.ChainingNode.NodeIndex; + newEdge.NodeTo = n.ChainingNode; + newEdge.NodeIndexTo = (ushort)n.ChainingNode.NodeIndex; + Region.Paths.AddEdge(newEdge); + + //chain start/end have these flags set... make sure they are updated! + copy.ChainingNode.NotLast = true; + n.ChainingNode.NotLast = false; + + if (copy.Region == Region) //only add the new edge if we're in the same region... + { + n.ChainingNode.Chain.AddEdge(newEdge); + } + else + { + //create a new chain..? + } + } + } + } + } + + + Nodes.Add(n); + + return n; + } + + + public bool RemoveNode(ScenarioNode node) + { + if (node == null) return false; + + var rgn = Region; + if (rgn == null) return false; + + bool res = true; + + if (rgn.Points != null) + { + if (node.MyPoint != null) + { + res = res && rgn.Points.RemoveMyPoint(node.MyPoint); + } + if (node.LoadSavePoint != null) + { + res = res && rgn.Points.RemoveLoadSavePoint(node.LoadSavePoint); + } + } + if ((node.Cluster != null) && (node.Cluster.Points != null)) + { + if (node.ClusterMyPoint != null) + { + res = res && node.Cluster.Points.RemoveMyPoint(node.ClusterMyPoint); + } + if (node.ClusterLoadSavePoint != null) + { + res = res && node.Cluster.Points.RemoveLoadSavePoint(node.ClusterLoadSavePoint); + } + } + if (node.Entity != null) + { + if (node.EntityPoint != null) + { + res = res && node.Entity.RemoveScenarioPoint(node.EntityPoint); + } + } + if ((node.ChainingNode != null) && (rgn.Paths != null)) + { + res = res && rgn.Paths.RemoveNode(node.ChainingNode); + } + + res = res && Nodes.Remove(node); + + return res; + } + + + + + + + + public byte[] Save() + { + if (Region == null) return null; + + RebuildAccelGrid(); + RebuildLookUps(); + RebuildChains(); + + MetaBuilder mb = new MetaBuilder(); + + var ptr = Region.Save(mb); + + Meta meta = mb.GetMeta(); + + byte[] data = ResourceBuilder.Build(meta, 2); //scenario ymt is version 2... + + return data; + } + + + + + public void RebuildAccelGrid() + { + if (Region == null) return; + + //find the grid extents, then sort points into the cell buckets. + //output cell end point indexes to the accel grid data. + + Vector3 vmin = new Vector3(float.MaxValue); + Vector3 vmax = new Vector3(float.MinValue); + var points = Region.Points?.MyPoints; + if ((points != null) && (points.Length > 0)) + { + foreach (var point in points) + { + var pos = point.Position; + vmin = Vector3.Min(vmin, pos); + vmax = Vector3.Max(vmax, pos); + } + } + else + { + vmin = Vector3.Zero; + vmax = Vector3.Zero; + } + + //need to first find the correct cell size - aim for a maximum of 999 cells + //start at 32x32 size, increment until cell count is within the limit. + float cellsize = 32; + Vector2 gmin = new Vector2(vmin.X / cellsize, vmin.Y / cellsize); + Vector2 gmax = new Vector2(vmax.X / cellsize, vmax.Y / cellsize); + Vector2I imin = new Vector2I(gmin); + Vector2I imax = new Vector2I(gmax); + Vector2I irng = new Vector2I(1, 1) + imax - imin; + int cellcount = irng.X * irng.Y; + while (cellcount > 999) + { + cellsize *= 2.0f; + gmin *= 0.5f; + gmax *= 0.5f; + imin = new Vector2I(gmin); + imax = new Vector2I(gmax); + irng = new Vector2I(1, 1) + imax - imin; + cellcount = irng.X * irng.Y; + } + + + + List[] cells = new List[cellcount]; + if ((points != null) && (points.Length > 0)) + { + foreach (var point in points) + { + var pos = point.Position; + Vector2 gpos = new Vector2(pos.X / cellsize, pos.Y / cellsize); + Vector2I ipos = new Vector2I(gpos) - imin; + if (ipos.X < 0) + { ipos.X = 0; } + if (ipos.Y < 0) + { ipos.Y = 0; } + if (ipos.X >= irng.X) + { ipos.X = irng.X - 1; } + if (ipos.Y >= irng.Y) + { ipos.Y = irng.Y - 1; } + + int idx = ipos.X + ipos.Y * irng.X; + if (idx < 0) + { idx = 0; } + if (idx >= cellcount) + { idx = cellcount - 1; } + + var cell = cells[idx]; + if (cell == null) + { + cell = new List(); + cells[idx] = cell; + } + + cell.Add(point); + } + } + + List newpoints = new List(); + List newids = new List(); + foreach (var cell in cells) + { + if (cell != null) + { + newpoints.AddRange(cell); + } + newids.Add((ushort)newpoints.Count); + } + + Region.Unk_3844724227 = newids.ToArray(); + + rage__spdGrid2D grid = new rage__spdGrid2D(); + grid.Unk_X_2690909759 = cellsize; + grid.Unk_Y_3691675019 = cellsize; + grid.Unk_MinX_860552138 = imin.X; + grid.Unk_MinY_496029782 = imin.Y; + grid.Unk_MaxX_3824598937 = imax.X; + grid.Unk_MaxY_3374647798 = imax.Y; + Region._Data.AccelGrid = grid; + + //store the reordered points. + if (newpoints.Count > 0) + { + Region.Points.MyPoints = newpoints.ToArray(); + } + else + { + Region.Points.MyPoints = null; //todo: error instead? + } + + + } + public void RebuildLookUps() + { + if (Region == null) return; + + //find all unique hashes from the points, and assign new indices on points. + + //var d = Region.LookUps.Data; + Dictionary typeNames = new Dictionary(); //scenario type hashes used by points + Dictionary pedModelSetNames = new Dictionary(); //ped names + Dictionary vehicleModelSetNames = new Dictionary(); //vehicle names + Dictionary interiorNames = new Dictionary(); + Dictionary groupNames = new Dictionary(); //scenario group names? + Dictionary imapNames = new Dictionary(); //ymap names + var nonehash = JenkHash.GenHash("none"); + //typeNames[nonehash] = 0; + pedModelSetNames[nonehash] = 0; + vehicleModelSetNames[nonehash] = 0; + interiorNames[nonehash] = 0; + groupNames[nonehash] = 0; + imapNames[nonehash] = 0; + + foreach (var node in Nodes) + { + if (node.MyPoint != null) + { + var mp = node.MyPoint; + int typeid = 0; + int modelsetid = 0; + int interiorid = 0; + int groupid = 0; + int imapid = 0; + if ((mp.Type != null) && (!typeNames.TryGetValue(mp.Type.NameHash, out typeid))) + { + typeid = typeNames.Count; + typeNames[mp.Type.NameHash] = typeid; + } + if (mp.ModelSet != null) + { + bool isveh = mp.Type?.IsVehicle ?? false; + if (isveh) + { + if (!vehicleModelSetNames.TryGetValue(mp.ModelSet.NameHash, out modelsetid)) + { + modelsetid = vehicleModelSetNames.Count; + vehicleModelSetNames[mp.ModelSet.NameHash] = modelsetid; + } + } + else + { + if (!pedModelSetNames.TryGetValue(mp.ModelSet.NameHash, out modelsetid)) + { + modelsetid = pedModelSetNames.Count; + pedModelSetNames[mp.ModelSet.NameHash] = modelsetid; + } + } + } + if ((mp.InteriorName != 0) && (!interiorNames.TryGetValue(mp.InteriorName, out interiorid))) + { + interiorid = interiorNames.Count; + interiorNames[mp.InteriorName] = interiorid; + } + if ((mp.GroupName != 0) && (!groupNames.TryGetValue(mp.GroupName, out groupid))) + { + groupid = groupNames.Count; + groupNames[mp.GroupName] = groupid; + } + if ((mp.IMapName != 0) && (!imapNames.TryGetValue(mp.IMapName, out imapid))) + { + imapid = imapNames.Count; + imapNames[mp.IMapName] = imapid; + } + mp.TypeId = (byte)typeid; + mp.ModelSetId = (byte)modelsetid; + mp.InteriorId = (byte)interiorid; + mp.GroupId = (ushort)groupid; + mp.IMapId = (byte)imapid; + } + if (node.LoadSavePoint != null) + { + var sp = node.LoadSavePoint; + int typeid = 0; + int modelsetid = 0; + int interiorid = 0; + int groupid = 0; + int imapid = 0; + if ((sp.SpawnType != 0) && (!typeNames.TryGetValue(sp.SpawnType, out typeid))) + { + typeid = typeNames.Count; + typeNames[sp.SpawnType] = typeid; + } + if ((sp.PedType != 0) && (!pedModelSetNames.TryGetValue(sp.PedType, out modelsetid))) + { + modelsetid = pedModelSetNames.Count; + pedModelSetNames[sp.PedType] = modelsetid; + } + if ((sp.Group != 0) && (!groupNames.TryGetValue(sp.Group, out groupid))) + { + groupid = groupNames.Count; + groupNames[sp.Group] = groupid; + } + if ((sp.Interior != 0) && (!interiorNames.TryGetValue(sp.Interior, out interiorid))) + { + interiorid = interiorNames.Count; + interiorNames[sp.Interior] = interiorid; + } + if ((sp.RequiredImap != 0) && (!imapNames.TryGetValue(sp.RequiredImap, out imapid))) + { + imapid = imapNames.Count; + imapNames[sp.RequiredImap] = imapid; + } + } + if (node.Cluster != null) + { + var cl = node.Cluster; + } + if (node.ClusterMyPoint != null) + { + var mp = node.ClusterMyPoint; + int typeid = 0; + int modelsetid = 0; + int interiorid = 0; + int groupid = 0; + int imapid = 0; + if ((mp.Type != null) && (!typeNames.TryGetValue(mp.Type.NameHash, out typeid))) + { + typeid = typeNames.Count; + typeNames[mp.Type.NameHash] = typeid; + } + if (mp.ModelSet != null) + { + bool isveh = mp.Type?.IsVehicle ?? false; + if (isveh) + { + if (!vehicleModelSetNames.TryGetValue(mp.ModelSet.NameHash, out modelsetid)) + { + modelsetid = vehicleModelSetNames.Count; + vehicleModelSetNames[mp.ModelSet.NameHash] = modelsetid; + } + } + else + { + if (!pedModelSetNames.TryGetValue(mp.ModelSet.NameHash, out modelsetid)) + { + modelsetid = pedModelSetNames.Count; + pedModelSetNames[mp.ModelSet.NameHash] = modelsetid; + } + } + } + if ((mp.InteriorName != 0) && (!interiorNames.TryGetValue(mp.InteriorName, out interiorid))) + { + interiorid = interiorNames.Count; + interiorNames[mp.InteriorName] = interiorid; + } + if ((mp.GroupName != 0) && (!groupNames.TryGetValue(mp.GroupName, out groupid))) + { + groupid = groupNames.Count; + groupNames[mp.GroupName] = groupid; + } + if ((mp.IMapName != 0) && (!imapNames.TryGetValue(mp.IMapName, out imapid))) + { + imapid = imapNames.Count; + imapNames[mp.IMapName] = imapid; + } + mp.TypeId = (byte)typeid; + mp.ModelSetId = (byte)modelsetid; + mp.InteriorId = (byte)interiorid; + mp.GroupId = (ushort)groupid; + mp.IMapId = (byte)imapid; + } + if (node.ClusterLoadSavePoint != null) + { + var sp = node.ClusterLoadSavePoint; + //int typeid = 0; + //int modelsetid = 0; + //int interiorid = 0; + //int groupid = 0; + //int imapid = 0; + //if ((sp.SpawnType != 0) && (!typeNames.TryGetValue(sp.SpawnType, out typeid))) + //{ + // typeid = typeNames.Count; + // typeNames[sp.SpawnType] = typeid; + //} + //if ((sp.PedType != 0) && (!pedModelSetNames.TryGetValue(sp.PedType, out modelsetid))) + //{ + // modelsetid = pedModelSetNames.Count; + // pedModelSetNames[sp.PedType] = modelsetid; + //} + //if ((sp.Group != 0) && (!groupNames.TryGetValue(sp.Group, out groupid))) + //{ + // groupid = groupNames.Count; + // groupNames[sp.Group] = groupid; + //} + //if ((sp.Interior != 0) && (!interiorNames.TryGetValue(sp.Interior, out interiorid))) + //{ + // interiorid = interiorNames.Count; + // interiorNames[sp.Interior] = interiorid; + //} + //if ((sp.RequiredImap != 0) && (!imapNames.TryGetValue(sp.RequiredImap, out imapid))) + //{ + // imapid = imapNames.Count; + // imapNames[sp.RequiredImap] = imapid; + //} + } + if (node.Entity != null) + { + var en = node.Entity; + } + if (node.EntityPoint != null) + { + var sp = node.EntityPoint; + //int typeid = 0; + //int modelsetid = 0; + //int interiorid = 0; + //int groupid = 0; + //int imapid = 0; + //if ((sp.SpawnType != 0) && (!typeNames.TryGetValue(sp.SpawnType, out typeid))) + //{ + // typeid = typeNames.Count; + // typeNames[sp.SpawnType] = typeid; + //} + //if ((sp.PedType != 0) && (!pedModelSetNames.TryGetValue(sp.PedType, out modelsetid))) + //{ + // modelsetid = pedModelSetNames.Count; + // pedModelSetNames[sp.PedType] = modelsetid; + //} + //if ((sp.Group != 0) && (!groupNames.TryGetValue(sp.Group, out groupid))) + //{ + // groupid = groupNames.Count; + // groupNames[sp.Group] = groupid; + //} + //if ((sp.Interior != 0) && (!interiorNames.TryGetValue(sp.Interior, out interiorid))) + //{ + // interiorid = interiorNames.Count; + // interiorNames[sp.Interior] = interiorid; + //} + //if ((sp.RequiredImap != 0) && (!imapNames.TryGetValue(sp.RequiredImap, out imapid))) + //{ + // imapid = imapNames.Count; + // imapNames[sp.RequiredImap] = imapid; + //} + } + if (node.ChainingNode != null) + { + var cn = node.ChainingNode; + //int typeid = 0; + //if ((cn.Type != null) && (!typeNames.TryGetValue(cn.Type.NameHash, out typeid))) + //{ + // typeid = typeNames.Count; + // typeNames[cn.Type.NameHash] = typeid; + //} + //cn.TypeHash = cn.Type?.NameHash ?? 0; + } + } + + + MetaHash[] htypeNames = new MetaHash[typeNames.Count]; + MetaHash[] hpedModelSetNames = new MetaHash[pedModelSetNames.Count]; + MetaHash[] hvehicleModelSetNames = new MetaHash[vehicleModelSetNames.Count]; + MetaHash[] hinteriorNames = new MetaHash[interiorNames.Count]; + MetaHash[] hgroupNames = new MetaHash[groupNames.Count]; + MetaHash[] himapNames = new MetaHash[imapNames.Count]; + foreach (var kvp in typeNames) + { + if (kvp.Value >= htypeNames.Length) + { continue; } + htypeNames[kvp.Value] = kvp.Key; + } + foreach (var kvp in pedModelSetNames) + { + if (kvp.Value >= hpedModelSetNames.Length) + { continue; } + hpedModelSetNames[kvp.Value] = kvp.Key; + } + foreach (var kvp in vehicleModelSetNames) + { + if (kvp.Value >= hvehicleModelSetNames.Length) + { continue; } + hvehicleModelSetNames[kvp.Value] = kvp.Key; + } + foreach (var kvp in interiorNames) + { + if (kvp.Value >= hinteriorNames.Length) + { continue; } + hinteriorNames[kvp.Value] = kvp.Key; + } + foreach (var kvp in groupNames) + { + if (kvp.Value >= hgroupNames.Length) + { continue; } + hgroupNames[kvp.Value] = kvp.Key; + } + foreach (var kvp in imapNames) + { + if (kvp.Value >= himapNames.Length) + { continue; } + himapNames[kvp.Value] = kvp.Key; + } + + + if (Region.LookUps == null) + { + Region.LookUps = new MCScenarioPointLookUps(); + Region.LookUps.Region = Region; + } + + var d = Region.LookUps; + d.TypeNames = htypeNames; + d.PedModelSetNames = hpedModelSetNames; + d.VehicleModelSetNames = hvehicleModelSetNames; + d.InteriorNames = hinteriorNames; + d.GroupNames = hgroupNames; + d.RequiredIMapNames = himapNames; + + + } + public void RebuildChains() + { + if (Region == null) return; + + //update chain nodes array, update from/to indexes + //currently not necessary - editor updates indexes and arrays already. + + } + + + } + + + + + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ScenarioNode : BasePathNode + { + public YmtFile Ymt { get; set; } + public MCScenarioPointRegion Region { get; set; } + + public MCScenarioPoint MyPoint { get; set; } + public MCExtensionDefSpawnPoint LoadSavePoint { get; set; } + public MCScenarioPointCluster Cluster { get; set; } + public MCScenarioPoint ClusterMyPoint { get; set; } + public MCExtensionDefSpawnPoint ClusterLoadSavePoint { get; set; } + public MCScenarioEntityOverride Entity { get; set; } + public MCExtensionDefSpawnPoint EntityPoint { get; set; } + public MCScenarioChainingNode ChainingNode { get; set; } + + public Vector3 Position { get; set; } + public Quaternion Orientation { get; set; } = Quaternion.Identity; + + public string ShortTypeName + { + get + { + if (MyPoint != null) return "ScenarioPoint"; + if (LoadSavePoint != null) return "ScenarioPoint"; + if (ClusterMyPoint != null) return "ScenarioPoint"; + if (ClusterLoadSavePoint != null) return "ScenarioPoint"; + if (Cluster != null) return "ScenarioCluster"; + if (EntityPoint != null) return "ScenarioPoint"; + if (Entity != null) return "ScenarioPoint"; + if (ChainingNode != null) return "ScenarioPoint"; + return "ScenarioPoint"; + } + } + public string FullTypeName + { + get + { + if (MyPoint != null) return "Scenario MyPoint"; + if (LoadSavePoint != null) return "Scenario LoadSavePoint"; + if (ClusterMyPoint != null) return "Scenario Cluster MyPoint"; + if (ClusterLoadSavePoint != null) return "Scenario Cluster LoadSavePoint"; + if (Cluster != null) return "Scenario Cluster"; + if (EntityPoint != null) return "Scenario Entity Override Point"; + if (Entity != null) return "Scenario Entity Override"; + if (ChainingNode != null) return "Scenario Chaining Node"; + return "Scenario Point"; + } + } + public string MedTypeName + { + get + { + if (MyPoint != null) return "MyPoint"; + if (LoadSavePoint != null) return "LoadSavePoint"; + if (ClusterMyPoint != null) return "Cluster MyPoint"; + if (ClusterLoadSavePoint != null) return "Cluster LoadSavePoint"; + if (Cluster != null) return "Cluster"; + if (EntityPoint != null) return "Entity Override Point"; + if (Entity != null) return "Entity Override"; + if (ChainingNode != null) return "Chaining Node"; + return "Point"; + } + } + public string StringText + { + get + { + if (MyPoint != null) return MyPoint.ToString(); + if (LoadSavePoint != null) return LoadSavePoint.ToString(); + if (ClusterMyPoint != null) return ClusterMyPoint.ToString(); + if (ClusterLoadSavePoint != null) return ClusterLoadSavePoint.ToString(); + if (Cluster != null) return Cluster.ToString(); + if (EntityPoint != null) return EntityPoint.ToString(); + if (Entity != null) return Entity.ToString(); + if (ChainingNode != null) return ChainingNode.ToString(); + return FloatUtil.GetVector3String(Position); + } + } + + + + public ScenarioNode(YmtFile ymt) + { + Ymt = ymt; + Region = ymt.ScenarioRegion?.Region; + } + + + public void SetPosition(Vector3 position) + { + Position = position; + + if (MyPoint != null) MyPoint.Position = position; + if (LoadSavePoint != null) LoadSavePoint.Position = position; + if (ClusterMyPoint != null) ClusterMyPoint.Position = position; + if (ClusterLoadSavePoint != null) ClusterLoadSavePoint.Position = position; + if ((Cluster != null) && (ClusterMyPoint == null) && (ClusterLoadSavePoint == null)) Cluster.Position = position; + if (EntityPoint != null) EntityPoint.Position = position; + if ((Entity != null) && (EntityPoint == null)) Entity.Position = position; + if (ChainingNode != null) ChainingNode.Position = position; + } + public void SetOrientation(Quaternion orientation) + { + Orientation = orientation; + + if (MyPoint != null) MyPoint.Orientation = orientation; + if (LoadSavePoint != null) LoadSavePoint.Orientation = orientation; + if (ClusterMyPoint != null) ClusterMyPoint.Orientation = orientation; + if (ClusterLoadSavePoint != null) ClusterLoadSavePoint.Orientation = orientation; + //if (Cluster != null) Cluster.Orientation = orientation; + if (EntityPoint != null) EntityPoint.Orientation = orientation; + //if (Entity != null) Entity.Orientation = orientation; + //if (ChainingNode != null) ChainingNode.Orientation = orientation; + } + + + + public override string ToString() + { + return MedTypeName + " " + StringText; + } + + } + + + + + + + public class ScenarioTypes + { + private object SyncRoot = new object(); //keep this thread-safe.. technically shouldn't be necessary, but best to be safe + + private Dictionary Types { get; set; } + private Dictionary PropSets { get; set; } + private Dictionary PedModelSets { get; set; } + private Dictionary VehicleModelSets { get; set; } + private Dictionary AnimGroups { get; set; } + + + + public void Load(GameFileCache gfc) + { + lock (SyncRoot) + { + Types = LoadTypes(gfc, "common:\\data\\ai\\scenarios.meta"); + PropSets = LoadModelSets(gfc, "common:\\data\\ai\\propsets.meta"); + PedModelSets = LoadModelSets(gfc, "common:\\data\\ai\\ambientpedmodelsets.meta"); + VehicleModelSets = LoadModelSets(gfc, "common:\\data\\ai\\vehiclemodelsets.meta"); + AnimGroups = LoadAnimGroups(gfc, "common:\\data\\ai\\conditionalanims.meta"); + } + } + + + private XmlDocument LoadXml(GameFileCache gfc, string filename) + { + string comstr = filename.Replace("common:", "common.rpf"); + string updstr = filename.Replace("common:", "update\\update.rpf\\common"); + string usestr = gfc.EnableDlc ? updstr : comstr; + var xml = gfc.RpfMan.GetFileXml(usestr); + if ((xml == null) || (xml.DocumentElement == null)) + { + xml = gfc.RpfMan.GetFileXml(comstr); + } + return xml; + } + + private Dictionary LoadTypes(GameFileCache gfc, string filename) + { + Dictionary types = new Dictionary(); + + var xml = LoadXml(gfc, filename); + + if ((xml == null) || (xml.DocumentElement == null)) + { + return types; + } + + var typesxml = xml.DocumentElement; + var items = typesxml.SelectNodes("Scenarios/Item"); + + foreach (XmlNode item in items) + { + var typestr = Xml.GetStringAttribute(item, "type"); + ScenarioType typeobj = null; + switch (typestr) + { + case "CScenarioPlayAnimsInfo": + typeobj = new ScenarioTypePlayAnims(); + break; + case "CScenarioWanderingInfo": + case "CScenarioJoggingInfo": + case "CScenarioFleeInfo": + case "CScenarioLookAtInfo": + typeobj = new ScenarioType(); + break; + case "CScenarioVehicleInfo": + case "CScenarioVehicleParkInfo": + typeobj = new ScenarioType(); + typeobj.IsVehicle = true; + break; + default: + break; + } + + if (typeobj != null) + { + typeobj.Load(item); + if (!string.IsNullOrEmpty(typeobj.NameLower)) + { + JenkIndex.Ensure(typeobj.NameLower); + uint hash = JenkHash.GenHash(typeobj.NameLower); + types[hash] = typeobj; + } + else + { } + } + + } + + JenkIndex.Ensure("none"); + + return types; + } + + private Dictionary LoadModelSets(GameFileCache gfc, string filename) + { + Dictionary sets = new Dictionary(); + + var xml = LoadXml(gfc, filename); + + if ((xml == null) || (xml.DocumentElement == null)) + { + return sets; + } + + var setsxml = xml.DocumentElement; + var items = setsxml.SelectNodes("ModelSets/Item"); + + foreach (XmlNode item in items) + { + AmbientModelSet set = new AmbientModelSet(); + set.Load(item); + if (!string.IsNullOrEmpty(set.NameLower)) + { + JenkIndex.Ensure(set.NameLower); + uint hash = JenkHash.GenHash(set.NameLower); + sets[hash] = set; + } + } + + return sets; + } + + private Dictionary LoadAnimGroups(GameFileCache gfc, string filename) + { + Dictionary groups = new Dictionary(); + + var xml = LoadXml(gfc, filename); + + if ((xml == null) || (xml.DocumentElement == null)) + { + return groups; + } + + var setsxml = xml.DocumentElement; + var items = setsxml.SelectNodes("ConditionalAnimsGroup/Item"); + + foreach (XmlNode item in items) + { + ConditionalAnimsGroup group = new ConditionalAnimsGroup(); + group.Load(item); + if (!string.IsNullOrEmpty(group.NameLower)) + { + JenkIndex.Ensure(group.Name); + JenkIndex.Ensure(group.NameLower); + uint hash = JenkHash.GenHash(group.NameLower); + groups[hash] = group; + } + } + + return groups; + } + + + + + public ScenarioType GetScenarioType(uint hash) + { + lock (SyncRoot) + { + if (Types == null) return null; + ScenarioType st; + Types.TryGetValue(hash, out st); + return st; + } + } + public AmbientModelSet GetPropSet(uint hash) + { + lock (SyncRoot) + { + if (PropSets == null) return null; + AmbientModelSet ms; + PropSets.TryGetValue(hash, out ms); + return ms; + } + } + public AmbientModelSet GetPedModelSet(uint hash) + { + lock (SyncRoot) + { + if (PedModelSets == null) return null; + AmbientModelSet ms; + PedModelSets.TryGetValue(hash, out ms); + return ms; + } + } + public AmbientModelSet GetVehicleModelSet(uint hash) + { + lock (SyncRoot) + { + if (VehicleModelSets == null) return null; + AmbientModelSet ms; + VehicleModelSets.TryGetValue(hash, out ms); + return ms; + } + } + public ConditionalAnimsGroup GetAnimGroup(uint hash) + { + lock (SyncRoot) + { + if (AnimGroups == null) return null; + ConditionalAnimsGroup ag; + AnimGroups.TryGetValue(hash, out ag); + return ag; + } + } + + public ScenarioType[] GetScenarioTypes() + { + lock (SyncRoot) + { + if (Types == null) return null; + return Types.Values.ToArray(); + } + } + public AmbientModelSet[] GetPropSets() + { + lock (SyncRoot) + { + if (PropSets == null) return null; + return PropSets.Values.ToArray(); + } + } + public AmbientModelSet[] GetPedModelSets() + { + lock (SyncRoot) + { + if (PedModelSets == null) return null; + return PedModelSets.Values.ToArray(); + } + } + public AmbientModelSet[] GetVehicleModelSets() + { + lock (SyncRoot) + { + if (VehicleModelSets == null) return null; + return VehicleModelSets.Values.ToArray(); + } + } + public ConditionalAnimsGroup[] GetAnimGroups() + { + lock (SyncRoot) + { + if (AnimGroups == null) return null; + return AnimGroups.Values.ToArray(); + } + } + + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ScenarioType + { + public string OuterXml { get; set; } + public string Name { get; set; } + public string NameLower { get; set; } + public MetaHash NameHash { get; set; } + public bool IsVehicle { get; set; } + + public virtual void Load(XmlNode node) + { + OuterXml = node.OuterXml; + Name = Xml.GetChildInnerText(node, "Name"); + NameLower = Name.ToLowerInvariant(); + NameHash = JenkHash.GenHash(NameLower); + } + + public override string ToString() + { + return Name; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class ScenarioTypePlayAnims : ScenarioType + { + + public override void Load(XmlNode node) + { + base.Load(node); + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class AmbientModelSet + { + public string Name { get; set; } + public string NameLower { get; set; } + public MetaHash NameHash { get; set; } + public AmbientModel[] Models { get; set; } + + + public void Load(XmlNode node) + { + Name = Xml.GetChildInnerText(node, "Name"); + NameLower = Name.ToLowerInvariant(); + NameHash = JenkHash.GenHash(NameLower); + + var models = node.SelectNodes("Models/Item"); + var modellist = new List(); + foreach (XmlNode item in models) + { + AmbientModel model = new AmbientModel(); + model.Load(item); + modellist.Add(model); + } + Models = modellist.ToArray(); + } + + public override string ToString() + { + return Name; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class AmbientModel + { + public string Name { get; set; } + public string NameLower { get; set; } + public float Probability { get; set; } + public string VariationsType { get; set; } + public AmbientModelVariation Variations { get; set; } + + public void Load(XmlNode node) + { + Name = Xml.GetChildInnerText(node, "Name"); + NameLower = Name.ToLowerInvariant(); + Probability = Xml.GetChildFloatAttribute(node, "Probability", "value"); + VariationsType = Xml.GetChildStringAttribute(node, "Variations", "type"); + var vars = node.SelectSingleNode("Variations"); + switch (VariationsType) + { + case "NULL": + break; + case "CAmbientPedModelVariations": + break; + case "CAmbientVehicleModelVariations": + break; + default: + break; + } + } + + public override string ToString() + { + return Name + ", " + VariationsType; + } + } + [TypeConverter(typeof(ExpandableObjectConverter))] public class AmbientModelVariation + { + public string Type { get; set; } + + + public void Load(XmlNode node) + { + } + + public override string ToString() + { + return Type; + } + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class ConditionalAnimsGroup + { + public string OuterXml { get; set; } + public string Name { get; set; } + public string NameLower { get; set; } + + + public void Load(XmlNode node) + { + OuterXml = node.OuterXml; + Name = Xml.GetChildInnerText(node, "Name"); + NameLower = Name.ToLowerInvariant(); + } + + public override string ToString() + { + return Name; + } + } + +} diff --git a/World/Space.cs b/World/Space.cs new file mode 100644 index 0000000..ce7f0a9 --- /dev/null +++ b/World/Space.cs @@ -0,0 +1,2078 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.World +{ + public class Space + { + + public LinkedList TemporaryEntities = new LinkedList(); + public LinkedList PersistentEntities = new LinkedList(); + public List EnabledEntities = new List(); //built each frame + + private GameFileCache GameFileCache = null; + + + public SpaceGrid Grid; + private Dictionary visibleBoundsDict = new Dictionary(); + + private Dictionary interiorLookup = new Dictionary(); + private Dictionary dataGroupDict = new Dictionary(); + private Dictionary nodedict = new Dictionary(); + private Dictionary boundsdict = new Dictionary(); + private Dictionary usedboundsdict = new Dictionary(); + + private Dictionary ymaptimes = new Dictionary(); + private Dictionary ymapweathertypes = new Dictionary(); + + public bool Inited = false; + + + public SpaceNodeGrid NodeGrid; + private Dictionary AllYnds = new Dictionary(); + + public SpaceNavGrid NavGrid; + + public List Collisions = new List(); + + + public void Init(GameFileCache gameFileCache, Action updateStatus) + { + GameFileCache = gameFileCache; + + + updateStatus("Scanning manifests..."); + + InitManifestData(); + + + updateStatus("Scanning caches..."); + + InitCacheData(); + + + updateStatus("Building world grid..."); + + InitMapGrid(); + + + updateStatus("Loading paths..."); + + InitNodeGrid(); + + + updateStatus("Loading nav meshes..."); + + InitNavGrid(); + + + Inited = true; + updateStatus("World initialised."); + } + + + private void InitManifestData() + { + interiorLookup.Clear(); + ymaptimes.Clear(); + ymapweathertypes.Clear(); + dataGroupDict.Clear(); + + var manifests = GameFileCache.AllManifests; + foreach (var manifest in manifests) + { + //build interior lookup - maps child->parent interior bounds + if (manifest.Interiors != null) + { + foreach (var interior in manifest.Interiors) + { + if (interior.Bounds != null) + { + foreach (var intbound in interior.Bounds) + { + if (interiorLookup.ContainsKey(intbound)) + { }//updates can hit here + interiorLookup[intbound] = interior.Interior.Name; + } + } + else + { } + } + } + + //these appear to be all the dynamic "togglable" ymaps.... + if (manifest.MapDataGroups != null) + { + foreach (var mapgroup in manifest.MapDataGroups) + { + if (mapgroup.HoursOnOff != 0) + { + ymaptimes[mapgroup.Name] = mapgroup.HoursOnOff; + } + if (mapgroup.WeatherTypes != null) + { + ymapweathertypes[mapgroup.Name] = mapgroup.WeatherTypes; + } + + if (dataGroupDict.ContainsKey(mapgroup.DataGroup.Name)) + { + if (mapgroup.Bounds != null) + { + var ex = dataGroupDict[mapgroup.DataGroup.Name]; + if (ex.Bounds != null) + { } //only 1 hit here - redcarpet + } + else + { + continue;//nothing to replace with + } + } + dataGroupDict[mapgroup.DataGroup.Name] = mapgroup; + } + } + } + + //YmfMapDataGroups string + //StringBuilder sb = new StringBuilder(); + //foreach (var dg in dataGroupDict.Values) + //{ + // sb.AppendLine(dg.ToString()); + // if (dg.YBNHashes_3298223272 != null) + // { + // foreach (var ybnh in dg.YBNHashes_3298223272) + // { + // sb.AppendLine(" " + ybnh.ToString()); + // } + // } + //} + //string str = sb.ToString(); + + } + + private void InitCacheData() + { + //build the grid from the cached data + var caches = GameFileCache.AllCacheFiles; + nodedict = new Dictionary(); + MetaHash inthash; + List intlist = new List(); + boundsdict = new Dictionary(); + usedboundsdict = new Dictionary(); + + Dictionary filedates = new Dictionary(); + Dictionary filedates2 = new Dictionary(); + + foreach (var cache in caches) + { + foreach (var filedate in cache.FileDates) + { + CacheFileDate exdate; + if (filedates.TryGetValue(filedate.FileName, out exdate)) + { + if (filedate.TimeStamp >= exdate.TimeStamp) + { + filedates[filedate.FileName] = filedate; + } + else //if (filedate.TimeStamp < exdate.TimeStamp) + { } + } + else + { + filedates[filedate.FileName] = filedate; + } + + if (filedates2.TryGetValue(filedate.FileID, out exdate)) + { + if (filedate.FileName != exdate.FileName) + { } + if (filedate.TimeStamp >= exdate.TimeStamp) + { + filedates2[filedate.FileID] = filedate; + } + else + { } + } + else + { + filedates2[filedate.FileID] = filedate; + } + + } + + + + foreach (var node in cache.AllMapNodes) + { + if (!GameFileCache.YmapDict.ContainsKey(node.Name)) + { continue; } + nodedict[node.Name] = node; + } + + foreach (var intprx in cache.AllCInteriorProxies) + { + //these might need to go into the grid. which grid..? + //but might need to map back to the bounds store... this has more info though! + } + + foreach (var item in cache.AllBoundsStoreItems) + { + if (!GameFileCache.YbnDict.ContainsKey(item.Name)) + { continue; } + + if ((item.Layer < 0) || (item.Layer > 3)) + { } //won't hit here.. + if (interiorLookup.TryGetValue(item.Name, out inthash)) + { + //it's an interior... the vectors are in local space... + intlist.Add(item);//handle it later? use the parent for a dict? + } + else //interiors filtered out + { + SpaceBoundsKey key = new SpaceBoundsKey(item.Name, item.Min); + if (boundsdict.ContainsKey(key)) + { }//updates/dlc hit here + boundsdict[key] = item; + + } + usedboundsdict[item.Name] = item; + } + } + + + + + //try and generate the cache data for uncached ymaps... mainly for mod maps! + var maprpfs = GameFileCache.ActiveMapRpfFiles; + foreach (var maprpf in maprpfs.Values) + { + foreach (var entry in maprpf.AllEntries) + { + if (entry.NameLower.EndsWith(".ymap")) + { + if (!nodedict.ContainsKey(new MetaHash(entry.ShortNameHash))) + { + //non-cached ymap. mostly only mods... but some interesting test things also + var ymap = GameFileCache.RpfMan.GetFile(entry); + if (ymap != null) + { + MapDataStoreNode dsn = new MapDataStoreNode(ymap); + if (dsn.Name != 0) + { + nodedict[dsn.Name] = dsn; + } + else + { } + } + else + { } + } + } + if (entry.NameLower.EndsWith(".ybn")) + { + MetaHash ehash = new MetaHash(entry.ShortNameHash); + if (!usedboundsdict.ContainsKey(ehash)) + { + if (interiorLookup.ContainsKey(ehash)) + { + } + else + { + //exterior ybn's that aren't already cached... only noncached modded bounds hit here... + //load the ybn and cache its extents. + var ybn = GameFileCache.RpfMan.GetFile(entry); + BoundsStoreItem item = new BoundsStoreItem(ybn.Bounds); + item.Name = ehash; + SpaceBoundsKey key = new SpaceBoundsKey(ehash, item.Min); + if (boundsdict.ContainsKey(key)) + { } + boundsdict[key] = item; + } + } + } + } + } + + + } + + private void InitMapGrid() + { + + Grid = new SpaceGrid(); + + List containers = new List(); + List critnodes = new List(); + List hdnodes = new List(); + List lodnodes = new List(); + List strmnodes = new List(); + List intnodes = new List(); + List occlnodes = new List(); + List grassnodes = new List(); + List lodlightsnodes = new List(); + + foreach (var node in nodedict.Values) + { + bool addtogrid = false; + byte t = (byte)(node.ContentFlags & 0xFF); + switch (node.ContentFlags)// t) + { + case 0: + addtogrid = true; //for mods/unused stuff? could be interesting. + break; + case 16://"container" node? + containers.Add(node); + break; + case 18: + case 82: + hdnodes.Add(node); + addtogrid = true; + break; + case 1: + case 65: + strmnodes.Add(node); + addtogrid = true; + break; + case 513: + case 577: + critnodes.Add(node); + addtogrid = true; + break; + case 9: + case 73: + intnodes.Add(node); + addtogrid = true; + break; + case 2: + case 4: + case 20: + case 66: + case 514: + lodnodes.Add(node); + addtogrid = true; + break; + case 128: + case 256: + lodlightsnodes.Add(node); + addtogrid = true; + break; + case 32: + occlnodes.Add(node); + //addtogrid = true; + break; + case 1088: + grassnodes.Add(node); + addtogrid = true; + break; + default: + break; + } + + + if (addtogrid) + { + Grid.AddNode(node); + } + + } + + + foreach (var item in boundsdict.Values) + { + Grid.AddBounds(item); + } + + } + + + private void InitNodeGrid() + { + + NodeGrid = new SpaceNodeGrid(); + AllYnds.Clear(); + + var rpfman = GameFileCache.RpfMan; + Dictionary yndentries = new Dictionary(); + foreach (var rpffile in GameFileCache.BaseRpfs) //load nodes from base rpfs + { + AddRpfYnds(rpffile, yndentries); + } + foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load nodes from current dlc rpfs + { + foreach (var rpffile in dlcrpf.Children) + { + AddRpfYnds(rpffile, yndentries); + } + } + var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load nodes from patch area... + if (updrpf != null) + { + foreach (var rpffile in updrpf.Children) + { + AddRpfYnds(rpffile, yndentries); + } + } + + + Vector3 corner = new Vector3(-8192, -8192, -2048); + Vector3 cellsize = new Vector3(512, 512, 4096); + + for (int x = 0; x < NodeGrid.CellCountX; x++) + { + for (int y = 0; y < NodeGrid.CellCountY; y++) + { + var cell = NodeGrid.Cells[x, y]; + string fname = "nodes" + cell.ID + ".ynd"; + uint fnhash = JenkHash.GenHash(fname); + RpfFileEntry fentry = null; + if (yndentries.TryGetValue(fnhash, out fentry)) + { + cell.Ynd = rpfman.GetFile(fentry); + cell.Ynd.BBMin = corner + (cellsize * new Vector3(x, y, 0)); + cell.Ynd.BBMax = cell.Ynd.BBMin + cellsize; + cell.Ynd.CellX = x; + cell.Ynd.CellY = y; + cell.Ynd.Loaded = true; + + AllYnds[fnhash] = cell.Ynd; + + if (cell.Ynd == null) continue; + if (cell.Ynd.NodeDictionary == null) continue; + if (cell.Ynd.NodeDictionary.Nodes == null) continue; + var na = cell.Ynd.NodeDictionary.Nodes; + + #region node flags test + + //for (int i = 0; i < na.Length; i++) + //{ + // var node = na[i]; + + // int nodetype = node.Unk25Type & 7; + // int linkcount = node.Unk25Type >> 3; + // int nxtlink = node.LinkID + linkcount; + // if (i < na.Length - 1) + // { + // var nxtnode = na[i + 1]; + // if (nxtnode.LinkID != nxtlink) + // { } + // } + // else + // { + // if (nxtlink != cell.Ynd.NodeDictionary.LinksCount) + // { } + // } + + // switch (node.Flags0) + // { + // case 0: + // case 1: + // case 2: + // case 8: + // case 10: + // case 32: + // case 34: + // case 35: + // case 40: + // case 42: + // case 66: + // case 98: + // case 129: + // case 130: + // case 162: + // case 194: + // case 226: + // break; + // default: + // break; + // } + // switch (node.Flags1) + // { + // case 0: + // case 1: + // case 2: + // case 3: + // case 4: + // case 16: + // case 80: + // case 112: + // case 120: + // case 121: + // case 122: + // case 128: + // case 129: + // case 136: + // case 144: + // case 152: + // case 160: + // break; + // default: + // break; + // } + + //} + #endregion + + } + } + } + + //join the dots.... + //StringBuilder sb = new StringBuilder(); + List tverts = new List(); + List tlinks = new List(); + List nlinks = new List(); + foreach (var ynd in AllYnds.Values) + { + BuildYndData(ynd, tverts, tlinks, nlinks); + + //sb.Append(ynd.nodestr); + } + + //string str = sb.ToString(); + + } + + private void AddRpfYnds(RpfFile rpffile, Dictionary yndentries) + { + if (rpffile.AllEntries == null) return; + foreach (var entry in rpffile.AllEntries) + { + if (entry is RpfFileEntry) + { + RpfFileEntry fentry = entry as RpfFileEntry; + if (entry.NameLower.EndsWith(".ynd")) + { + if (yndentries.ContainsKey(entry.NameHash)) + { } + yndentries[entry.NameHash] = fentry; + } + } + } + } + + public void BuildYndLinks(YndFile ynd, List tlinks = null, List nlinks = null) + { + var ynodes = ynd.Nodes; + var nodes = ynd.NodeDictionary?.Nodes; + var links = ynd.NodeDictionary?.Links; + if ((ynodes == null) || (nodes == null) || (links == null)) return; + + int nodecount = ynodes.Length; + + + //build the links arrays. + if(tlinks==null) tlinks = new List(); + if(nlinks==null) nlinks = new List(); + tlinks.Clear(); + for (int i = 0; i < nodecount; i++) + { + nlinks.Clear(); + var node = ynodes[i]; + + var linkid = node.LinkID; + for (int l = 0; l < node.LinkCount; l++) + { + var llid = linkid + l; + if (llid >= links.Length) continue; + var link = links[llid]; + YndNode tnode; + if (link.AreaID == node.AreaID) + { + if (link.NodeID >= ynodes.Length) + { continue; } + tnode = ynodes[link.NodeID]; + } + else + { + tnode = NodeGrid.GetYndNode(link.AreaID, link.NodeID); + if (tnode == null) + { continue; } + if ((Math.Abs(tnode.Ynd.CellX - ynd.CellX) > 1) || (Math.Abs(tnode.Ynd.CellY - ynd.CellY) > 1)) + { /*continue;*/ } //non-adjacent cell? seems to be the carrier problem... + } + + YndLink yl = new YndLink(); + yl.Init(ynd, node, tnode, link); + tlinks.Add(yl); + nlinks.Add(yl); + } + node.Links = nlinks.ToArray(); + } + ynd.Links = tlinks.ToArray(); + + } + public void BuildYndVerts(YndFile ynd, List tverts = null) + { + var ynodes = ynd.Nodes; + if (ynodes == null) return; + + int nodecount = ynodes.Length; + + //build the main linked vertex array (used by the renderable to draw the lines). + if(tverts==null) tverts = new List(); + tverts.Clear(); + for (int i = 0; i < nodecount; i++) + { + var node = ynodes[i]; + if (node.Links == null) continue; + + + var nvert = new VertexTypePC(); + nvert.Position = node.Position; + nvert.Colour = (uint)node.Colour.ToRgba(); + + + for (int l = 0; l < node.Links.Length; l++) + { + YndLink yl = node.Links[l]; + var tnode = yl.Node2; + if (tnode == null) continue; //invalid links could hit here + var tvert = new VertexTypePC(); + tvert.Position = tnode.Position; + tvert.Colour = (uint)tnode.Colour.ToRgba(); + + tverts.Add(nvert); + tverts.Add(tvert); + } + } + ynd.LinkedVerts = tverts.ToArray(); + + + ynd.UpdateTriangleVertices(); + } + public void BuildYndJuncs(YndFile ynd) + { + //attach the junctions to the nodes. + var yjuncs = ynd.Junctions; + if (yjuncs != null) + { + var junccount = yjuncs.Length; + for (int i = 0; i < junccount; i++) + { + var junc = yjuncs[i]; + var cell = NodeGrid.GetCell(junc.RefData.AreaID); + if ((cell == null) || (cell.Ynd == null) || (cell.Ynd.Nodes == null)) + { continue; } + + var jynd = cell.Ynd; + if (cell.Ynd != ynd) //junc in different ynd..? no hits here, except ynds in project.. + { + if (cell.Ynd.AreaID == ynd.AreaID) + { + jynd = ynd; + } + else + { } + } + + if (junc.RefData.NodeID >= jynd.Nodes.Length) + { continue; } + + var jnode = jynd.Nodes[junc.RefData.NodeID]; + jnode.Junction = junc; + jnode.HasJunction = true; + } + } + + } + public void BuildYndData(YndFile ynd, List tverts = null, List tlinks = null, List nlinks = null) + { + + BuildYndLinks(ynd, tlinks, nlinks); + + BuildYndJuncs(ynd); + + BuildYndVerts(ynd, tverts); + + } + + + private void InitNavGrid() + { + NavGrid = new SpaceNavGrid(); + + var rpfman = GameFileCache.RpfMan; + Dictionary ynventries = new Dictionary(); + foreach (var rpffile in GameFileCache.BaseRpfs) //load navmeshes from base rpfs + { + AddRpfYnvs(rpffile, ynventries); + } + foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load navmeshes from current dlc rpfs + { + foreach (var rpffile in dlcrpf.Children) + { + AddRpfYnvs(rpffile, ynventries); + } + } + var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load navmeshes from patch area... + if (updrpf != null) + { + foreach (var rpffile in updrpf.Children) + { + AddRpfYnvs(rpffile, ynventries); + } + } + + + for (int x = 0; x < NavGrid.CellCountX; x++) + { + for (int y = 0; y < NavGrid.CellCountY; y++) + { + var cell = NavGrid.Cells[x, y]; + string fname = "navmesh[" + cell.FileX.ToString() + "][" + cell.FileY.ToString() + "].ynv"; + uint fnhash = JenkHash.GenHash(fname); + RpfFileEntry fentry = null; + if (ynventries.TryGetValue(fnhash, out fentry)) + { + cell.YnvEntry = fentry as RpfResourceFileEntry; + //cell.Ynv = rpfman.GetFile(fentry); + } + } + } + + } + + private void AddRpfYnvs(RpfFile rpffile, Dictionary ynventries) + { + if (rpffile.AllEntries == null) return; + foreach (var entry in rpffile.AllEntries) + { + if (entry is RpfFileEntry) + { + RpfFileEntry fentry = entry as RpfFileEntry; + if (entry.NameLower.EndsWith(".ynv")) + { + if (ynventries.ContainsKey(entry.NameHash)) + { } + ynventries[entry.NameHash] = fentry; + } + } + } + } + + + + public void Update(float elapsed) + { + if (!Inited) return; + if (Grid == null) return; + + + Collisions.Clear(); + + + EnabledEntities.Clear(); + foreach (var e in PersistentEntities) + { + if (e.Enabled) EnabledEntities.Add(e); + } + foreach (var e in TemporaryEntities) + { + if (e.Enabled) EnabledEntities.Add(e); + } + + + + float gravamt = -9.8f; + Vector3 dvgrav = new Vector3(0, 0, gravamt * elapsed); //gravity acceleration vector + dvgrav += (0.5f * dvgrav * elapsed); //v = ut+0.5at^2 ! + float minvel = 0.5f; // stop bouncing when slow... + + foreach (var e in EnabledEntities) + { + if (!e.Enabled) continue; + + e.Velocity += dvgrav; //apply gravity + e.Momentum = e.Velocity * e.Mass; + + e.PreUpdate(elapsed); + + if (e.EnableCollisions) + { + var coll = FindFirstCollision(e, elapsed); + + if (coll.Hit) + { + Collisions.Add(coll); + + float argvel = Math.Abs((e.Velocity - dvgrav).Length()); + + if (e.WasColliding && (argvel < minvel)) + { + e.Velocity = Vector3.Zero; + e.Momentum = Vector3.Zero; + } + else + { + e.Position = coll.PrePos; //move to the last known position before collision + + //bounce... + int maxbounce = 5; + int curbounce = 0; + float trem = 1.0f - coll.PreT; + while (trem > 0) + { + float vl = e.Velocity.Length(); + float erem = elapsed * trem; + float drem = vl * erem; + Vector3 hitn = coll.SphereHit.Normal; + Vector3 bdir = Vector3.Reflect(coll.HitVelDir, hitn); + Vector3 newvel = bdir * (vl * 0.5f); //restitution/bouncyness + e.Velocity = newvel; + + coll = FindFirstCollision(e, erem); + + if (!coll.Hit) + { + e.Position = coll.HitPos;//no hit, all done + break; + } + + Collisions.Add(coll); + + e.Position = coll.PrePos; + + trem = Math.Max(trem * (1.0f - coll.PreT), 0); + + curbounce++; + if (curbounce >= maxbounce) + { + e.Position = coll.HitPos; + break; + } + + + //if ((coll.PreT <= 0))// || (coll.SphereHit.Normal == hitn)) + //{ + // //ae.Velocity = Vector3.Zero; //same collision twice? abort? + // break; + //} + } + + e.Momentum = e.Velocity * e.Mass; + } + e.WasColliding = true; + } + else + { + e.Position = coll.HitPos; //hit pos is the end pos if no hit + e.WasColliding = false; + } + } + + if (e.EntityDef != null) + { + e.EntityDef.Position = e.Position; + } + + + } + + + } + + + public SpaceEntityCollision FindFirstCollision(Entity e, float elapsed) + { + SpaceEntityCollision r = new SpaceEntityCollision(); + r.Entity = e; + + Vector3 pos = e.Position; + Vector3 sphpos = pos + e.Center; + Vector3 disp = e.Velocity * elapsed; + float absdisp = disp.Length(); + + r.HitVelDir = Vector3.Normalize(disp); + r.HitPos = pos + disp; + r.HitVel = e.Velocity; + r.HitT = 1.0f; + r.PreT = 0.0f; + r.PrePos = pos; + + BoundingSphere sph = new BoundingSphere(r.HitPos + e.Center, e.Radius); + + r.SphereHit = SphereIntersect(sph); + + if (!r.SphereHit.Hit) + { + if (absdisp > (e.Radius * 2.0f)) //fast-moving... do a ray test to make sure it's not tunnelling + { + Ray rayt = new Ray(sphpos, r.HitVelDir); + float rayl = absdisp + e.Radius * 4.0f; //include some extra incase of glancing hit + var rayhit = RayIntersect(rayt, rayl); + if (rayhit.Hit) //looks like it is tunnelling... need to find the sphere hit point + { + sph.Center = rayhit.Position; + float hitd = rayhit.HitDist; + r.HitT = hitd / absdisp; + if (r.HitT > 1.0f) + { + r.HitT = 1.0f; + sph.Center = r.HitPos + e.Center; //this really shouldn't happen... but just in case of glancing hit.. + } + + r.SphereHit = SphereIntersect(sph); //this really should be a hit! + } + } + } + + if (r.SphereHit.Hit) + { + int maxiter = 6;//(would be better to iterate until error within tolerance..) + int curiter = 0; + float curt = r.HitT * 0.5f; + float step = curt * 0.5f; + float minstep = 0.05f; + while (curiter < maxiter) //iterate to find a closer hit time... improve this! + { + sph.Center = sphpos + disp * curt; + var tcollres = SphereIntersect(sph); + if (tcollres.Hit) + { + r.HitT = curt; + r.HitPos = sph.Center - e.Center; + r.SphereHit = tcollres; //only use the best hit (ignore misses) + r.HitNumber = curiter; + } + else + { + r.PreT = curt; + r.PrePos = sph.Center - e.Center; + } + curiter++; + if (curiter < maxiter) + { + curt += step * (tcollres.Hit ? -1.0f : 1.0f); + step *= 0.5f; + } + if (absdisp * step < minstep) + { + break; + } + } + } + + r.Hit = r.SphereHit.Hit; + + return r; + } + + + public void AddTemporaryEntity(Entity e) + { + e.Space = this; + while (TemporaryEntities.Count > 100) + { + TemporaryEntities.RemoveFirst();//don't be too laggy + } + TemporaryEntities.AddLast(e); + } + + public void AddPersistentEntity(Entity e) + { + e.Space = this; + PersistentEntities.AddLast(e); + } + + public void RemovePersistentEntity(Entity e) + { + PersistentEntities.Remove(e); + } + + + + private bool IsYmapAvailable(uint ymaphash, int hour, MetaHash weather) + { + MetaHash ymapname = new MetaHash(ymaphash); + uint ymaptime; + MetaHash[] weathers; + if ((hour >= 0) && (hour <= 23)) + { + if (ymaptimes.TryGetValue(ymapname, out ymaptime)) + { + uint mask = 1u << hour; + if ((ymaptime & mask) == 0) return false; + } + } + if (weather.Hash != 0) + { + if (ymapweathertypes.TryGetValue(ymapname, out weathers)) + { + for (int i = 0; i < weathers.Length; i++) + { + if (weathers[i] == weather) return true; + } + return false; + } + } + return true; + } + + public void GetVisibleYmaps(Camera cam, int hour, MetaHash weather, Dictionary ymaps) + { + if (!Inited) return; + if (Grid == null) return; + + + ymaps.Clear(); + + //var pos = Grid.GetCellPos(cam.Position); + var cell = Grid.GetCell(cam.Position); + if (cell.NodesList != null) + { + for (int n = 0; n < cell.NodesList.Count; n++) + { + var node = cell.NodesList[n]; + var hash = node.Name; + if (!ymaps.ContainsKey(hash)) + { + var ymap = (hash > 0) ? GameFileCache.GetYmap(hash) : null; + while ((ymap != null) && (ymap.Loaded)) + { + if (!IsYmapAvailable(hash, hour, weather)) break; + ymaps[hash] = ymap; + hash = ymap.CMapData.parent; + if (ymaps.ContainsKey(hash)) break; + ymap = (hash > 0) ? GameFileCache.GetYmap(hash) : null; + } + } + } + } + + + + //int gridrange = 0; + + //var pos = Grid.GetCellPos(cam.Position); + //int minx = Math.Min(Math.Max(pos.X - gridrange, 0), SpaceGrid.LastCell); + //int maxx = Math.Min(Math.Max(pos.X + gridrange, 0), SpaceGrid.LastCell); + //int miny = Math.Min(Math.Max(pos.Y - gridrange, 0), SpaceGrid.LastCell); + //int maxy = Math.Min(Math.Max(pos.Y + gridrange, 0), SpaceGrid.LastCell); + + //for (int x = minx; x <= maxx; x++) + //{ + // for (int y = miny; y <= maxy; y++) + // { + // var cell = Grid.GetCell(new Vector2I(x, y)); + // if (cell.NodesList != null) + // { + // for (int n = 0; n < cell.NodesList.Count; n++) + // { + // var node = cell.NodesList[n]; + // var hash = node.Name; + // if (!ymaps.ContainsKey(hash)) + // { + // var ymap = (hash > 0) ? GameFileCache.GetYmap(hash) : null; + // if ((ymap != null) && (ymap.Loaded)) + // { + // ymaps[hash] = ymap; + // } + // } + // } + // } + // } + //} + + } + + + public void GetVisibleBounds(Camera cam, int gridrange, bool[] layers, List boundslist) + { + if (!Inited) return; + if (Grid == null) return; + + visibleBoundsDict.Clear(); + + var pos = Grid.GetCellPos(cam.Position); + int minx = Math.Min(Math.Max(pos.X - gridrange, 0), SpaceGrid.LastCell); + int maxx = Math.Min(Math.Max(pos.X + gridrange, 0), SpaceGrid.LastCell); + int miny = Math.Min(Math.Max(pos.Y - gridrange, 0), SpaceGrid.LastCell); + int maxy = Math.Min(Math.Max(pos.Y + gridrange, 0), SpaceGrid.LastCell); + + for (int x = minx; x <= maxx; x++) + { + for (int y = miny; y <= maxy; y++) + { + var cell = Grid.GetCell(new Vector2I(x, y)); + if (cell.BoundsList != null) + { + foreach (var item in cell.BoundsList) + { + uint l = item.Layer; + if (l < 3) + { + if (!layers[l]) continue; + } + else + { } + + visibleBoundsDict[new SpaceBoundsKey(item.Name, item.Min)] = item; + } + } + } + } + + //var cell = grid.GetCell(cam.Position); + //if (cell.BoundsList != null) + //{ + // boundslist.AddRange(cell.BoundsList); + //} + + boundslist.AddRange(visibleBoundsDict.Values); + + } + + + public void GetVisibleYnds(Camera cam, List ynds) + { + if (!Inited) return; + if (NodeGrid == null) return; + + //int x = 9; + //int y = 15; //== nodes489.ynd + + //ynds.Add(NodeGrid.Cells[x, y].Ynd); + + ynds.AddRange(AllYnds.Values); + + } + + + public void GetVisibleYnvs(Camera cam, List ynvs) + { + if (!Inited) return; + if (Grid == null) return; + + + ynvs.Clear(); + + + int gridrange = 30; + var pos = NavGrid.GetCellPos(cam.Position); + int minx = Math.Min(Math.Max(pos.X - gridrange, 0), NavGrid.CellCountX-1); + int maxx = Math.Min(Math.Max(pos.X + gridrange, 0), NavGrid.CellCountX-1); + int miny = Math.Min(Math.Max(pos.Y - gridrange, 0), NavGrid.CellCountY-1); + int maxy = Math.Min(Math.Max(pos.Y + gridrange, 0), NavGrid.CellCountY-1); + for (int x = minx; x <= maxx; x++) + { + for (int y = miny; y <= maxy; y++) + { + var cell = NavGrid.GetCell(new Vector2I(x, y)); + if ((cell != null) && (cell.YnvEntry != null)) + { + var hash = cell.YnvEntry.ShortNameHash; + var ynv = (hash > 0) ? GameFileCache.GetYnv(hash) : null; + if ((ynv != null) && (ynv.Loaded)) + { + ynvs.Add(ynv); + } + } + } + } + + + } + + + public SpaceRayIntersectResult RayIntersect(Ray ray, float maxdist = float.MaxValue) + { + var res = new SpaceRayIntersectResult(); + if (GameFileCache == null) return res; + int polytestcount = 0; + int nodetestcount = 0; + bool testcomplete = true; + var cellpos = Grid.GetCellPos(ray.Position); + var cell = Grid.GetCell(cellpos); + var startz = ray.Position.Z; + var maxcells = 5; + var cellcount = 0; + var box = new BoundingBox(); + var tsph = new BoundingSphere(); + var rayt = new Ray(); + var rp = ray.Position; + var rd = ray.Direction; + float dirx = (rd.X < 0) ? -1 : (rd.X > 0) ? 1 : 0; + float diry = (rd.Y < 0) ? -1 : (rd.Y > 0) ? 1 : 0; + var boxhitdist = float.MaxValue; + var itemhitdist = float.MaxValue; + Vector3 p1, p2, p3, p4, a1, a2, a3; + Vector3 n1 = Vector3.Zero; + float polyhittestdist = 0; + bool hit = false; + BoundPolygon hitpoly = null; + Vector3 hitnorm = Vector3.Zero; + Vector3 hitpos = Vector3.Zero; + while (cell != null) + { + if (cell.BoundsList != null) + { + foreach (var bound in cell.BoundsList) + { + box.Minimum = bound.Min; + box.Maximum = bound.Max; + float boxhitdisttest; + if (ray.Intersects(ref box, out boxhitdisttest)) + { + YbnFile ybn = GameFileCache.GetYbn(bound.Name); + if (ybn == null) + { continue; } //ybn not found? + if (!ybn.Loaded) + { testcomplete = false; continue; } //ybn not loaded yet... + + bool ybnhit = false; + var b = ybn.Bounds; + box.Minimum = b.BoundingBoxMin; + box.Maximum = b.BoundingBoxMax; + float itemboxhitdisttest; + if (!ray.Intersects(ref box, out itemboxhitdisttest)) + { continue; } //ray doesn't hit this ybn + if (itemboxhitdisttest > itemhitdist) + { continue; } //already a closer hit. + if (itemboxhitdisttest > maxdist) + { continue; } + + switch (b.Type) + { + case 10: //BoundComposite + BoundComposite boundcomp = b as BoundComposite; + if (boundcomp == null) + { continue; } + var compchilds = boundcomp.Children?.data_items; + if (compchilds == null) + { continue; } + for (int i = 0; i < compchilds.Length; i++) + { + BoundBVH bgeom = compchilds[i] as BoundBVH; + if (bgeom == null) + { continue; } + if (bgeom.Polygons == null) + { continue; } + if ((bgeom.BVH == null) || (bgeom.BVH.Trees == null)) + { continue; } + + box.Minimum = bgeom.BoundingBoxMin; + box.Maximum = bgeom.BoundingBoxMax; + float bvhboxhittest; + if (!ray.Intersects(ref box, out bvhboxhittest)) + { continue; } + if (bvhboxhittest > itemhitdist) + { continue; } //already a closer hit. + + var q = bgeom.BVH.Quantum.XYZ(); + var c = bgeom.BVH.BoundingBoxCenter.XYZ(); + var cg = bgeom.CenterGeom; + for (int t = 0; t < bgeom.BVH.Trees.Length; t++) + { + var tree = bgeom.BVH.Trees[t]; + box.Minimum = new Vector3(tree.MinX, tree.MinY, tree.MinZ) * q + c; + box.Maximum = new Vector3(tree.MaxX, tree.MaxY, tree.MaxZ) * q + c; + if (!ray.Intersects(ref box, out bvhboxhittest)) + { continue; } + if (bvhboxhittest > itemhitdist) + { continue; } //already a closer hit. + if (bvhboxhittest > maxdist) + { continue; } + + int nodeind = tree.NodeIndex1; + int lastind = tree.NodeIndex2; + while (nodeind < lastind) + { + var node = bgeom.BVH.Nodes[nodeind]; + box.Minimum = new Vector3(node.MinX, node.MinY, node.MinZ) * q + c; + box.Maximum = new Vector3(node.MaxX, node.MaxY, node.MaxZ) * q + c; + bool nodehit = ray.Intersects(ref box, out bvhboxhittest); + bool nodeskip = !nodehit || (bvhboxhittest > itemhitdist); + if (node.PolyCount <= 0) //intermediate node with child nodes + { + if (nodeskip) + { + nodeind += node.PolyId; //(child node count) + } + else + { + nodeind++; + } + } + else //leaf node, with polygons + { + if (!nodeskip) + { + var lastp = node.PolyId + node.PolyCount; + lastp = Math.Min(lastp, (int)bgeom.PolygonsCount); + for (int p = node.PolyId; p < lastp; p++) + { + var polygon = bgeom.Polygons[p]; + bool polyhit = false; + switch (polygon.Type) + { + case BoundPolygonType.Triangle: + var ptri = polygon as BoundPolygonTriangle; + p1 = bgeom.GetVertex(ptri.vertIndex1) + cg; + p2 = bgeom.GetVertex(ptri.vertIndex2) + cg; + p3 = bgeom.GetVertex(ptri.vertIndex3) + cg; + polyhit = ray.Intersects(ref p1, ref p2, ref p3, out polyhittestdist); + if (polyhit) n1 = Vector3.Normalize(Vector3.Cross(p2 - p1, p3 - p1)); + break; + case BoundPolygonType.Sphere: + var psph = polygon as BoundPolygonSphere; + tsph.Center = bgeom.GetVertex(psph.sphereIndex) + cg; + tsph.Radius = psph.sphereRadius; + polyhit = ray.Intersects(ref tsph, out polyhittestdist); + if (polyhit) n1 = Vector3.Normalize((ray.Position + ray.Direction * polyhittestdist) - tsph.Center); + break; + case BoundPolygonType.Capsule: + //TODO + break; + case BoundPolygonType.Box: + var pbox = polygon as BoundPolygonBox; + p1 = bgeom.GetVertex(pbox.boxIndex1);// + cg; //corner + p2 = bgeom.GetVertex(pbox.boxIndex2);// + cg; + p3 = bgeom.GetVertex(pbox.boxIndex3);// + cg; + p4 = bgeom.GetVertex(pbox.boxIndex4);// + cg; + a1 = ((p3 + p4) - (p1 + p2)) * 0.5f; + a2 = p3 - (p1 + a1); + a3 = p4 - (p1 + a1); + Vector3 bs = new Vector3(a1.Length(), a2.Length(), a3.Length()); + Vector3 m1 = a1 / bs.X; + Vector3 m2 = a2 / bs.Y; + Vector3 m3 = a3 / bs.Z; + if ((bs.X < bs.Y) && (bs.X < bs.Z)) m1 = Vector3.Cross(m2, m3); + else if (bs.Y < bs.Z) m2 = Vector3.Cross(m1, m3); + else m3 = Vector3.Cross(m1, m2); + Vector3 tp = rp - (p1 + cg); + rayt.Position = new Vector3(Vector3.Dot(tp, m1), Vector3.Dot(tp, m2), Vector3.Dot(tp, m3)); + rayt.Direction = new Vector3(Vector3.Dot(rd, m1), Vector3.Dot(rd, m2), Vector3.Dot(rd, m3)); + box.Minimum = Vector3.Zero; + box.Maximum = bs; + polyhit = rayt.Intersects(ref box, out polyhittestdist); + if (polyhit) + { + Vector3 hpt = rayt.Position + rayt.Direction * polyhittestdist; + const float eps = 0.002f; + if (Math.Abs(hpt.X) < eps) n1 = -m1; + else if (Math.Abs(hpt.X - bs.X) < eps) n1 = m1; + else if (Math.Abs(hpt.Y) < eps) n1 = -m2; + else if (Math.Abs(hpt.Y - bs.Y) < eps) n1 = m2; + else if (Math.Abs(hpt.Z) < eps) n1 = -m3; + else if (Math.Abs(hpt.Z - bs.Z) < eps) n1 = m3; + else + { n1 = Vector3.UnitZ; } //ray starts inside the box... + } + break; + case BoundPolygonType.Cylinder: + //TODO + break; + } + if (polyhit && (polyhittestdist < itemhitdist) && (polyhittestdist < maxdist)) + { + itemhitdist = polyhittestdist; + ybnhit = true; + hit = true; + hitnorm = n1; + hitpoly = polygon; + } + polytestcount++; + } + } + nodeind++; + } + nodetestcount++; + } + } + } + break; + case 3: //BoundBox - found in drawables - TODO + BoundBox boundbox = b as BoundBox; + if (boundbox == null) + { continue; } + break; + case 0: //BoundSphere - found in drawables - TODO + BoundSphere boundsphere = b as BoundSphere; + if (boundsphere == null) + { continue; } + break; + default: + break; + } + + + if (ybnhit) + { + boxhitdist = boxhitdisttest; + //hit = true; + } + + } + } + } + + + //walk the line to the next cell... + + cellcount++; + if (cellcount >= maxcells) break; + if ((dirx == 0) && (diry == 0)) break; //vertical ray + + Vector3 cellwp = Grid.GetWorldPos(cellpos); + float compx = (dirx < 0) ? cellwp.X : cellwp.X + SpaceGrid.CellSize; + float compy = (diry < 0) ? cellwp.Y : cellwp.Y + SpaceGrid.CellSize; + float deltx = Math.Abs(compx - rp.X); + float delty = Math.Abs(compy - rp.Y); + float nextd = 0; + if (deltx < delty) + { + cellpos.X += (int)dirx; + nextd = (rd.X != 0) ? (deltx / rd.X) : 0; + } + else + { + cellpos.Y += (int)diry; + nextd = (rd.Y != 0) ? (delty / rd.Y) : 0; + } + + cell = Grid.GetCell(cellpos); + + if (nextd > itemhitdist) + { break; } //next cell is further away than current hit.. no need to continue + if (nextd > maxdist) + { break; } //next cell is out of the testing range.. stop now + } + + if (hit) + { + hitpos = ray.Position + ray.Direction * itemhitdist; + } + + res.TestedNodeCount = nodetestcount; + res.TestedPolyCount = polytestcount; + res.TestComplete = testcomplete; + res.Hit = hit; + res.HitDist = itemhitdist; + res.HitPolygon = hitpoly; + res.Position = hitpos; + res.Normal = hitnorm; + + return res; + } + + public SpaceSphereIntersectResult SphereIntersect(BoundingSphere sph) + { + var res = new SpaceSphereIntersectResult(); + if (GameFileCache == null) return res; + int polytestcount = 0; + int nodetestcount = 0; + bool testcomplete = true; + Vector3 sphmin = sph.Center - sph.Radius; + Vector3 sphmax = sph.Center + sph.Radius; + var cellmin = Grid.GetCellPos(sphmin); + var cellmax = Grid.GetCellPos(sphmax); + var cellcount = 0; + var box = new BoundingBox(); + var tsph = new BoundingSphere(); + var spht = new BoundingSphere(); + var sp = sph.Center; + var sr = sph.Radius; + //var boxhitdist = float.MaxValue; + //var itemhitdist = float.MaxValue; + Vector3 p1, p2, p3, p4, a1, a2, a3; + Vector3 n1 = Vector3.Zero; + //float polyhittestdist = 0; + bool hit = false; + BoundPolygon hitpoly = null; + Vector3 hitnorm = Vector3.Zero; + Vector3 hitpos = Vector3.Zero; + for (int x = cellmin.X; x <= cellmax.X; x++) + { + for (int y = cellmin.Y; y <= cellmax.Y; y++) + { + var cell = Grid.GetCell(new Vector2I(x, y)); + if (cell == null) continue; + if (cell.BoundsList == null) continue; + + foreach (var bound in cell.BoundsList) + { + box.Minimum = bound.Min; + box.Maximum = bound.Max; + if (sph.Intersects(ref box)) + { + YbnFile ybn = GameFileCache.GetYbn(bound.Name); + if (ybn == null) + { continue; } //ybn not found? + if (!ybn.Loaded) + { testcomplete = false; continue; } //ybn not loaded yet... + + //bool ybnhit = false; + var b = ybn.Bounds; + box.Minimum = b.BoundingBoxMin; + box.Maximum = b.BoundingBoxMax; + if (!sph.Intersects(ref box)) + { continue; } //ray doesn't hit this ybn + + switch (b.Type) + { + case 10: //BoundComposite + BoundComposite boundcomp = b as BoundComposite; + if (boundcomp == null) + { continue; } + var compchilds = boundcomp.Children?.data_items; + if (compchilds == null) + { continue; } + for (int i = 0; i < compchilds.Length; i++) + { + BoundBVH bgeom = compchilds[i] as BoundBVH; + if (bgeom == null) + { continue; } + if (bgeom.Polygons == null) + { continue; } + if ((bgeom.BVH == null) || (bgeom.BVH.Trees == null)) + { continue; } + + box.Minimum = bgeom.BoundingBoxMin; + box.Maximum = bgeom.BoundingBoxMax; + if (!sph.Intersects(ref box)) + { continue; } + + var q = bgeom.BVH.Quantum.XYZ(); + var c = bgeom.BVH.BoundingBoxCenter.XYZ(); + var cg = bgeom.CenterGeom; + for (int t = 0; t < bgeom.BVH.Trees.Length; t++) + { + var tree = bgeom.BVH.Trees[t]; + box.Minimum = new Vector3(tree.MinX, tree.MinY, tree.MinZ) * q + c; + box.Maximum = new Vector3(tree.MaxX, tree.MaxY, tree.MaxZ) * q + c; + if (!sph.Intersects(ref box)) + { continue; } + + int nodeind = tree.NodeIndex1; + int lastind = tree.NodeIndex2; + while (nodeind < lastind) + { + var node = bgeom.BVH.Nodes[nodeind]; + box.Minimum = new Vector3(node.MinX, node.MinY, node.MinZ) * q + c; + box.Maximum = new Vector3(node.MaxX, node.MaxY, node.MaxZ) * q + c; + bool nodehit = sph.Intersects(ref box); + bool nodeskip = !nodehit; + if (node.PolyCount <= 0) //intermediate node with child nodes + { + if (nodeskip) + { + nodeind += node.PolyId; //(child node count) + } + else + { + nodeind++; + } + } + else //leaf node, with polygons + { + if (!nodeskip) + { + var lastp = node.PolyId + node.PolyCount; + lastp = Math.Min(lastp, (int)bgeom.PolygonsCount); + for (int p = node.PolyId; p < lastp; p++) + { + var polygon = bgeom.Polygons[p]; + bool polyhit = false; + switch (polygon.Type) + { + case BoundPolygonType.Triangle: + var ptri = polygon as BoundPolygonTriangle; + p1 = bgeom.GetVertex(ptri.vertIndex1) + cg; + p2 = bgeom.GetVertex(ptri.vertIndex2) + cg; + p3 = bgeom.GetVertex(ptri.vertIndex3) + cg; + polyhit = sph.Intersects(ref p1, ref p2, ref p3); + if (polyhit) n1 = Vector3.Normalize(Vector3.Cross(p2 - p1, p3 - p1)); + break; + case BoundPolygonType.Sphere: + var psph = polygon as BoundPolygonSphere; + tsph.Center = bgeom.GetVertex(psph.sphereIndex) + cg; + tsph.Radius = psph.sphereRadius; + polyhit = sph.Intersects(ref tsph); + if (polyhit) n1 = Vector3.Normalize(sph.Center - tsph.Center); + break; + case BoundPolygonType.Capsule: + //TODO + break; + case BoundPolygonType.Box: + var pbox = polygon as BoundPolygonBox; + p1 = bgeom.GetVertex(pbox.boxIndex1);// + cg; //corner + p2 = bgeom.GetVertex(pbox.boxIndex2);// + cg; + p3 = bgeom.GetVertex(pbox.boxIndex3);// + cg; + p4 = bgeom.GetVertex(pbox.boxIndex4);// + cg; + a1 = ((p3 + p4) - (p1 + p2)) * 0.5f; + a2 = p3 - (p1 + a1); + a3 = p4 - (p1 + a1); + Vector3 bs = new Vector3(a1.Length(), a2.Length(), a3.Length()); + Vector3 m1 = a1 / bs.X; + Vector3 m2 = a2 / bs.Y; + Vector3 m3 = a3 / bs.Z; + if ((bs.X < bs.Y) && (bs.X < bs.Z)) m1 = Vector3.Cross(m2, m3); + else if (bs.Y < bs.Z) m2 = Vector3.Cross(m1, m3); + else m3 = Vector3.Cross(m1, m2); + Vector3 tp = sp - (p1 + cg); + spht.Center = new Vector3(Vector3.Dot(tp, m1), Vector3.Dot(tp, m2), Vector3.Dot(tp, m3)); + spht.Radius = sph.Radius; + box.Minimum = Vector3.Zero; + box.Maximum = bs; + polyhit = spht.Intersects(ref box); + if (polyhit) + { + Vector3 smin = spht.Center - spht.Radius; + Vector3 smax = spht.Center + spht.Radius; + float eps = spht.Radius * 0.8f; + n1 = Vector3.Zero; + if (Math.Abs(smax.X) < eps) n1 -= m1; + else if (Math.Abs(smin.X - bs.X) < eps) n1 += m1; + if (Math.Abs(smax.Y) < eps) n1 -= m2; + else if (Math.Abs(smin.Y - bs.Y) < eps) n1 += m2; + if (Math.Abs(smax.Z) < eps) n1 -= m3; + else if (Math.Abs(smin.Z - bs.Z) < eps) n1 += m3; + float n1l = n1.Length(); + if (n1l > 0.0f) n1 = n1 / n1l; + else n1 = Vector3.UnitZ; + } + break; + case BoundPolygonType.Cylinder: + //TODO + break; + } + if (polyhit) // && (polyhittestdist < itemhitdist) && (polyhittestdist < maxdist)) + { + hitpoly = polygon; + //itemhitdist = polyhittestdist; + //ybnhit = true; + hit = true; + hitnorm = n1; + } + polytestcount++; + } + } + nodeind++; + } + nodetestcount++; + } + } + } + break; + case 3: //BoundBox - found in drawables - TODO + BoundBox boundbox = b as BoundBox; + if (boundbox == null) + { continue; } + break; + case 0: //BoundSphere - found in drawables - TODO + BoundSphere boundsphere = b as BoundSphere; + if (boundsphere == null) + { continue; } + break; + default: + break; + } + + + //if (ybnhit) + //{ + // //boxhitdist = boxhitdisttest; + // //hit = true; + //} + + } + } + + cellcount++; + } + } + + //if (hit) + //{ + // hitpos = ray.Position + ray.Direction * itemhitdist; + //} + + res.TestedNodeCount = nodetestcount; + res.TestedPolyCount = polytestcount; + res.TestComplete = testcomplete; + res.Hit = hit; + res.HitDist = 0;// itemhitdist; + res.HitPolygon = hitpoly; + res.Position = hitpos; + res.Normal = hitnorm; + + return res; + } + + } + + public class SpaceGrid + { + public const int CellCount = 500; //cells along a side, total cell count is this squared + public const int LastCell = CellCount - 1; //the last cell index in the array + public const float WorldSize = 10000.0f; //max world grid size +/- 10000 units + public const float CellSize = 2.0f * WorldSize / (float)CellCount;//20.0f; //size of a cell + public const float CellSizeInv = 1.0f / CellSize; //inverse of the cell size. + public const float CellSizeHalf = CellSize * 0.5f; //half the cell size + + public int TotalBoundsCount = 0; //total number of bounds in this grid + public int TotalBoundsRefCount = 0; //total number of bounds placements in cells + private int MaxBoundsInCell = 0; //biggest number of bounds added to a single cell + private SpaceGridCell DensestBoundsCell = null; + + public int TotalNodeCount = 0; //total map nodes in grid + public int TotalNodeRefCount = 0; //total number of map node placements in cells + public int MaxNodesInCell = 0; //biggest number of nodes added to a single cell + private SpaceGridCell DensestNodeCell = null; + + public SpaceGridCell[,] Cells { get; set; } = new SpaceGridCell[CellCount, CellCount]; + + + public Vector3 GetWorldPos(Vector2I p) + { + Vector3 ind = new Vector3(p.X, p.Y, 0.0f); + return (ind * CellSize) - new Vector3(WorldSize, WorldSize, 0); + } + public Vector2I GetCellPos(Vector3 p) + { + Vector3 ind = (p + WorldSize) * CellSizeInv; + int x = (int)ind.X; + int y = (int)ind.Y; + x = (x < 0) ? 0 : (x > LastCell) ? LastCell : x; + y = (y < 0) ? 0 : (y > LastCell) ? LastCell : y; + return new Vector2I(x, y); + } + public SpaceGridCell GetCell(Vector2I g) + { + if ((g.X < 0) || (g.Y < 0) || (g.X >= CellCount) || (g.Y >= CellCount)) + { + return null; + } + var cell = Cells[g.X, g.Y]; + if (cell == null) + { + cell = new SpaceGridCell(); + Cells[g.X, g.Y] = cell; + } + return cell; + } + public SpaceGridCell GetCell(Vector3 p) + { + return GetCell(GetCellPos(p)); + } + + public void AddBounds(BoundsStoreItem item) + { + Vector2I min = GetCellPos(item.Min); + Vector2I max = GetCellPos(item.Max); + + int cellcount = 0; + for (int x = min.X; x <= max.X; x++) + { + for (int y = min.Y; y <= max.Y; y++) + { + var cell = GetCell(new Vector2I(x, y)); + cell.AddBounds(item); + TotalBoundsRefCount++; + if (cell.BoundsList.Count > MaxBoundsInCell) + { + MaxBoundsInCell = cell.BoundsList.Count; + DensestBoundsCell = cell; + } + cellcount++; + } + } + if (cellcount == 0) + { } + + TotalBoundsCount++; + } + + public void AddNode(MapDataStoreNode node) + { + bool useouter = true;// false; + //switch (node.Unk01) + //{ + // case 2: + // case 4: + // case 20: + // case 66: + // case 514://lods + // useouter = true; + // break; + // case 128: + // case 256://lodlights + // useouter = true; + // break; + // case 18: + // case 82://HD nodes + // useouter = true; + // break; + //} + + //Vector2I min = GetCellPos(node.OuterBBMin); + //Vector2I max = GetCellPos(node.OuterBBMax); + Vector2I min = GetCellPos(useouter ? node.streamingExtentsMin : node.entitiesExtentsMin); + Vector2I max = GetCellPos(useouter ? node.streamingExtentsMax : node.entitiesExtentsMax); + + for (int x = min.X; x <= max.X; x++) + { + for (int y = min.Y; y <= max.Y; y++) + { + var cell = GetCell(new Vector2I(x, y)); + cell.AddNode(node); + TotalNodeRefCount++; + if (cell.NodesList.Count > MaxNodesInCell) + { + MaxNodesInCell = cell.NodesList.Count; + DensestNodeCell = cell; + } + } + } + + TotalNodeCount++; + } + + } + public class SpaceGridCell + { + public List NodesList; + public List BoundsList; + + + public void AddNode(MapDataStoreNode node) + { + if (NodesList == null) + { + NodesList = new List(); + } + NodesList.Add(node); + } + + public void AddBounds(BoundsStoreItem item) + { + if (BoundsList == null) + { + BoundsList = new List(5); + } + BoundsList.Add(item); + } + public void RemoveBounds(BoundsStoreItem item) + { + if (BoundsList != null) + { + BoundsList.Remove(item); + } + } + } + public struct SpaceBoundsKey + { + public MetaHash Name { get; set; } + public Vector3 Position { get; set; } + public SpaceBoundsKey(MetaHash name, Vector3 position) + { + Name = name; + Position = position; + } + } + + + + public class SpaceNodeGrid + { + //node grid for V paths + public SpaceNodeGridCell[,] Cells { get; set; } + public float CellSize = 512.0f; + public float CellSizeInv; //inverse of the cell size. + public int CellCountX = 32; + public int CellCountY = 32; + public float CornerX = -8192.0f; + public float CornerY = -8192.0f; + + public SpaceNodeGrid() + { + CellSizeInv = 1.0f / CellSize; + + Cells = new SpaceNodeGridCell[CellCountX, CellCountY]; + + for (int x = 0; x < CellCountX; x++) + { + for (int y = 0; y < CellCountY; y++) + { + Cells[x, y] = new SpaceNodeGridCell(x, y); + } + } + } + + public SpaceNodeGridCell GetCell(int id) + { + int x = id % CellCountX; + int y = id / CellCountX; + if ((x >= 0) && (x < CellCountX) && (y >= 0) && (y < CellCountY)) + { + return Cells[x, y]; + } + return null; + } + + + public YndNode GetYndNode(ushort areaid, ushort nodeid) + { + var cell = GetCell(areaid); + if ((cell == null) || (cell.Ynd == null) || (cell.Ynd.Nodes == null)) + { return null; } + if (nodeid >= cell.Ynd.Nodes.Length) + { return null; } + return cell.Ynd.Nodes[nodeid]; + } + + } + public class SpaceNodeGridCell + { + public int X; + public int Y; + public int ID; + + public YndFile Ynd; + + public SpaceNodeGridCell(int x, int y) + { + X = x; + Y = y; + ID = y * 32 + x; + } + + } + + + public class SpaceNavGrid + { + //grid for V navmeshes + public SpaceNavGridCell[,] Cells { get; set; } + public float CellSize = 150.0f; + public float CellSizeInv; //inverse of the cell size. + public int CellCountX = 100; + public int CellCountY = 100; + public float CornerX = -6000.0f; + public float CornerY = -6000.0f; + + public SpaceNavGrid() + { + CellSizeInv = 1.0f / CellSize; + + Cells = new SpaceNavGridCell[CellCountX, CellCountY]; + + for (int x = 0; x < CellCountX; x++) + { + for (int y = 0; y < CellCountY; y++) + { + Cells[x, y] = new SpaceNavGridCell(x, y); + } + } + } + + public SpaceNavGridCell GetCell(int id) + { + int x = id % CellCountX; + int y = id / CellCountX; + if ((x >= 0) && (x < CellCountX) && (y >= 0) && (y < CellCountY)) + { + return Cells[x, y]; + } + return null; + } + + + + public Vector2I GetCellPos(Vector3 p) + { + Vector3 ind = (p - new Vector3(CornerX, CornerY, 0)) * CellSizeInv; + int x = (int)ind.X; + int y = (int)ind.Y; + x = (x < 0) ? 0 : (x >= CellCountX) ? CellCountX-1 : x; + y = (y < 0) ? 0 : (y >= CellCountY) ? CellCountY-1 : y; + return new Vector2I(x, y); + } + public SpaceNavGridCell GetCell(Vector2I g) + { + var cell = Cells[g.X, g.Y]; + if (cell == null) + { + //cell = new SpaceNavGridCell(g.X, g.Y); + //Cells[g.X, g.Y] = cell; + } + return cell; + } + public SpaceNavGridCell GetCell(Vector3 p) + { + return GetCell(GetCellPos(p)); + } + + + + + } + public class SpaceNavGridCell + { + public int X; + public int Y; + public int ID; + public int FileX; + public int FileY; + + public RpfResourceFileEntry YnvEntry; + public YnvFile Ynv; + + public SpaceNavGridCell(int x, int y) + { + X = x; + Y = y; + ID = y * 100 + x; + FileX = x * 3; + FileY = y * 3; + } + + } + + + + public struct SpaceRayIntersectResult + { + public bool Hit; + public float HitDist; + public BoundPolygon HitPolygon; + public Vector3 Position; + public Vector3 Normal; + public int TestedNodeCount; + public int TestedPolyCount; + public bool TestComplete; + } + public struct SpaceSphereIntersectResult + { + public bool Hit; + public float HitDist; + public BoundPolygon HitPolygon; + public Vector3 Position; + public Vector3 Normal; + public int TestedNodeCount; + public int TestedPolyCount; + public bool TestComplete; + } + + public struct SpaceEntityCollision + { + public Entity Entity; //the entity owning this collision + public Entity Entity2; //second entity, if this is a collision between two entities + public SpaceSphereIntersectResult SphereHit; //details of the sphere intersection point + public Vector3 PrePos; //last known position before hit + public float PreT; //last known T before hit + public float HitT; //fraction of the frame (0-1) + public Vector3 HitPos; //position of the sphere center at hit point + public Quaternion HitRot; //rotation of the entity at hit point + public Vector3 HitVel; //velocity of the entity for this hit + public Vector3 HitAngVel; //angular velocity of the entity for this hit + public int HitNumber; //count of previous iterations + public bool Hit; + public Vector3 HitVelDir; + } + +} diff --git a/World/Timecycle.cs b/World/Timecycle.cs new file mode 100644 index 0000000..0dfb8e2 --- /dev/null +++ b/World/Timecycle.cs @@ -0,0 +1,124 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.World +{ + public class Timecycle + { + public volatile bool Inited = false; + + public float sun_roll { get; set; } + public float sun_yaw { get; set; } + public float moon_roll { get; set; } + public float moon_wobble_freq { get; set; } + public float moon_wobble_amp { get; set; } + public float moon_wobble_offset { get; set; } + public List Samples { get; set; } = new List(); + public List Regions { get; set; } = new List(); + + public float CurrentHour { get; set; } = 0; + public int CurrentSampleIndex { get; set; } = 0; + public float CurrentSampleBlend { get; set; } = 1.0f; + public float NextSampleBlend { get; set; } = 0.0f; + public Vector3 CurrentSunDirection { get; set; } = new Vector3(0, 0, 1); + public Vector3 CurrentMoonDirection { get; set; } = new Vector3(0, 0, -1); + + public void Init(GameFileCache gameFileCache, Action updateStatus) + { + var rpfman = gameFileCache.RpfMan; + + string filename = "common.rpf\\data\\levels\\gta5\\time.xml"; + + XmlDocument timexml = rpfman.GetFileXml(filename); + + XmlElement time = timexml.DocumentElement; + XmlNode suninfo = time.SelectSingleNode("suninfo"); + XmlNode mooninfo = time.SelectSingleNode("mooninfo"); + XmlNodeList samples = time.SelectNodes("sample"); + XmlNodeList regions = time.SelectNodes("region"); + + sun_roll = Xml.GetFloatAttribute(suninfo, "sun_roll"); + sun_yaw = Xml.GetFloatAttribute(suninfo, "sun_yaw"); + moon_roll = Xml.GetFloatAttribute(mooninfo, "moon_roll"); + moon_wobble_freq = Xml.GetFloatAttribute(mooninfo, "moon_wobble_freq"); + moon_wobble_amp = Xml.GetFloatAttribute(mooninfo, "moon_wobble_amp"); + moon_wobble_offset = Xml.GetFloatAttribute(mooninfo, "moon_wobble_offset"); + + Samples.Clear(); + for (int i = 0; i < samples.Count; i++) + { + TimecycleSample tcs = new TimecycleSample(); + tcs.Init(samples[i]); + Samples.Add(tcs); + } + + Regions.Clear(); + for (int i = 0; i < regions.Count; i++) + { + Regions.Add(Xml.GetStringAttribute(regions[i], "name")); + } + + Inited = true; + } + + + public void SetTime(float hour) + { + float day = Math.Max(hour / 24.0f, 0.0f); + float h = hour - ((float)Math.Floor(day) * 24.0f); + CurrentHour = h; + + for (int i = 0; i < Samples.Count; i++) + { + bool lasti = (i >= Samples.Count - 1); + var cur = Samples[i]; + var nxt = Samples[lasti ? 0 : i+1]; + var nxth = lasti ? nxt.hour + 24.0f : nxt.hour; + if (((h >= cur.hour) && (h < nxth)) || lasti) + { + float blendrange = (nxth - cur.hour) - cur.duration; + float blendstart = cur.hour + cur.duration; + float blendrel = h - blendstart; + float blendval = blendrel / blendrange; + float blend = Math.Min(Math.Max(blendval, 0.0f), 1.0f); + NextSampleBlend = blend; + CurrentSampleBlend = 1.0f - blend; + CurrentSampleIndex = i; + break; + } + } + } + + public bool IsNightTime + { + get + { + return (CurrentHour < 6.0f) || (CurrentHour > 20.0f); + } + } + } + + public class TimecycleSample + { + public string name { get; set; } + public float hour { get; set; } + public float duration { get; set; } + public string uw_tc_mod { get; set; } + + public void Init(XmlNode node) + { + name = Xml.GetStringAttribute(node, "name"); + hour = Xml.GetFloatAttribute(node, "hour"); + duration = Xml.GetFloatAttribute(node, "duration"); + uw_tc_mod = Xml.GetStringAttribute(node, "uw_tc_mod"); + } + } + + +} diff --git a/World/TimecycleMods.cs b/World/TimecycleMods.cs new file mode 100644 index 0000000..c24e5fc --- /dev/null +++ b/World/TimecycleMods.cs @@ -0,0 +1,148 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.World +{ + public class TimecycleMods + { + + public Dictionary Dict = new Dictionary(); + + + + public void Init(GameFileCache gameFileCache, Action updateStatus) + { + Dict.Clear(); + + var rpfman = gameFileCache.RpfMan; + + LoadXml(rpfman.GetFileXml("common.rpf\\data\\timecycle\\timecycle_mods_1.xml")); + LoadXml(rpfman.GetFileXml("common.rpf\\data\\timecycle\\timecycle_mods_2.xml")); + LoadXml(rpfman.GetFileXml("common.rpf\\data\\timecycle\\timecycle_mods_3.xml")); + LoadXml(rpfman.GetFileXml("common.rpf\\data\\timecycle\\timecycle_mods_4.xml")); + + LoadXml(rpfman.GetFileXml("update\\update.rpf\\common\\data\\timecycle\\timecycle_mods_1.xml")); + LoadXml(rpfman.GetFileXml("update\\update.rpf\\common\\data\\timecycle\\timecycle_mods_2.xml"));//doesn't exist, but try anyway + LoadXml(rpfman.GetFileXml("update\\update.rpf\\common\\data\\timecycle\\timecycle_mods_3.xml")); + LoadXml(rpfman.GetFileXml("update\\update.rpf\\common\\data\\timecycle\\timecycle_mods_4.xml")); + + if (gameFileCache.EnableDlc) + { + foreach (var dlcrpf in gameFileCache.DlcActiveRpfs) + { + foreach (var file in dlcrpf.AllEntries) + { + if (file.NameLower.EndsWith(".xml") && file.NameLower.StartsWith("timecycle_mods_")) + { + LoadXml(rpfman.GetFileXml(file.Path)); + } + } + } + } + + + gameFileCache.TimeCycleModsDict = Dict; + } + + private void LoadXml(XmlDocument doc) + { + var root = doc.DocumentElement; + if (root == null) + { return; } + + float version = Xml.GetFloatAttribute(root, "version"); + + var modnodes = root.SelectNodes("modifier"); + foreach (XmlNode modnode in modnodes) + { + if (!(modnode is XmlElement)) continue; + TimecycleMod mod = new TimecycleMod(); + mod.Init(modnode); + Dict[mod.nameHash] = mod; + } + + } + + + } + + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class TimecycleMod + { + public string name { get; set; } + public uint nameHash { get; set; } + public int numMods { get; set; } + public int userFlags { get; set; } + + public TimecycleModValue[] Values { get; set; } + public Dictionary Dict { get; set; } + + public void Init(XmlNode node) + { + Dict = new Dictionary(); + + name = Xml.GetStringAttribute(node, "name"); + numMods = Xml.GetIntAttribute(node, "numMods"); + userFlags = Xml.GetIntAttribute(node, "userFlags"); + + string namel = name.ToLower(); + JenkIndex.Ensure(namel); + nameHash = JenkHash.GenHash(namel); + + List vals = new List(); + foreach (XmlNode valnode in node.ChildNodes) + { + if (!(valnode is XmlElement)) continue; + + TimecycleModValue val = new TimecycleModValue(); + val.Init(valnode); + + vals.Add(val); + Dict[val.name] = val; + } + Values = vals.ToArray(); + + } + + public override string ToString() + { + return name + " (" + numMods.ToString() + " mods, userFlags: " + userFlags.ToString() + ")"; + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public class TimecycleModValue + { + public string name { get; set; } + public float value1 { get; set; } + public float value2 { get; set; } + + public void Init(XmlNode node) + { + name = node.Name; + + string valstr = node.InnerText; + string[] valstrs = valstr.Split(' '); + if (valstrs.Length == 2) + { + value1 = FloatUtil.Parse(valstrs[0]); + value2 = FloatUtil.Parse(valstrs[1]); + } + else + { } + } + + public override string ToString() + { + return name + ": " + FloatUtil.ToString(value1) + ", " + FloatUtil.ToString(value2); + } + } + +} diff --git a/World/Trains.cs b/World/Trains.cs new file mode 100644 index 0000000..ec5fbec --- /dev/null +++ b/World/Trains.cs @@ -0,0 +1,433 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using SharpDX; + +namespace CodeWalker.World +{ + public class Trains + { + public volatile bool Inited = false; + public GameFileCache GameFileCache; + + public List TrainTracks { get; set; } = new List(); + + + public void Init(GameFileCache gameFileCache, Action updateStatus) + { + GameFileCache = gameFileCache; + + var rpfman = gameFileCache.RpfMan; + + string trainsfilename = "common.rpf\\data\\levels\\gta5\\trains.xml"; + XmlDocument trainsxml = rpfman.GetFileXml(trainsfilename); + XmlElement trainsdata = trainsxml.DocumentElement; + //TODO: parse train_configs + + + string tracksfilename = "common.rpf\\data\\levels\\gta5\\traintracks.xml"; + XmlDocument tracksxml = rpfman.GetFileXml(tracksfilename); + XmlElement tracksdata = tracksxml.DocumentElement; + XmlNodeList tracks = tracksdata.SelectNodes("train_track"); + + TrainTracks.Clear(); + for (int i = 0; i < tracks.Count; i++) + { + var trackxml = tracks[i]; + TrainTrack tt = new TrainTrack(); + tt.Load(gameFileCache, trackxml); + TrainTracks.Add(tt); + } + + + Inited = true; + } + + } + + public class TrainTrack : BasePathData + { + public string filename { get; set; } + public string trainConfigName { get; set; } + public bool isPingPongTrack { get; set; } + public bool stopsAtStations { get; set; } + public bool MPstopsAtStations { get; set; } + public float speed { get; set; } + public float brakingDist { get; set; } + + + public List Nodes { get; set; } + public int NodeCount { get; set; } + + + public int StationCount + { + get + { + int sc = 0; + foreach (var node in Nodes) + { + if ((node.NodeType == 1) || (node.NodeType == 2) || (node.NodeType == 5)) + { + sc++; + } + } + return sc; + } + } + + + public VertexTypePC[] LinkedVerts { get; set; } + public Vector4[] NodePositions { get; set; } + + public VertexTypePC[] GetPathVertices() + { + return LinkedVerts; + } + public VertexTypePC[] GetTriangleVertices() + { + return null; + } + public Vector4[] GetNodePositions() + { + return NodePositions; + } + + public PathBVH BVH { get; set; } + + public string NodesString { get; set; } + public RpfFileEntry RpfFileEntry { get; set; } + public string Name { get; set; } + public string FilePath { get; set; } + public bool HasChanged { get; set; } + public bool Loaded { get; set; } + + + + + public void Load(GameFileCache gameFileCache, XmlNode node) + { + //load from game file cache + + filename = Xml.GetStringAttribute(node, "filename"); + trainConfigName = Xml.GetStringAttribute(node, "trainConfigName"); + isPingPongTrack = Xml.GetBoolAttribute(node, "isPingPongTrack"); + stopsAtStations = Xml.GetBoolAttribute(node, "stopsAtStations"); + MPstopsAtStations = Xml.GetBoolAttribute(node, "MPstopsAtStations"); + speed = Xml.GetFloatAttribute(node, "speed"); + brakingDist = Xml.GetFloatAttribute(node, "brakingDist"); + + RpfFileEntry = gameFileCache.RpfMan.GetEntry(filename) as RpfFileEntry; + NodesString = gameFileCache.RpfMan.GetFileUTF8Text(filename); + SetNameFromFilename(); + FilePath = Name; + + Load(NodesString); + + BuildVertices(); + + BuildBVH(); + + Loaded = true; + } + + public void Load(byte[] data) + { + filename = string.Empty; + trainConfigName = string.Empty; + RpfFileEntry = new RpfBinaryFileEntry(); + + + string str = Encoding.UTF8.GetString(data); + Load(str); + + BuildVertices(); + + BuildBVH(); + + Loaded = true; + } + + public byte[] Save() + { + NodeCount = Nodes.Count; + StringBuilder sb = new StringBuilder(); + sb.AppendLine(Nodes.Count.ToString()); + foreach (var node in Nodes) + { + var nstr = FloatUtil.GetVector3String(node.Position).Replace(",","") + " " + node.NodeType.ToString(); + sb.AppendLine(nstr); + } + string str = sb.ToString(); + return Encoding.UTF8.GetBytes(str); + } + + + public void SetNameFromFilename() + { + string[] fparts = filename.Replace('\\', '/').Split('/'); + if ((fparts == null) || (fparts.Length == 0)) + { + Name = filename; + } + else + { + Name = fparts[fparts.Length - 1]; + } + } + + + public void Load(string trackstr) + { + //load nodes from a text string... + NodesString = trackstr; + + if (!string.IsNullOrEmpty(trackstr)) + { + string[] trackstrs = trackstr.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + if (trackstrs.Length > 1) + { + int nodecount; + int.TryParse(trackstrs[0], out nodecount); + NodeCount = nodecount; + List nodes = new List(); + for (int i = 1; i < trackstrs.Length; i++) + { + var nodestr = trackstrs[i].Trim(); + var nodevals = nodestr.Split(' '); + if (nodevals.Length == 4) + { + TrainTrackNode ttnode = new TrainTrackNode(); + var x = FloatUtil.Parse(nodevals[0]); + var y = FloatUtil.Parse(nodevals[1]); + var z = FloatUtil.Parse(nodevals[2]); + int nodetype; + int.TryParse(nodevals[3], out nodetype); + ttnode.Position = new Vector3(x, y, z); + ttnode.NodeType = nodetype; + ttnode.Track = this; + ttnode.Index = nodes.Count; + ttnode.Links[0] = (nodes.Count > 0) ? nodes[nodes.Count - 1] : null; + if (ttnode.Links[0] != null) + { + ttnode.Links[0].Links[1] = ttnode; + } + nodes.Add(ttnode); + } + else + { } + } + Nodes = nodes; + } + else + { } + } + else + { } + + if (Nodes == null) + { + Nodes = new List(); + } + + } + + + public void BuildVertices() + { + if ((Nodes != null) && (Nodes.Count > 0)) + { + var nc = Nodes.Count; + var lc = nc - 1; + var lvc = lc * 2; + var np = new Vector4[nc]; + var lv = new VertexTypePC[lvc]; + for (int i = 0; i < nc; i++) + { + np[i] = new Vector4(Nodes[i].Position, 1.0f); + if (i > 0) + { + var l = i - 1; + var li = l * 2; + var ni = li + 1; + lv[li].Position = Nodes[l].Position; + lv[ni].Position = Nodes[i].Position; + lv[li].Colour = (uint)Nodes[l].GetColour(); + lv[ni].Colour = (uint)Nodes[i].GetColour(); + } + } + NodePositions = np; + LinkedVerts = lv; + } + + } + + + + + + public void UpdateBvhForNode(TrainTrackNode node) + { + //this needs to be called when a node's position changes... + //need to recalc the BVH for mouse intersection optimisation purposes. + + //if (BVH == null) return; + //BVH.UpdateForNode(node); + + BuildBVH(); + + //also updates the NodePositions for the visible vertex + if (Nodes != null) + { + for (int i = 0; i < Nodes.Count; i++) + { + if (Nodes[i] == node) + { + NodePositions[i] = new Vector4(node.Position, 1.0f); + break; + } + } + } + + } + + public void BuildBVH() + { + BVH = new PathBVH(Nodes, 10); + } + + + + + + + public TrainTrackNode AddNode(TrainTrackNode afternode = null) + { + int cnt = Nodes?.Count ?? 0; + TrainTrackNode tn = new TrainTrackNode(); + tn.Track = this; + tn.Index = (afternode != null) ? afternode.Index + 1 : cnt; + + if (Nodes == null) + { + Nodes = new List(); + } + + if (afternode != null) + { + TrainTrackNode aln = afternode.Links[1]; + if (aln != null) aln.Links[0] = tn; + afternode.Links[1] = tn; + tn.Links[0] = afternode; + tn.Links[1] = aln; + + int idx = tn.Index; + Nodes.Insert(idx, tn); + + for (int i = 0; i < Nodes.Count; i++) + { + Nodes[i].Index = i; + } + + } + else + { + if (cnt > 0) + { + TrainTrackNode ln = Nodes[cnt - 1]; + tn.Links[0] = ln; + ln.Links[1] = tn; + } + + Nodes.Add(tn); + } + + + NodeCount = Nodes.Count; + + return tn; + } + + public bool RemoveNode(TrainTrackNode node) + { + bool r = false; + + r = Nodes.Remove(node); + + NodeCount = Nodes.Count; + + if (r) + { + var l0 = node.Links[0]; + var l1 = node.Links[1]; + + if (l0 != null) + { + l0.Links[1] = l1; + } + if (l1 != null) + { + l1.Links[0] = l0; + } + + for (int i = 0; i < Nodes.Count; i++) + { + Nodes[i].Index = i; + } + + BuildVertices(); + } + + return r; + } + + + + + + public override string ToString() + { + return Name + ": " + filename + " (" + NodeCount.ToString() + " nodes)"; + } + } + + public class TrainTrackNode : BasePathNode + { + public Vector3 Position { get; set; } + public int NodeType { get; set; } + + public TrainTrack Track { get; set; } + public int Index { get; set; } + public TrainTrackNode[] Links { get; set; } = new TrainTrackNode[2]; + + public int GetColour() + { + switch (NodeType) + { + case 0: return new Color4(1.0f, 0.0f, 0.0f, 1.0f).ToRgba(); + case 1: return new Color4(1.0f, 1.0f, 0.0f, 1.0f).ToRgba(); + case 2: return new Color4(0.0f, 1.0f, 0.0f, 1.0f).ToRgba(); + case 3: return new Color4(0.0f, 1.0f, 1.0f, 1.0f).ToRgba(); + case 4: return new Color4(0.0f, 0.0f, 1.0f, 1.0f).ToRgba(); + case 5: return new Color4(1.0f, 0.0f, 1.0f, 1.0f).ToRgba(); + default: return new Color4(1.0f, 1.0f, 1.0f, 1.0f).ToRgba(); + } + } + + + public void SetPosition(Vector3 pos) + { + Position = pos; + } + + public override string ToString() + { + return Index.ToString() + ": " + NodeType.ToString();// + ": " + FloatUtil.GetVector3String(Position); + } + } + +} diff --git a/World/Water.cs b/World/Water.cs new file mode 100644 index 0000000..954832c --- /dev/null +++ b/World/Water.cs @@ -0,0 +1,213 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.World +{ + public class Water + { + public volatile bool Inited = false; + public GameFileCache GameFileCache; + public List WaterQuads = new List(); + public List CalmingQuads = new List(); + public List WaveQuads = new List(); + + public void Init(GameFileCache gameFileCache, Action updateStatus) + { + GameFileCache = gameFileCache; + + var rpfman = gameFileCache.RpfMan; + + string filename = "common.rpf\\data\\levels\\gta5\\water.xml"; + + XmlDocument waterxml = rpfman.GetFileXml(filename); + + XmlElement waterdata = waterxml.DocumentElement; + + XmlNodeList waterquads = waterdata.SelectNodes("WaterQuads/Item"); + WaterQuads.Clear(); + for (int i = 0; i < waterquads.Count; i++) + { + var waterquad = new WaterQuad(); + waterquad.Init(waterquads[i]); + WaterQuads.Add(waterquad); + } + + XmlNodeList calmingquads = waterdata.SelectNodes("CalmingQuads/Item"); + CalmingQuads.Clear(); + for (int i = 0; i < calmingquads.Count; i++) + { + var calmingquad = new WaterCalmingQuad(); + calmingquad.Init(calmingquads[i]); + CalmingQuads.Add(calmingquad); + } + + XmlNodeList wavequads = waterdata.SelectNodes("WaveQuads/Item"); + WaveQuads.Clear(); + for (int i = 0; i < wavequads.Count; i++) + { + var wavequad = new WaterWaveQuad(); + wavequad.Init(wavequads[i]); + WaveQuads.Add(wavequad); + } + + Inited = true; + } + + + + public void GetVisibleQuads(Camera camera, List quads) + { + if (!Inited) return; + + var vf = camera.ViewFrustum; + for (int i = 0; i < WaterQuads.Count; i++) + { + var quad = WaterQuads[i]; + + Vector3 camrel = quad.BSCenter - camera.Position; + if (vf.ContainsSphereNoClipNoOpt(ref camrel, quad.BSRadius)) + { + quads.Add(quad); + } + } + } + + } + + + public class WaterQuad + { + public float minX { get; set; } + public float maxX { get; set; } + public float minY { get; set; } + public float maxY { get; set; } + public int Type { get; set; } + public bool IsInvisible { get; set; } + public bool HasLimitedDepth { get; set; } + public float z { get; set; } + public float a1 { get; set; } + public float a2 { get; set; } + public float a3 { get; set; } + public float a4 { get; set; } + public bool NoStencil { get; set; } + + public Vector3 BSCenter; + public float BSRadius; + + + public void Init(XmlNode node) + { + minX = Xml.GetChildFloatAttribute(node, "minX", "value"); + maxX = Xml.GetChildFloatAttribute(node, "maxX", "value"); + minY = Xml.GetChildFloatAttribute(node, "minY", "value"); + maxY = Xml.GetChildFloatAttribute(node, "maxY", "value"); + Type = Xml.GetChildIntAttribute(node, "Type", "value"); + IsInvisible = Xml.GetChildBoolAttribute(node, "IsInvisible", "value"); + HasLimitedDepth = Xml.GetChildBoolAttribute(node, "HasLimitedDepth", "value"); + z = Xml.GetChildFloatAttribute(node, "z", "value"); + a1 = Xml.GetChildFloatAttribute(node, "a1", "value"); + a2 = Xml.GetChildFloatAttribute(node, "a2", "value"); + a3 = Xml.GetChildFloatAttribute(node, "a3", "value"); + a4 = Xml.GetChildFloatAttribute(node, "a4", "value"); + NoStencil = Xml.GetChildBoolAttribute(node, "NoStencil", "value"); + + /* + + + + + + + + + + + + + + */ + + + BSCenter = new Vector3((minX + maxX) * 0.5f, (minY + maxY) * 0.5f, z); + BSRadius = new Vector2(maxX - minX, maxY - minY).Length() * 0.5f; + + } + + public override string ToString() + { + return string.Format("{0}, {1}, {2}", FloatUtil.ToString(minX), FloatUtil.ToString(minY), FloatUtil.ToString(z), FloatUtil.ToString(maxX), FloatUtil.ToString(maxY)); + } + + } + + public class WaterCalmingQuad + { + public float minX { get; set; } + public float maxX { get; set; } + public float minY { get; set; } + public float maxY { get; set; } + public float fDampening { get; set; } + + public void Init(XmlNode node) + { + minX = Xml.GetChildFloatAttribute(node, "minX", "value"); + maxX = Xml.GetChildFloatAttribute(node, "maxX", "value"); + minY = Xml.GetChildFloatAttribute(node, "minY", "value"); + maxY = Xml.GetChildFloatAttribute(node, "maxY", "value"); + fDampening = Xml.GetChildFloatAttribute(node, "fDampening", "value"); + + /* + + + + + + */ + + } + + } + + public class WaterWaveQuad + { + public float minX { get; set; } + public float maxX { get; set; } + public float minY { get; set; } + public float maxY { get; set; } + public float Amplitude { get; set; } + public float XDirection { get; set; } + public float YDirection { get; set; } + + public void Init(XmlNode node) + { + minX = Xml.GetChildFloatAttribute(node, "minX", "value"); + maxX = Xml.GetChildFloatAttribute(node, "maxX", "value"); + minY = Xml.GetChildFloatAttribute(node, "minY", "value"); + maxY = Xml.GetChildFloatAttribute(node, "maxY", "value"); + Amplitude = Xml.GetChildFloatAttribute(node, "Amplitude", "value"); + XDirection = Xml.GetChildFloatAttribute(node, "XDirection", "value"); + YDirection = Xml.GetChildFloatAttribute(node, "YDirection", "value"); + + /* + + + + + + + + */ + + } + + } + + + +} diff --git a/World/Weather.cs b/World/Weather.cs new file mode 100644 index 0000000..84f305a --- /dev/null +++ b/World/Weather.cs @@ -0,0 +1,569 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace CodeWalker.World +{ + public class Weather + { + + public Dictionary WeatherGpuFx { get; set; } = new Dictionary(); + public Dictionary WeatherTypes { get; set; } = new Dictionary(); + public List WeatherCycles { get; set; } = new List(); + public WeatherValues CurrentValues; + + public volatile bool Inited = false; + public WeatherType CurrentWeatherType; + public WeatherType NextWeatherType; + public float WeatherChangeTime = 0.33f; + public float CurrentWeatherChangeTime = 0.0f; + public float CurrentWeatherChangeBlend = 0.0f; + public string Region = "GLOBAL"; //URBAN or GLOBAL.. + public WeatherCycleKeyframeRegion CurrentWeatherRegion; + public WeatherCycleKeyframeRegion NextWeatherRegion; + + public Timecycle Timecycle; + public TimecycleMods TimecycleMods; + + public void Init(GameFileCache gameFileCache, Action updateStatus, Timecycle timecycle) + { + Timecycle = timecycle; + var rpfman = gameFileCache.RpfMan; + + //TODO: RpfMan should be able to get the right version? or maybe let gameFileCache do it! + string filename = "common.rpf\\data\\levels\\gta5\\weather.xml"; + if (gameFileCache.EnableDlc) + { + filename = "update\\update.rpf\\common\\data\\levels\\gta5\\weather.xml"; + } + + XmlDocument weatherxml = rpfman.GetFileXml(filename); + + XmlElement weather = weatherxml.DocumentElement; + + XmlNodeList weathergpufx = weather.SelectNodes("WeatherGpuFx/Item"); + WeatherGpuFx.Clear(); + for (int i = 0; i < weathergpufx.Count; i++) + { + var weathergpufxi = new WeatherGpuFx(); + weathergpufxi.Init(weathergpufx[i]); + WeatherGpuFx[weathergpufxi.Name] = weathergpufxi; + } + + XmlNodeList weathertypes = weather.SelectNodes("WeatherTypes/Item"); + WeatherTypes.Clear(); + for (int i = 0; i < weathertypes.Count; i++) + { + var weathertype = new WeatherType(); + weathertype.Init(gameFileCache, weathertypes[i]); + WeatherTypes[weathertype.Name] = weathertype; + } + + XmlNodeList weathercycles = weather.SelectNodes("WeatherCycles/Item"); + WeatherCycles.Clear(); + for (int i = 0; i < weathercycles.Count; i++) + { + var weathercycle = new WeatherCycle(); + weathercycle.Init(weathercycles[i]); + WeatherCycles.Add(weathercycle); + } + + + + if (WeatherTypes.Count > 0) + { + CurrentWeatherType = WeatherTypes.Values.First(); + CurrentWeatherRegion = CurrentWeatherType.GetRegion(Region); + NextWeatherType = CurrentWeatherType; + NextWeatherRegion = NextWeatherType.GetRegion(Region); + } + + + TimecycleMods = new TimecycleMods(); + TimecycleMods.Init(gameFileCache, updateStatus); + + + Inited = true; + } + + public void Update(float elapsed) + { + if (!Inited) return; + + if (CurrentWeatherType != NextWeatherType) + { + CurrentWeatherChangeTime += elapsed; + if (CurrentWeatherChangeTime >= WeatherChangeTime) + { + CurrentWeatherType = NextWeatherType; + CurrentWeatherChangeTime = 0.0f; + } + CurrentWeatherChangeBlend = Math.Min(CurrentWeatherChangeTime / WeatherChangeTime, 1.0f); + } + if (CurrentWeatherType != null) + { + CurrentWeatherRegion = CurrentWeatherType.GetRegion(Region); + } + if (NextWeatherType != null) + { + NextWeatherRegion = NextWeatherType.GetRegion(Region); + } + + CurrentValues.Update(this); + } + + public void SetNextWeather(string name) + { + WeatherTypes.TryGetValue(name, out NextWeatherType); + if (NextWeatherType == null) + { + NextWeatherType = CurrentWeatherType; + } + else + { + CurrentWeatherChangeTime = 0.0f; + } + } + + public float GetDynamicValue(string name) + { + int csi = Timecycle.CurrentSampleIndex; + float csb = Timecycle.CurrentSampleBlend; + if ((CurrentWeatherRegion != null) && (NextWeatherRegion != null)) + { + float cv = CurrentWeatherRegion.GetCurrentValue(name, csi, csb); + float nv = NextWeatherRegion.GetCurrentValue(name, csi, csb); + return cv * (1.0f - CurrentWeatherChangeBlend) + nv * CurrentWeatherChangeBlend; + } + else if (CurrentWeatherRegion != null) + { + return CurrentWeatherRegion.GetCurrentValue(name, csi, csb); + } + //throw new Exception("CurrentWeatherRegion was null."); + return 0.0f; + } + public Vector3 GetDynamicRGB(string rname, string gname, string bname) + { + int csi = Timecycle.CurrentSampleIndex; + float csb = Timecycle.CurrentSampleBlend; + if ((CurrentWeatherRegion != null) && (NextWeatherRegion != null)) + { + float cvr = CurrentWeatherRegion.GetCurrentValue(rname, csi, csb); + float cvg = CurrentWeatherRegion.GetCurrentValue(gname, csi, csb); + float cvb = CurrentWeatherRegion.GetCurrentValue(bname, csi, csb); + float nvr = NextWeatherRegion.GetCurrentValue(rname, csi, csb); + float nvg = NextWeatherRegion.GetCurrentValue(gname, csi, csb); + float nvb = NextWeatherRegion.GetCurrentValue(bname, csi, csb); + Vector3 cv = new Vector3(cvr, cvg, cvb); + Vector3 nv = new Vector3(nvr, nvg, nvb); + return cv * (1.0f - CurrentWeatherChangeBlend) + nv * CurrentWeatherChangeBlend; + } + else if (CurrentWeatherRegion != null) + { + float cvr = CurrentWeatherRegion.GetCurrentValue(rname, csi, csb); + float cvg = CurrentWeatherRegion.GetCurrentValue(gname, csi, csb); + float cvb = CurrentWeatherRegion.GetCurrentValue(bname, csi, csb); + return new Vector3(cvr, cvg, cvb); + } + //throw new Exception("CurrentWeatherRegion was null."); + return Vector3.Zero; + } + public Vector4 GetDynamicRGBA(string rname, string gname, string bname, string aname) + { + int csi = Timecycle.CurrentSampleIndex; + float csb = Timecycle.CurrentSampleBlend; + if ((CurrentWeatherRegion != null) && (NextWeatherRegion != null)) + { + float cvr = CurrentWeatherRegion.GetCurrentValue(rname, csi, csb); + float cvg = CurrentWeatherRegion.GetCurrentValue(gname, csi, csb); + float cvb = CurrentWeatherRegion.GetCurrentValue(bname, csi, csb); + float cva = CurrentWeatherRegion.GetCurrentValue(aname, csi, csb); + float nvr = NextWeatherRegion.GetCurrentValue(rname, csi, csb); + float nvg = NextWeatherRegion.GetCurrentValue(gname, csi, csb); + float nvb = NextWeatherRegion.GetCurrentValue(bname, csi, csb); + float nva = NextWeatherRegion.GetCurrentValue(aname, csi, csb); + Vector4 cv = new Vector4(cvr, cvg, cvb, cva); + Vector4 nv = new Vector4(nvr, nvg, nvb, nva); + return cv * (1.0f - CurrentWeatherChangeBlend) + nv * CurrentWeatherChangeBlend; + } + else if (CurrentWeatherRegion != null) + { + float cvr = CurrentWeatherRegion.GetCurrentValue(rname, csi, csb); + float cvg = CurrentWeatherRegion.GetCurrentValue(gname, csi, csb); + float cvb = CurrentWeatherRegion.GetCurrentValue(bname, csi, csb); + float cva = CurrentWeatherRegion.GetCurrentValue(aname, csi, csb); + return new Vector4(cvr, cvg, cvb, cva); + } + //throw new Exception("CurrentWeatherRegion was null."); + return Vector4.Zero; + } + + } + + public class WeatherGpuFx + { + public string Name { get; set; } + public string SystemType { get; set; } + public string diffuseName { get; set; } + public string distortionTexture { get; set; } + public string diffuseSplashName { get; set; } + public string driveType { get; set; } + public float windInfluence { get; set; } + public float gravity { get; set; } + public string emitterSettingsName { get; set; } + public string renderSettingsName { get; set; } + + public void Init(XmlNode node) + { + Name = Xml.GetChildInnerText(node, "Name"); + SystemType = Xml.GetChildInnerText(node, "SystemType"); + diffuseName = Xml.GetChildInnerText(node, "diffuseName"); + distortionTexture = Xml.GetChildInnerText(node, "distortionTexture"); + diffuseSplashName = Xml.GetChildInnerText(node, "diffuseSplashName"); + driveType = Xml.GetChildInnerText(node, "driveType"); + windInfluence = Xml.GetChildFloatAttribute(node, "windInfluence", "value"); + gravity = Xml.GetChildFloatAttribute(node, "gravity", "value"); + emitterSettingsName = Xml.GetChildInnerText(node, "emitterSettingsName"); + renderSettingsName = Xml.GetChildInnerText(node, "renderSettingsName"); + } + + public override string ToString() + { + return Name; + } + } + + public class WeatherType + { + public MetaHash NameHash { get; set; } + public string Name { get; set; } + public float Sun { get; set; } + public float Cloud { get; set; } + public float WindMin { get; set; } + public float WindMax { get; set; } + public float Rain { get; set; } + public float Snow { get; set; } + public float SnowMist { get; set; } + public float Fog { get; set; } + public float RippleBumpiness { get; set; } + public float RippleMinBumpiness { get; set; } + public float RippleMaxBumpiness { get; set; } + public float RippleBumpinessWindScale { get; set; } + public float RippleScale { get; set; } + public float RippleSpeed { get; set; } + public float RippleVelocityTransfer { get; set; } + public float OceanBumpiness { get; set; } + public float DeepOceanScale { get; set; } + public float OceanNoiseMinAmplitude { get; set; } + public float OceanWaveAmplitude { get; set; } + public float ShoreWaveAmplitude { get; set; } + public float OceanWaveWindScale { get; set; } + public float ShoreWaveWindScale { get; set; } + public float OceanWaveMinAmplitude { get; set; } + public float ShoreWaveMinAmplitude { get; set; } + public float OceanWaveMaxAmplitude { get; set; } + public float ShoreWaveMaxAmplitude { get; set; } + public float OceanFoamIntensity { get; set; } + public float OceanFoamScale { get; set; } + public float RippleDisturb { get; set; } + public float Lightning { get; set; } + public float Sandstorm { get; set; } + public string OldSettingName { get; set; } + public string DropSettingName { get; set; } + public string MistSettingName { get; set; } + public string GroundSettingName { get; set; } + public string TimeCycleFilename { get; set; } + public string CloudSettingsName { get; set; } + + public WeatherCycleKeyframeData TimeCycleData; + + public void Init(GameFileCache gameFileCache, XmlNode node) + { + Name = Xml.GetChildInnerText(node, "Name"); + NameHash = new MetaHash(JenkHash.GenHash(Name.ToLower())); + Sun = Xml.GetChildFloatAttribute(node, "Sun", "value"); + Cloud = Xml.GetChildFloatAttribute(node, "Cloud", "value"); + WindMin = Xml.GetChildFloatAttribute(node, "WindMin", "value"); + WindMax = Xml.GetChildFloatAttribute(node, "WindMax", "value"); + Rain = Xml.GetChildFloatAttribute(node, "Rain", "value"); + Snow = Xml.GetChildFloatAttribute(node, "Snow", "value"); + SnowMist = Xml.GetChildFloatAttribute(node, "SnowMist", "value"); + Fog = Xml.GetChildFloatAttribute(node, "Fog", "value"); + RippleBumpiness = Xml.GetChildFloatAttribute(node, "RippleBumpiness", "value"); + RippleMinBumpiness = Xml.GetChildFloatAttribute(node, "RippleMinBumpiness", "value"); + RippleMaxBumpiness = Xml.GetChildFloatAttribute(node, "RippleMaxBumpiness", "value"); + RippleBumpinessWindScale = Xml.GetChildFloatAttribute(node, "RippleBumpinessWindScale", "value"); + RippleScale = Xml.GetChildFloatAttribute(node, "RippleScale", "value"); + RippleSpeed = Xml.GetChildFloatAttribute(node, "RippleSpeed", "value"); + RippleVelocityTransfer = Xml.GetChildFloatAttribute(node, "RippleVelocityTransfer", "value"); + OceanBumpiness = Xml.GetChildFloatAttribute(node, "OceanBumpiness", "value"); + DeepOceanScale = Xml.GetChildFloatAttribute(node, "DeepOceanScale", "value"); + OceanNoiseMinAmplitude = Xml.GetChildFloatAttribute(node, "OceanNoiseMinAmplitude", "value"); + OceanWaveAmplitude = Xml.GetChildFloatAttribute(node, "OceanWaveAmplitude", "value"); + ShoreWaveAmplitude = Xml.GetChildFloatAttribute(node, "ShoreWaveAmplitude", "value"); + OceanWaveWindScale = Xml.GetChildFloatAttribute(node, "OceanWaveWindScale", "value"); + ShoreWaveWindScale = Xml.GetChildFloatAttribute(node, "ShoreWaveWindScale", "value"); + OceanWaveMinAmplitude = Xml.GetChildFloatAttribute(node, "OceanWaveMinAmplitude", "value"); + ShoreWaveMinAmplitude = Xml.GetChildFloatAttribute(node, "ShoreWaveMinAmplitude", "value"); + OceanWaveMaxAmplitude = Xml.GetChildFloatAttribute(node, "OceanWaveMaxAmplitude", "value"); + ShoreWaveMaxAmplitude = Xml.GetChildFloatAttribute(node, "ShoreWaveMaxAmplitude", "value"); + OceanFoamIntensity = Xml.GetChildFloatAttribute(node, "OceanFoamIntensity", "value"); + OceanFoamScale = Xml.GetChildFloatAttribute(node, "OceanFoamScale", "value"); + RippleDisturb = Xml.GetChildFloatAttribute(node, "RippleDisturb", "value"); + Lightning = Xml.GetChildFloatAttribute(node, "Lightning", "value"); + Sandstorm = Xml.GetChildFloatAttribute(node, "Sandstorm", "value"); + OldSettingName = Xml.GetChildInnerText(node, "OldSettingName"); + DropSettingName = Xml.GetChildInnerText(node, "DropSettingName"); + MistSettingName = Xml.GetChildInnerText(node, "MistSettingName"); + GroundSettingName = Xml.GetChildInnerText(node, "GroundSettingName"); + TimeCycleFilename = Xml.GetChildInnerText(node, "TimeCycleFilename"); + CloudSettingsName = Xml.GetChildInnerText(node, "CloudSettingsName"); + + + if (!string.IsNullOrEmpty(TimeCycleFilename)) + { + + //TODO: RpfMan should be able to get the right version? or maybe let gameFileCache do it! + string fname = TimeCycleFilename.ToLower(); + bool useupd = gameFileCache.EnableDlc; + if (useupd) + { + fname = fname.Replace("common:", "update/update.rpf/common"); + } + XmlDocument tcxml = gameFileCache.RpfMan.GetFileXml(fname); + if (useupd && !tcxml.HasChildNodes) + { + fname = TimeCycleFilename.ToLower(); + tcxml = gameFileCache.RpfMan.GetFileXml(fname); + } + + foreach (XmlNode cycle in tcxml.DocumentElement.ChildNodes) + { + TimeCycleData = new WeatherCycleKeyframeData(); + TimeCycleData.Init(cycle); + } + } + + } + + public WeatherCycleKeyframeRegion GetRegion(string name) + { + if ((TimeCycleData != null) && (TimeCycleData.Regions != null)) + { + WeatherCycleKeyframeRegion r; + if (TimeCycleData.Regions.TryGetValue(name, out r)) + { + return r; + } + return TimeCycleData.Regions.Values.FirstOrDefault(); + } + return null; + } + + public override string ToString() + { + return Name; + } + } + + public class WeatherCycle + { + public string CycleName { get; set; } + public float TimeMult { get; set; } + + public void Init(XmlNode node) + { + CycleName = Xml.GetChildInnerText(node, "CycleName"); + TimeMult = Xml.GetChildFloatAttribute(node, "TimeMult", "value"); + } + + public override string ToString() + { + return CycleName + ", " + TimeMult.ToString(); + } + } + + public class WeatherCycleKeyframeData + { + public string Name { get; set; } + public int RegionCount { get; set; } + public Dictionary Regions { get; set; } + + public void Init(XmlNode node) + { + //read cycle node + Name = Xml.GetStringAttribute(node, "name"); + RegionCount = Xml.GetIntAttribute(node, "regions"); + Regions = new Dictionary(); + foreach (XmlNode child in node.ChildNodes) + { + WeatherCycleKeyframeRegion r = new WeatherCycleKeyframeRegion(); + r.Init(child); + Regions[r.Name] = r; + } + } + + public override string ToString() + { + return Name; + } + } + public class WeatherCycleKeyframeRegion + { + public string Name { get; set; } + public Dictionary Data { get; set; } + + public void Init(XmlNode node) + { + //read region node + Name = Xml.GetStringAttribute(node, "name"); + Data = new Dictionary(); + foreach (XmlNode child in node.ChildNodes) + { + if (child != null) + { + WeatherCycleKeyframeDataEntry d = new WeatherCycleKeyframeDataEntry(); + d.Init(child); + Data[d.Name] = d; + } + } + } + + public float GetCurrentValue(string name, int sample, float curblend) + { + WeatherCycleKeyframeDataEntry e; + if (Data.TryGetValue(name, out e)) + { + if (sample >= e.Values.Length) + { + //System.Windows.Forms.MessageBox.Show("Sample index was out of range: " + sample.ToString()); + sample = e.Values.Length - 1; + } + int nxtsample = (sample < e.Values.Length - 1) ? sample + 1 : 0; + float cv = e.Values[sample]; + float nv = e.Values[nxtsample]; + return cv * curblend + nv * (1.0f - curblend); + } + //throw new Exception("WeatherCycleKeyframeDataEntry " + name + " not found in region " + Name + "."); + return 0.0f; + } + + public override string ToString() + { + return Name; + } + } + public class WeatherCycleKeyframeDataEntry + { + public string Name { get; set; } + public float[] Values { get; set; } + + public void Init(XmlNode node) + { + //read data node + Name = node.Name; + string[] strvals = node.InnerText.Trim().Split(' '); + Values = new float[strvals.Length]; + for (int i = 0; i < strvals.Length; i++) + { + if (!FloatUtil.TryParse(strvals[i], out Values[i])) + { + //System.Windows.Forms.MessageBox.Show("Error parsing float value: " + strvals[i] + "\n" + + // "Node: " + node.OuterXml.ToString()); + //throw new Exception(); + } + } + } + + public override string ToString() + { + return Name; + } + } + + + public struct WeatherValues + { + public Vector3 sunDirection; + public Vector3 moonDirection; + public Vector4 skyZenithCol; + public Vector4 skyZenithTransitionCol; + public Vector4 skyZenithTransition; + public Vector4 skyAzimuthEastCol; + public Vector4 skyAzimuthWestCol; + public Vector4 skyAzimuthTransitionCol; + public float skyAzimuthTransition; + public float skyHdr; + public Vector4 skyPlane; + public Vector3 skySunCol; + public Vector3 skySunDiscCol; + public float skySunDiscSize; + public float skySunHdr; + public Vector3 skySunMie; + public float skySunInfluenceRadius; + public float skySunScatterInten; + public Vector3 skyMoonCol; + public float skyMoonDiscSize; + public float skyMoonIten; + public float skyMoonInfluenceRadius; + public float skyMoonScatterInten; + public float skyStarsIten; + public Vector4 lightDirCol; + public Vector4 lightDirAmbCol; + public float lightDirAmbIntensityMult; + public float lightDirAmbBounce; + public Vector4 lightNaturalAmbDown; + public Vector4 lightNaturalAmbUp; + public float lightNaturalAmbUpIntensityMult; + public Vector4 lightArtificialIntDown; + public Vector4 lightArtificialIntUp; + public Vector4 lightArtificialExtDown; + public Vector4 lightArtificialExtUp; + + public void Update(Weather w) + { + sunDirection = w.GetDynamicRGB("sun_direction_x", "sun_direction_y", "sun_direction_z"); + moonDirection = w.GetDynamicRGB("moon_direction_x", "moon_direction_y", "moon_direction_z"); + skyZenithCol = w.GetDynamicRGBA("sky_zenith_col_r", "sky_zenith_col_g", "sky_zenith_col_b", "sky_zenith_col_inten"); + skyZenithTransitionCol = w.GetDynamicRGBA("sky_zenith_transition_col_r", "sky_zenith_transition_col_g", "sky_zenith_transition_col_b", "sky_zenith_transition_col_inten"); + //skyZenithTransition = w.GetDynamicRGBA("sky_zenith_transition_position", "sky_zenith_transition_east_blend", "sky_zenith_transition_west_blend", "sky_zenith_blend_start"); + skyZenithTransition = w.GetDynamicRGBA("sky_zenith_blend_start", "sky_zenith_transition_east_blend", "sky_zenith_transition_west_blend", "sky_zenith_transition_position"); + skyAzimuthEastCol = w.GetDynamicRGBA("sky_azimuth_east_col_r", "sky_azimuth_east_col_g", "sky_azimuth_east_col_b", "sky_azimuth_east_col_inten"); + skyAzimuthWestCol = w.GetDynamicRGBA("sky_azimuth_west_col_r", "sky_azimuth_west_col_g", "sky_azimuth_west_col_b", "sky_azimuth_west_col_inten"); + skyAzimuthTransitionCol = w.GetDynamicRGBA("sky_azimuth_transition_col_r", "sky_azimuth_transition_col_g", "sky_azimuth_transition_col_b", "sky_azimuth_transition_col_inten"); + skyAzimuthTransition = w.GetDynamicValue("sky_azimuth_transition_position"); + skyHdr = w.GetDynamicValue("sky_hdr"); + skyPlane = w.GetDynamicRGBA("sky_plane_r", "sky_plane_g", "sky_plane_b", "sky_plane_inten"); + skySunCol = w.GetDynamicRGB("sky_sun_col_r", "sky_sun_col_g", "sky_sun_col_b"); + skySunDiscCol = w.GetDynamicRGB("sky_sun_disc_col_r", "sky_sun_disc_col_g", "sky_sun_disc_col_b"); + skySunDiscSize = w.GetDynamicValue("sky_sun_disc_size"); + skySunHdr = w.GetDynamicValue("sky_sun_hdr"); + skySunMie = w.GetDynamicRGB("sky_sun_miephase", "sky_sun_miescatter", "sky_sun_mie_intensity_mult"); + skySunInfluenceRadius = w.GetDynamicValue("sky_sun_influence_radius"); + skySunScatterInten = w.GetDynamicValue("sky_sun_scatter_inten"); + skyMoonCol = w.GetDynamicRGB("sky_moon_col_r", "sky_moon_col_g", "sky_moon_col_b"); + skyMoonDiscSize = w.GetDynamicValue("sky_moon_disc_size"); + skyMoonIten = w.GetDynamicValue("sky_moon_iten"); + skyMoonInfluenceRadius = w.GetDynamicValue("sky_moon_influence_radius"); + skyMoonScatterInten = w.GetDynamicValue("sky_moon_scatter_inten"); + skyStarsIten = w.GetDynamicValue("sky_stars_iten"); + lightDirCol = w.GetDynamicRGBA("light_dir_col_r", "light_dir_col_g", "light_dir_col_b", "light_dir_mult"); + lightDirAmbCol = w.GetDynamicRGBA("light_directional_amb_col_r", "light_directional_amb_col_g", "light_directional_amb_col_b", "light_directional_amb_intensity"); + lightDirAmbIntensityMult = w.GetDynamicValue("light_directional_amb_intensity_mult"); + lightDirAmbBounce = w.GetDynamicValue("light_directional_amb_bounce_enabled"); + lightNaturalAmbDown = w.GetDynamicRGBA("light_natural_amb_down_col_r", "light_natural_amb_down_col_g", "light_natural_amb_down_col_b", "light_natural_amb_down_intensity"); + lightNaturalAmbUp = w.GetDynamicRGBA("light_natural_amb_up_col_r", "light_natural_amb_up_col_g", "light_natural_amb_up_col_b", "light_natural_amb_up_intensity"); + lightNaturalAmbUpIntensityMult = w.GetDynamicValue("light_natural_amb_up_intensity_mult"); + lightArtificialIntDown = w.GetDynamicRGBA("light_artificial_int_down_col_r", "light_artificial_int_down_col_g", "light_artificial_int_down_col_b", "light_artificial_int_down_intensity"); + lightArtificialIntUp = w.GetDynamicRGBA("light_artificial_int_up_col_r", "light_artificial_int_up_col_g", "light_artificial_int_up_col_b", "light_artificial_int_up_intensity"); + lightArtificialExtDown = w.GetDynamicRGBA("light_artificial_ext_down_col_r", "light_artificial_ext_down_col_g", "light_artificial_ext_down_col_b", "light_artificial_ext_down_intensity"); + lightArtificialExtUp = w.GetDynamicRGBA("light_artificial_ext_up_col_r", "light_artificial_ext_up_col_g", "light_artificial_ext_up_col_b", "light_artificial_ext_up_intensity"); + + } + } +} diff --git a/World/Widget.cs b/World/Widget.cs new file mode 100644 index 0000000..0a404f8 --- /dev/null +++ b/World/Widget.cs @@ -0,0 +1,941 @@ +using CodeWalker.Rendering; +using SharpDX; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.World +{ + public abstract class Widget + { + public bool Visible { get; set; } = true; + + public abstract void Update(Camera cam); + + public abstract void Render(DeviceContext context, Camera cam, WidgetShader shader); + + protected bool GetAxisRayHit(Vector3 ax1, Vector3 ax2, Vector3 camrel, Ray ray, out Vector3 pos) + { + //helper method for double sided ray/plane intersection + Vector3 pn = Vector3.Cross(ax1, ax2); + Plane p = new Plane(camrel, pn); + if (ray.Intersects(ref p, out pos)) + { + return true; + } + else + { + p = new Plane(camrel, -pn); + if (ray.Intersects(ref p, out pos)) + { + return true; + } + } + pos = Vector3.Zero; + return false; + } + + protected int GetAxisIndex(WidgetAxis axis) + { + switch (axis) + { + default: + case WidgetAxis.X: return 0; + case WidgetAxis.Y: return 1; + case WidgetAxis.Z: return 2; + } + } + + protected float GetWorldSize(float pxsize, float dist, Camera cam) + { + float sssize = pxsize / cam.Height; + float size = sssize * dist; + if (cam.IsMapView || cam.IsOrthographic) + { + size = sssize * cam.OrthographicSize; + } + return size; + } + } + + public class TransformWidget : Widget + { + public DefaultWidget DefaultWidget { get; set; } = new DefaultWidget(); + public PositionWidget PositionWidget { get; set; } = new PositionWidget(); + public RotationWidget RotationWidget { get; set; } = new RotationWidget(); + public ScaleWidget ScaleWidget { get; set; } = new ScaleWidget(); + + public bool ObjectSpace + { + get { return PositionWidget.ObjectSpace; } + set + { + DefaultWidget.ObjectSpace = value; + PositionWidget.ObjectSpace = value; + RotationWidget.ObjectSpace = value; + } + } + public Vector3 Position + { + get { return PositionWidget.Position; } + set + { + PositionWidget.Position = value; + RotationWidget.Position = value; + ScaleWidget.Position = value; + DefaultWidget.Position = value; + } + } + public Quaternion Rotation + { + get { return RotationWidget.Rotation; } + set + { + PositionWidget.Rotation = value; + RotationWidget.Rotation = value; + ScaleWidget.Rotation = value; + DefaultWidget.Rotation = value; + } + } + public Vector3 Scale + { + get { return ScaleWidget.Scale; } + set { ScaleWidget.Scale = value; } + } + public WidgetMode Mode { get; set; } = WidgetMode.Default; + + + public event WidgetPositionChangeHandler OnPositionChange; + public event WidgetRotationChangeHandler OnRotationChange; + public event WidgetScaleChangeHandler OnScaleChange; + + public bool IsUnderMouse + { + get + { + switch (Mode) + { + default: + case WidgetMode.Default: return false; + case WidgetMode.Position: return (PositionWidget.MousedAxis != WidgetAxis.None); + case WidgetMode.Rotation: return (RotationWidget.MousedAxis != WidgetAxis.None); + case WidgetMode.Scale: return (ScaleWidget.MousedAxis != WidgetAxis.None); + } + } + } + public bool IsDragging + { + get + { + switch (Mode) + { + default: + case WidgetMode.Default: return false; + case WidgetMode.Position: return PositionWidget.IsDragging; + case WidgetMode.Rotation: return RotationWidget.IsDragging; + case WidgetMode.Scale: return ScaleWidget.IsDragging; + } + } + set + { + switch (Mode) + { + case WidgetMode.Position: PositionWidget.IsDragging = value; break; + case WidgetMode.Rotation: RotationWidget.IsDragging = value; break; + case WidgetMode.Scale: ScaleWidget.IsDragging = value; break; + } + } + } + + + public TransformWidget() + { + PositionWidget.OnPositionChange += PositionWidget_OnPositionChange; + RotationWidget.OnRotationChange += RotationWidget_OnRotationChange; + ScaleWidget.OnScaleChange += ScaleWidget_OnScaleChange; + } + + private void PositionWidget_OnPositionChange(Vector3 newpos, Vector3 oldpos) + { + DefaultWidget.Position = newpos; + RotationWidget.Position = newpos; + ScaleWidget.Position = newpos; + OnPositionChange?.Invoke(newpos, oldpos); + } + + private void RotationWidget_OnRotationChange(Quaternion newrot, Quaternion oldrot) + { + DefaultWidget.Rotation = newrot; + PositionWidget.Rotation = newrot; + ScaleWidget.Rotation = newrot; + OnRotationChange?.Invoke(newrot, oldrot); + } + + private void ScaleWidget_OnScaleChange(Vector3 newscale, Vector3 oldscale) + { + OnScaleChange?.Invoke(newscale, oldscale); + } + + public override void Update(Camera cam) + { + if (!Visible) return; + switch (Mode) + { + case WidgetMode.Position: + PositionWidget.Update(cam); + break; + case WidgetMode.Rotation: + RotationWidget.Update(cam); + break; + case WidgetMode.Scale: + ScaleWidget.Update(cam); + break; + case WidgetMode.Default: + DefaultWidget.Update(cam); + break; + } + } + + public override void Render(DeviceContext context, Camera cam, WidgetShader shader) + { + if (!Visible) return; + switch (Mode) + { + case WidgetMode.Position: + PositionWidget.Render(context, cam, shader); + break; + case WidgetMode.Rotation: + RotationWidget.Render(context, cam, shader); + break; + case WidgetMode.Scale: + ScaleWidget.Render(context, cam, shader); + break; + case WidgetMode.Default: + DefaultWidget.Render(context, cam, shader); + break; + } + } + + + } + + public class DefaultWidget : Widget + { + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } = Quaternion.Identity; + + public float Size { get; set; } = 70.0f; + + public bool ObjectSpace { get; set; } = true; + + + public override void Render(DeviceContext context, Camera cam, WidgetShader shader) + { + if (!Visible) return; + + Vector3 camrel = Position - cam.Position; + float dist = camrel.Length(); + float size = GetWorldSize(Size, dist, cam); + + var ori = ObjectSpace ? Rotation : Quaternion.Identity; + + shader.DrawDefaultWidget(context, cam, camrel, ori, size); + } + + public override void Update(Camera cam) + { + //nothing to update here... + } + } + + public class PositionWidget : Widget + { + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } = Quaternion.Identity; + public event WidgetPositionChangeHandler OnPositionChange; + + public WidgetAxis MousedAxis { get; set; } = WidgetAxis.None; + public WidgetAxis DraggedAxis { get; set; } = WidgetAxis.None; + public Vector3 DraggedAxisDir { get; set; } + public Vector3 DraggedAxisSideDir { get; set; } + public Vector3 DragStartPosition { get; set; } + public bool IsDragging { get; set; } + private bool WasDragging = false; + private Vector3 DragStartVec; //projected onto the plane/axis being dragged + + public float Size { get; set; } = 90.0f; + + public bool ObjectSpace { get; set; } = true; + + + public PositionWidget() + { + } + + public override void Render(DeviceContext context, Camera cam, WidgetShader shader) + { + if (!Visible) return; + + Vector3 camrel = Position - cam.Position; + float dist = camrel.Length(); + float size = GetWorldSize(Size, dist, cam); + + WidgetAxis ax = IsDragging ? DraggedAxis : MousedAxis; + + var ori = ObjectSpace ? Rotation : Quaternion.Identity; + + shader.DrawPositionWidget(context, cam, camrel, ori, size, ax); + + } + + public override void Update(Camera cam) + { + if (!Visible) return; + + var ori = ObjectSpace ? Rotation : Quaternion.Identity; + + Vector3 xdir = Vector3.UnitX; + Vector3 ydir = Vector3.UnitY; + Vector3 zdir = Vector3.UnitZ; + Vector3[] axes = { xdir, ydir, zdir }; + Vector3[] sides1 = { ydir, zdir, xdir }; + Vector3[] sides2 = { zdir, xdir, ydir }; + WidgetAxis[] sideax1 = { WidgetAxis.Y, WidgetAxis.Z, WidgetAxis.X }; + WidgetAxis[] sideax2 = { WidgetAxis.Z, WidgetAxis.X, WidgetAxis.Y }; + + + + Quaternion iori = Quaternion.Invert(ori); + Vector3 camrel = iori.Multiply(Position - cam.Position); + Vector3 cdir = Vector3.Normalize(camrel); + Ray ray = cam.MouseRay; + ray.Position = iori.Multiply(ray.Position); + ray.Direction = iori.Multiply(ray.Direction); + + + float dist = camrel.Length(); + float size = GetWorldSize(Size, dist, cam); + float linestart = 0.2f * size; + float lineend = 1.0f * size; + float sideval = 0.4f * size; + float arrowstart = 1.0f * size; + float arrowend = 1.33f * size; + float arrowrad = 0.06f * size; + float axhitrad = 0.07f * size; + float axhitstart = 0.2f * size; + float axhitend = 1.33f * size; + float sidehitend = 0.5f * size; + float sidehitstart = 0.25f * size; + float allhitrad = 0.07f * size; + + //test for single and double axes hits + BoundingBox bb = new BoundingBox(); + BoundingBox bb2 = new BoundingBox(); + float hitd = float.MaxValue; + float d, d2; + WidgetAxis hitax = WidgetAxis.None; + for (int i = 0; i < 3; i++) + { + WidgetAxis ax = (WidgetAxis)(1 << i); + Vector3 s = sides1[i] * axhitrad + sides2[i] * axhitrad; + bb.Minimum = camrel - s + axes[i] * axhitstart; + bb.Maximum = camrel + s + axes[i] * axhitend; + if (ray.Intersects(ref bb, out d)) //single axis + { + if (d < hitd) + { + hitd = d; + hitax = ax; + } + } + for (int n = i + 1; n < 3; n++) + { + //double axis hit test - don't hit if in the central area (L shape hit area) + WidgetAxis ax2 = (WidgetAxis)(1 << n); + bb.Minimum = camrel; + bb.Maximum = camrel + axes[i] * sidehitend + axes[n] * sidehitend; + bb2.Minimum = camrel; + bb2.Maximum = camrel + axes[i] * sidehitstart + axes[n] * sidehitstart; + if (ray.Intersects(ref bb, out d) && !ray.Intersects(ref bb2, out d2)) + { + if (d < hitd) + { + hitd = d; + hitax = ax | ax2; + } + } + } + } + + //small box at the center for all axes hit. + Vector3 ss = (axes[0] + axes[1] + axes[2]) * allhitrad; + bb.Minimum = camrel - ss; + bb.Maximum = camrel + ss; + if (ray.Intersects(ref bb, out d)) + { + if (d < hitd) + { + hitd = d; + hitax = WidgetAxis.XYZ; + } + } + + MousedAxis = hitax; + + + if (IsDragging && !WasDragging) + { + //drag start. mark the start vector and axes + DraggedAxis = MousedAxis; + DragStartPosition = Position; + DraggedAxisDir = axes[0]; + DraggedAxisSideDir = axes[1]; + + switch (DraggedAxis) + { + case WidgetAxis.XZ: DraggedAxisSideDir = axes[2]; break; + case WidgetAxis.YZ: DraggedAxisDir = axes[1]; DraggedAxisSideDir = axes[2]; break; + case WidgetAxis.Y: DraggedAxisDir = axes[1]; break; + case WidgetAxis.Z: DraggedAxisDir = axes[2]; break; + } + switch (DraggedAxis) //find the best second axis to use, for single axis motion only. + { + case WidgetAxis.X: + case WidgetAxis.Y: + case WidgetAxis.Z: + int curax = GetAxisIndex(DraggedAxis); + int minax = 0; + float mindp = float.MaxValue; + for (int i = 0; i < 3; i++) + { + if (i != curax) + { + float dp = Math.Abs(Vector3.Dot(cdir, axes[i])); + if (dp < mindp) + { + mindp = dp; + minax = i; + } + } + } + DraggedAxisSideDir = axes[minax]; + break; + } + if (DraggedAxis == WidgetAxis.XYZ) + { + //all axes, move in the screen plane + float ad1 = Math.Abs(Vector3.Dot(cdir, Vector3.UnitY)); + float ad2 = Math.Abs(Vector3.Dot(cdir, Vector3.UnitZ)); + DraggedAxisDir = Vector3.Normalize(Vector3.Cross(cdir, (ad1 > ad2) ? Vector3.UnitY : Vector3.UnitZ)); + DraggedAxisSideDir = Vector3.Normalize(Vector3.Cross(cdir, DraggedAxisDir)); + } + + + bool hit = GetAxisRayHit(DraggedAxisDir, DraggedAxisSideDir, camrel, ray, out DragStartVec); + if ((MousedAxis == WidgetAxis.None) || !hit) + { + IsDragging = false; + } + } + else if (IsDragging) + { + //continue drag. + Vector3 newvec; + bool hit = GetAxisRayHit(DraggedAxisDir, DraggedAxisSideDir, camrel, ray, out newvec); + if (hit) + { + Vector3 diff = newvec - DragStartVec; + switch (DraggedAxis) + { + case WidgetAxis.X: diff.Y = 0; diff.Z = 0; break; + case WidgetAxis.Y: diff.X = 0; diff.Z = 0; break; + case WidgetAxis.Z: diff.X = 0; diff.Y = 0; break; + } + + if (ObjectSpace) + { + diff = ori.Multiply(diff); + } + + if (diff.Length() < 10000.0f) //limit movement in one go, to avoid losing the widget... + { + Vector3 oldpos = Position; + Position = DragStartPosition + diff; + if (Position != oldpos) + { + OnPositionChange?.Invoke(Position, oldpos); + } + } + } + } + + + + WasDragging = IsDragging; + } + + + } + + public class RotationWidget : Widget + { + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } = Quaternion.Identity; + public event WidgetRotationChangeHandler OnRotationChange; + + public WidgetAxis MousedAxis { get; set; } = WidgetAxis.None; + public WidgetAxis DraggedAxis { get; set; } = WidgetAxis.None; + public Vector3 DraggedAxisDir { get; set; } + public Vector3 DraggedAxisSideDir1 { get; set; } + public Vector3 DraggedAxisSideDir2 { get; set; } + public Quaternion DragStartRotation { get; set; } + public bool IsDragging { get; set; } + private bool WasDragging = false; + private Vector3 DragStartVec; //projected onto the plane/axis being dragged + + public float Size { get; set; } = 100.0f; + + public bool ObjectSpace { get; set; } = true; + public WidgetAxis EnableAxes { get; set; } = WidgetAxis.XYZ; + + public RotationWidget() + { + } + + public override void Render(DeviceContext context, Camera cam, WidgetShader shader) + { + if (!Visible) return; + + Vector3 camrel = Position - cam.Position; + float dist = camrel.Length(); + float size = GetWorldSize(Size, dist, cam); + + WidgetAxis ax = IsDragging ? DraggedAxis : MousedAxis; + + var ori = ObjectSpace ? Rotation : Quaternion.Identity; + + shader.DrawRotationWidget(context, cam, camrel, ori, size, ax, EnableAxes); + } + + public override void Update(Camera cam) + { + if (!Visible) return; + + var ori = ObjectSpace ? Rotation : Quaternion.Identity; + Vector3 xdir = ori.Multiply(Vector3.UnitX); + Vector3 ydir = ori.Multiply(Vector3.UnitY); + Vector3 zdir = ori.Multiply(Vector3.UnitZ); + Vector3[] axes = { xdir, ydir, zdir }; + Vector3[] sides1 = { ydir, zdir, xdir }; + Vector3[] sides2 = { zdir, xdir, ydir }; + + Ray ray = cam.MouseRay; + Vector3 camrel = Position - cam.Position; + float dist = camrel.Length(); + float size = GetWorldSize(Size, dist, cam); + float ocircsize = 1.0f * size; //outer ring radius + float icircsize = 0.75f * size; //inner ring radius + float icircthick = 0.2f * size; //inner ring hit width + float ocircthick = 0.13f * size;//outer ring hit width + float icirchiti = icircsize - icircthick; + float icirchito = icircsize + icircthick; + float ocirchiti = ocircsize - ocircthick; + float ocirchito = ocircsize + ocircthick; + + + //test for the main axes hits + float cullvalue = -0.18f; + float hitd = float.MaxValue; + Vector3 hitp = camrel; + Vector3 hitrel = Vector3.Zero; + WidgetAxis hitax = WidgetAxis.None; + Vector3 hitaxd = Vector3.UnitX; + Vector3 hitax1 = Vector3.UnitY; + Vector3 hitax2 = Vector3.UnitZ; + for (int i = 0; i < 3; i++) + { + WidgetAxis ax = (WidgetAxis)(1 << i); + if ((ax & EnableAxes) == 0) continue; + Vector3 s1 = sides1[i]; + Vector3 s2 = sides2[i]; + if (GetAxisRayHit(s1, s2, camrel, ray, out hitp)) + { + float hitdist = hitp.Length(); + float hitreld = (camrel.Length() - hitdist) / size; + if (hitreld < cullvalue) continue; //this hit was at the backside of the widget; ignore + Vector3 thitrel = hitp - camrel; + float hitrad = thitrel.Length(); + if ((hitrad > icirchiti) && (hitrad < icirchito) && (hitdist < hitd)) + { + hitd = hitdist; + hitax = ax; + hitax1 = s1; + hitax2 = s2; + hitrel = thitrel; + hitaxd = axes[i]; + } + } + } + + //test for the outer ring hit + if ((hitax == WidgetAxis.None) && (EnableAxes == WidgetAxis.XYZ)) + { + Vector3 sdir = Vector3.Normalize(camrel); + //if (cam.IsMapView || cam.IsOrthographic) + //{ + // sdir = cam.ViewDirection; + //} + float ad1 = Math.Abs(Vector3.Dot(sdir, Vector3.UnitY)); + float ad2 = Math.Abs(Vector3.Dot(sdir, Vector3.UnitZ)); + Vector3 ax1 = Vector3.Normalize(Vector3.Cross(sdir, (ad1 > ad2) ? Vector3.UnitY : Vector3.UnitZ)); + Vector3 ax2 = Vector3.Normalize(Vector3.Cross(sdir, ax1)); + if (GetAxisRayHit(ax1, ax2, camrel, ray, out hitp)) + { + Vector3 thitrel = hitp - camrel; + float hitrad = thitrel.Length(); + if ((hitrad > ocirchiti) && (hitrad < ocirchito)) + { + hitax = WidgetAxis.XYZ; + hitax1 = ax1; + hitax2 = ax2; + hitrel = thitrel; + hitaxd = sdir; + } + } + } + + + MousedAxis = hitax; + + + if (IsDragging && !WasDragging) + { + //drag start. mark the start vector and axes + DraggedAxis = MousedAxis; + DragStartRotation = Rotation; + DraggedAxisDir = hitaxd; + DraggedAxisSideDir1 = hitax1; + DraggedAxisSideDir2 = hitax2; + + bool hit = GetAxisRayHit(DraggedAxisSideDir1, DraggedAxisSideDir2, camrel, ray, out DragStartVec); + if ((MousedAxis == WidgetAxis.None) || !hit) + { + IsDragging = false; + } + } + else if (IsDragging) + { + //continue drag. + Vector3 newvec; + bool hit = GetAxisRayHit(DraggedAxisSideDir1, DraggedAxisSideDir2, camrel, ray, out newvec); + if (hit) + { + Vector3 diff = newvec - DragStartVec; + if (diff.Length() < 10000.0f) //put some limit to the plane intersection... + { + Vector3 nv = Vector3.Normalize(newvec - camrel); + Vector3 ov = Vector3.Normalize(DragStartVec - camrel); + float na = AngleOnAxes(nv, DraggedAxisSideDir1, DraggedAxisSideDir2); + float oa = AngleOnAxes(ov, DraggedAxisSideDir1, DraggedAxisSideDir2); + float a = na - oa; + Quaternion rot = Quaternion.RotationAxis(DraggedAxisDir, a); + Quaternion oldrot = Rotation; + Rotation = Quaternion.Normalize(Quaternion.Multiply(rot, DragStartRotation)); + if (Rotation != oldrot) + { + OnRotationChange?.Invoke(Rotation, oldrot); + } + } + } + } + + + WasDragging = IsDragging; + } + + private float AngleOnAxes(Vector3 v, Vector3 ax1, Vector3 ax2) + { + float d1 = Vector3.Dot(v, ax1); + float d2 = Vector3.Dot(v, ax2); + return (float)Math.Atan2(d2, d1); + } + + } + + public class ScaleWidget : Widget + { + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } = Quaternion.Identity; + public Vector3 Scale { get; set; } = Vector3.One; + public event WidgetScaleChangeHandler OnScaleChange; + + public WidgetAxis MousedAxis { get; set; } = WidgetAxis.None; + public WidgetAxis DraggedAxis { get; set; } = WidgetAxis.None; + public Vector3 DraggedAxisDir { get; set; } + public Vector3 DraggedAxisSideDir { get; set; } + public Vector3 DragStartScale { get; set; } + public bool IsDragging { get; set; } + private bool WasDragging = false; + private Vector3 DragStartVec; //projected onto the plane/axis being dragged + + public bool LockXY { get; set; } = true; + + public float Size { get; set; } = 90.0f; + + public ScaleWidget() + { + } + + public override void Render(DeviceContext context, Camera cam, WidgetShader shader) + { + if (!Visible) return; + + Vector3 camrel = Position - cam.Position; + float dist = camrel.Length(); + float size = GetWorldSize(Size, dist, cam); + + WidgetAxis ax = IsDragging ? DraggedAxis : MousedAxis; + + var ori = Rotation; //scale is always in object space. + + shader.DrawScaleWidget(context, cam, camrel, ori, size, ax); + } + + public override void Update(Camera cam) + { + if (!Visible) return; + + var ori = Rotation;// : Quaternion.Identity; + + Vector3 xdir = Vector3.UnitX; + Vector3 ydir = Vector3.UnitY; + Vector3 zdir = Vector3.UnitZ; + Vector3[] axes = { xdir, ydir, zdir }; + Vector3[] sides1 = { ydir, zdir, xdir }; + Vector3[] sides2 = { zdir, xdir, ydir }; + WidgetAxis[] sideax1 = { WidgetAxis.Y, WidgetAxis.Z, WidgetAxis.X }; + WidgetAxis[] sideax2 = { WidgetAxis.Z, WidgetAxis.X, WidgetAxis.Y }; + + + + Quaternion iori = Quaternion.Invert(ori); + Vector3 camrel = iori.Multiply(Position - cam.Position); + Vector3 cdir = Vector3.Normalize(camrel); + Ray ray = cam.MouseRay; + ray.Position = iori.Multiply(ray.Position); + ray.Direction = iori.Multiply(ray.Direction); + + + float dist = camrel.Length(); + float size = GetWorldSize(Size, dist, cam); + + float axhitrad = 0.09f * size; + float axhitstart = 0.4f * size; + float axhitend = 1.33f * size; + float innertri = 0.7f * size; + float outertri = 1.0f * size; + + //test for single and double axes hits + BoundingBox bb = new BoundingBox(); + float hitd = float.MaxValue; + float d; + Vector3 hitp; + WidgetAxis hitax = WidgetAxis.None; + for (int i = 0; i < 3; i++) + { + WidgetAxis ax = (WidgetAxis)(1 << i); + Vector3 s = sides1[i] * axhitrad + sides2[i] * axhitrad; + bb.Minimum = camrel - s + axes[i] * axhitstart; + bb.Maximum = camrel + s + axes[i] * axhitend; + if (ray.Intersects(ref bb, out d)) //single axis + { + if (d < hitd) + { + hitd = d; + hitax = ax; + } + } + + Vector3 s1 = axes[i]; + Vector3 s2 = sides1[i]; + if (GetAxisRayHit(s1, s2, camrel, ray, out hitp)) + { + //test if hitp is within the inner triangle - uniform scale + //test if hitp is within the outer triangle - 2 axes scale + float hitpl = hitp.Length(); + if (hitpl > hitd) continue; + Vector3 hitrel = hitp - camrel; + float d1 = Vector3.Dot(hitrel, s1); + float d2 = Vector3.Dot(hitrel, s2); + + if ((d1 > 0) && (d2 > 0)) + { + if ((d1 < innertri) && (d2 < innertri) && ((d1 + d2) < innertri)) + { + hitd = hitpl; + hitax = WidgetAxis.XYZ; + } + else if ((d1 < outertri) && (d2 < outertri) && ((d1 + d2) < outertri)) + { + hitd = hitpl; + hitax = ax | sideax1[i]; + } + } + } + } + if (LockXY) + { + switch (hitax) + { + case WidgetAxis.X: + case WidgetAxis.Y: + hitax = WidgetAxis.XY; + break; + case WidgetAxis.XZ: + case WidgetAxis.YZ: + hitax = WidgetAxis.XYZ; + break; + } + } + + + MousedAxis = hitax; + + + if (IsDragging && !WasDragging) + { + //drag start. mark the start vector and axes + DraggedAxis = MousedAxis; + DragStartScale = Scale; + DraggedAxisDir = axes[0]; + DraggedAxisSideDir = axes[1]; + + switch (DraggedAxis) + { + case WidgetAxis.XZ: DraggedAxisSideDir = axes[2]; break; + case WidgetAxis.YZ: DraggedAxisDir = axes[1]; DraggedAxisSideDir = axes[2]; break; + case WidgetAxis.Y: DraggedAxisDir = axes[1]; break; + case WidgetAxis.Z: DraggedAxisDir = axes[2]; break; + } + switch (DraggedAxis) //find the best second axis to use, for single axis motion only. + { + case WidgetAxis.X: + case WidgetAxis.Y: + case WidgetAxis.Z: + int curax = GetAxisIndex(DraggedAxis); + int minax = 0; + float mindp = float.MaxValue; + for (int i = 0; i < 3; i++) + { + if (i != curax) + { + float dp = Math.Abs(Vector3.Dot(cdir, axes[i])); + if (dp < mindp) + { + mindp = dp; + minax = i; + } + } + } + DraggedAxisSideDir = axes[minax]; + break; + } + if (DraggedAxis == WidgetAxis.XYZ) + { + //all axes, move in the screen plane + float ad1 = Math.Abs(Vector3.Dot(cdir, Vector3.UnitY)); + float ad2 = Math.Abs(Vector3.Dot(cdir, Vector3.UnitZ)); + DraggedAxisDir = Vector3.Normalize(Vector3.Cross(cdir, (ad1 > ad2) ? Vector3.UnitY : Vector3.UnitZ)); + DraggedAxisSideDir = Vector3.Normalize(Vector3.Cross(cdir, DraggedAxisDir)); + } + + + bool hit = GetAxisRayHit(DraggedAxisDir, DraggedAxisSideDir, camrel, ray, out DragStartVec); + if ((MousedAxis == WidgetAxis.None) || !hit) + { + IsDragging = false; + } + } + else if (IsDragging) + { + //continue drag. + Vector3 newvec; + bool hit = GetAxisRayHit(DraggedAxisDir, DraggedAxisSideDir, camrel, ray, out newvec); + if (hit) + { + Vector3 diff = newvec - DragStartVec; + switch (DraggedAxis) + { + case WidgetAxis.X: diff.Y = 0; diff.Z = 0; break; + case WidgetAxis.Y: diff.X = 0; diff.Z = 0; break; + case WidgetAxis.Z: diff.X = 0; diff.Y = 0; break; + } + + //diff = ori.Multiply(diff); + Vector3 ods = DragStartVec - camrel;// ori.Multiply(DragStartVec); + float odl = Math.Max(ods.Length(), 0.0001f); //don't divide by 0 + float ndl = Math.Max((ods + diff).Length(), 0.001f); //don't scale to 0 size + float dl = ndl / odl; + + if (diff.Length() < 10000.0f) //limit movement in one go, to avoid crazy values... + { + Vector3 oldscale = Scale; + Vector3 sv = Vector3.One; + switch (DraggedAxis) + { + case WidgetAxis.X: sv = new Vector3(dl, 1, 1); break; + case WidgetAxis.Y: sv = new Vector3(1, dl, 1); break; + case WidgetAxis.Z: sv = new Vector3(1, 1, dl); break; + case WidgetAxis.XY: sv = new Vector3(dl, dl, 1); break; + case WidgetAxis.YZ: sv = new Vector3(1, dl, dl); break; + case WidgetAxis.XZ: sv = new Vector3(dl, 1, dl); break; + case WidgetAxis.XYZ: sv = new Vector3(dl); break; + } + Scale = DragStartScale * sv; + + if (Scale != oldscale) + { + OnScaleChange?.Invoke(Scale, oldscale); + } + } + } + } + + WasDragging = IsDragging; + } + + } + + + public delegate void WidgetPositionChangeHandler(Vector3 newpos, Vector3 oldpos); + public delegate void WidgetRotationChangeHandler(Quaternion newrot, Quaternion oldrot); + public delegate void WidgetScaleChangeHandler(Vector3 newscale, Vector3 oldscale); + + public enum WidgetMode + { + Default = 0, + Position = 1, + Rotation = 2, + Scale = 3, + } + public enum WidgetAxis + { + None = 0, + X = 1, + Y = 2, + Z = 4, + XY = 3, + XZ = 5, + YZ = 6, + XYZ = 7, + } + + + + + + +} diff --git a/WorldForm.Designer.cs b/WorldForm.Designer.cs new file mode 100644 index 0000000..97e258c --- /dev/null +++ b/WorldForm.Designer.cs @@ -0,0 +1,3434 @@ +using CodeWalker.WinForms; + +namespace CodeWalker +{ + partial class WorldForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WorldForm)); + this.FolderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); + this.StatusStrip = new System.Windows.Forms.StatusStrip(); + this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.MousedLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.StatsLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.ModelComboBox = new System.Windows.Forms.ComboBox(); + this.ToolsPanel = new System.Windows.Forms.Panel(); + this.ToolsDragPanel = new System.Windows.Forms.Panel(); + this.AboutButton = new System.Windows.Forms.Button(); + this.ToolsButton = new System.Windows.Forms.Button(); + this.ToolsPanelExpandButton = new System.Windows.Forms.Button(); + this.ToolsTabControl = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.ViewTabControl = new System.Windows.Forms.TabControl(); + this.ViewWorldTabPage = new System.Windows.Forms.TabPage(); + this.EnableModsCheckBox = new System.Windows.Forms.CheckBox(); + this.label30 = new System.Windows.Forms.Label(); + this.DlcLevelComboBox = new System.Windows.Forms.ComboBox(); + this.EnableDlcCheckBox = new System.Windows.Forms.CheckBox(); + this.WorldYmapWeatherFilterCheckBox = new System.Windows.Forms.CheckBox(); + this.WorldYmapTimeFilterCheckBox = new System.Windows.Forms.CheckBox(); + this.WorldScriptedYmapsCheckBox = new System.Windows.Forms.CheckBox(); + this.WorldDetailDistLabel = new System.Windows.Forms.Label(); + this.label18 = new System.Windows.Forms.Label(); + this.WorldDetailDistTrackBar = new System.Windows.Forms.TrackBar(); + this.WorldLodDistLabel = new System.Windows.Forms.Label(); + this.label16 = new System.Windows.Forms.Label(); + this.WorldLodDistTrackBar = new System.Windows.Forms.TrackBar(); + this.label15 = new System.Windows.Forms.Label(); + this.WorldMaxLodComboBox = new System.Windows.Forms.ComboBox(); + this.ViewYmapsTabPage = new System.Windows.Forms.TabPage(); + this.ShowYmapChildrenCheckBox = new System.Windows.Forms.CheckBox(); + this.label2 = new System.Windows.Forms.Label(); + this.DetailTrackBar = new System.Windows.Forms.TrackBar(); + this.DynamicLODCheckBox = new System.Windows.Forms.CheckBox(); + this.YmapsTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.ViewModelTabPage = new System.Windows.Forms.TabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.ViewModeComboBox = new System.Windows.Forms.ComboBox(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.label27 = new System.Windows.Forms.Label(); + this.CameraPositionTextBox = new System.Windows.Forms.TextBox(); + this.AddSelectionMarkerButton = new System.Windows.Forms.Button(); + this.AddCurrentPositonMarkerButton = new System.Windows.Forms.Button(); + this.ResetMarkersButton = new System.Windows.Forms.Button(); + this.ClearMarkersButton = new System.Windows.Forms.Button(); + this.GoToButton = new System.Windows.Forms.Button(); + this.ShowLocatorCheckBox = new System.Windows.Forms.CheckBox(); + this.label6 = new System.Windows.Forms.Label(); + this.LocateTextBox = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.AddMarkersButton = new System.Windows.Forms.Button(); + this.MultiFindTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.label25 = new System.Windows.Forms.Label(); + this.SelectionModeComboBox = new System.Windows.Forms.ComboBox(); + this.SelectionNameTextBox = new System.Windows.Forms.TextBox(); + this.SelectionTabControl = new System.Windows.Forms.TabControl(); + this.SelectionEntityTabPage = new System.Windows.Forms.TabPage(); + this.SelEntityPropertyGrid = new CodeWalker.WinForms.ReadOnlyPropertyGrid(); + this.SelectionArchetypeTabPage = new System.Windows.Forms.TabPage(); + this.SelArchetypePropertyGrid = new CodeWalker.WinForms.ReadOnlyPropertyGrid(); + this.SelectionDrawableTabPage = new System.Windows.Forms.TabPage(); + this.tabControl3 = new System.Windows.Forms.TabControl(); + this.tabPage11 = new System.Windows.Forms.TabPage(); + this.SelDrawablePropertyGrid = new CodeWalker.WinForms.ReadOnlyPropertyGrid(); + this.tabPage12 = new System.Windows.Forms.TabPage(); + this.SelDrawableModelsTreeView = new CodeWalker.WinForms.TreeViewFix(); + this.tabPage13 = new System.Windows.Forms.TabPage(); + this.SelDrawableTexturesTreeView = new CodeWalker.WinForms.TreeViewFix(); + this.SelectionExtensionTabPage = new System.Windows.Forms.TabPage(); + this.SelExtensionPropertyGrid = new CodeWalker.WinForms.ReadOnlyPropertyGrid(); + this.MouseSelectCheckBox = new System.Windows.Forms.CheckBox(); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.OptionsTabControl = new System.Windows.Forms.TabControl(); + this.tabPage8 = new System.Windows.Forms.TabPage(); + this.AdvancedSettingsButton = new System.Windows.Forms.Button(); + this.ControlSettingsButton = new System.Windows.Forms.Button(); + this.MapViewDetailLabel = new System.Windows.Forms.Label(); + this.label28 = new System.Windows.Forms.Label(); + this.MapViewDetailTrackBar = new System.Windows.Forms.TrackBar(); + this.CameraModeComboBox = new System.Windows.Forms.ComboBox(); + this.label24 = new System.Windows.Forms.Label(); + this.WaterQuadsCheckBox = new System.Windows.Forms.CheckBox(); + this.FieldOfViewLabel = new System.Windows.Forms.Label(); + this.label22 = new System.Windows.Forms.Label(); + this.TimedEntitiesAlwaysOnCheckBox = new System.Windows.Forms.CheckBox(); + this.GrassCheckBox = new System.Windows.Forms.CheckBox(); + this.InteriorsCheckBox = new System.Windows.Forms.CheckBox(); + this.CollisionMeshLayerDrawableCheckBox = new System.Windows.Forms.CheckBox(); + this.CollisionMeshLayer2CheckBox = new System.Windows.Forms.CheckBox(); + this.CollisionMeshLayer1CheckBox = new System.Windows.Forms.CheckBox(); + this.label13 = new System.Windows.Forms.Label(); + this.CollisionMeshLayer0CheckBox = new System.Windows.Forms.CheckBox(); + this.label12 = new System.Windows.Forms.Label(); + this.CollisionMeshRangeTrackBar = new System.Windows.Forms.TrackBar(); + this.CollisionMeshesCheckBox = new System.Windows.Forms.CheckBox(); + this.FullScreenCheckBox = new System.Windows.Forms.CheckBox(); + this.TimedEntitiesCheckBox = new System.Windows.Forms.CheckBox(); + this.FieldOfViewTrackBar = new System.Windows.Forms.TrackBar(); + this.tabPage14 = new System.Windows.Forms.TabPage(); + this.WireframeCheckBox = new System.Windows.Forms.CheckBox(); + this.RenderModeComboBox = new System.Windows.Forms.ComboBox(); + this.label11 = new System.Windows.Forms.Label(); + this.TextureSamplerComboBox = new System.Windows.Forms.ComboBox(); + this.TextureCoordsComboBox = new System.Windows.Forms.ComboBox(); + this.label10 = new System.Windows.Forms.Label(); + this.AnisotropicFilteringCheckBox = new System.Windows.Forms.CheckBox(); + this.ProxiesCheckBox = new System.Windows.Forms.CheckBox(); + this.WaitForChildrenCheckBox = new System.Windows.Forms.CheckBox(); + this.label14 = new System.Windows.Forms.Label(); + this.tabPage9 = new System.Windows.Forms.TabPage(); + this.NavMeshesCheckBox = new System.Windows.Forms.CheckBox(); + this.TrainPathsCheckBox = new System.Windows.Forms.CheckBox(); + this.PathsDepthClipCheckBox = new System.Windows.Forms.CheckBox(); + this.PathBoundsCheckBox = new System.Windows.Forms.CheckBox(); + this.SelectionWidgetCheckBox = new System.Windows.Forms.CheckBox(); + this.MarkerStyleComboBox = new System.Windows.Forms.ComboBox(); + this.ShowToolbarCheckBox = new System.Windows.Forms.CheckBox(); + this.label4 = new System.Windows.Forms.Label(); + this.LocatorStyleComboBox = new System.Windows.Forms.ComboBox(); + this.label5 = new System.Windows.Forms.Label(); + this.MarkerDepthClipCheckBox = new System.Windows.Forms.CheckBox(); + this.label9 = new System.Windows.Forms.Label(); + this.PathsCheckBox = new System.Windows.Forms.CheckBox(); + this.SelectionBoundsCheckBox = new System.Windows.Forms.CheckBox(); + this.BoundsDepthClipCheckBox = new System.Windows.Forms.CheckBox(); + this.BoundsRangeTrackBar = new System.Windows.Forms.TrackBar(); + this.BoundsStyleComboBox = new System.Windows.Forms.ComboBox(); + this.label8 = new System.Windows.Forms.Label(); + this.tabPage10 = new System.Windows.Forms.TabPage(); + this.WeatherRegionComboBox = new System.Windows.Forms.ComboBox(); + this.label29 = new System.Windows.Forms.Label(); + this.CloudParamTrackBar = new System.Windows.Forms.TrackBar(); + this.CloudParamComboBox = new System.Windows.Forms.ComboBox(); + this.label23 = new System.Windows.Forms.Label(); + this.CloudsComboBox = new System.Windows.Forms.ComboBox(); + this.label21 = new System.Windows.Forms.Label(); + this.TimeSpeedLabel = new System.Windows.Forms.Label(); + this.label20 = new System.Windows.Forms.Label(); + this.TimeSpeedTrackBar = new System.Windows.Forms.TrackBar(); + this.TimeStartStopButton = new System.Windows.Forms.Button(); + this.ArtificialAmbientLightCheckBox = new System.Windows.Forms.CheckBox(); + this.NaturalAmbientLightCheckBox = new System.Windows.Forms.CheckBox(); + this.DistantLODLightsCheckBox = new System.Windows.Forms.CheckBox(); + this.HDRRenderingCheckBox = new System.Windows.Forms.CheckBox(); + this.ControlTimeOfDayCheckBox = new System.Windows.Forms.CheckBox(); + this.TimeOfDayLabel = new System.Windows.Forms.Label(); + this.label19 = new System.Windows.Forms.Label(); + this.TimeOfDayTrackBar = new System.Windows.Forms.TrackBar(); + this.WeatherComboBox = new System.Windows.Forms.ComboBox(); + this.label17 = new System.Windows.Forms.Label(); + this.ControlLightDirectionCheckBox = new System.Windows.Forms.CheckBox(); + this.SkydomeCheckBox = new System.Windows.Forms.CheckBox(); + this.ShadowsCheckBox = new System.Windows.Forms.CheckBox(); + this.StatusBarCheckBox = new System.Windows.Forms.CheckBox(); + this.QuitButton = new System.Windows.Forms.Button(); + this.ReloadSettingsButton = new System.Windows.Forms.Button(); + this.SaveSettingsButton = new System.Windows.Forms.Button(); + this.ReloadShadersButton = new System.Windows.Forms.Button(); + this.ErrorConsoleCheckBox = new System.Windows.Forms.CheckBox(); + this.ToolsPanelHideButton = new System.Windows.Forms.Button(); + this.ToolsPanelShowButton = new System.Windows.Forms.Button(); + this.ConsolePanel = new System.Windows.Forms.Panel(); + this.ConsoleTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.StatsUpdateTimer = new System.Windows.Forms.Timer(this.components); + this.SelectedMarkerPanel = new System.Windows.Forms.Panel(); + this.SelectedMarkerPositionTextBox = new System.Windows.Forms.TextBox(); + this.SelectedMarkerNameTextBox = new System.Windows.Forms.TextBox(); + this.ToolsMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.ToolsMenuRPFBrowser = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuRPFExplorer = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuSelectionInfo = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuProjectWindow = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuWorldSearch = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuBinarySearch = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuJenkGen = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuJenkInd = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuExtractScripts = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuExtractTextures = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuExtractRawFiles = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuExtractShaders = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsMenuOptions = new System.Windows.Forms.ToolStripMenuItem(); + this.Toolbar = new CodeWalker.WinForms.ToolStripFix(); + this.ToolbarNewButton = new System.Windows.Forms.ToolStripSplitButton(); + this.ToolbarNewProjectButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarNewYmapButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarNewYndButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarNewTrainsButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarOpenButton = new System.Windows.Forms.ToolStripSplitButton(); + this.ToolbarOpenProjectButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarOpenYmapButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarOpenYndButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarOpenTrainsButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSaveButton = new System.Windows.Forms.ToolStripButton(); + this.ToolbarSaveAllButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); + this.ToolbarSelectButton = new CodeWalker.WinForms.ToolStripSplitButtonFix(); + this.ToolbarSelectEntityButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectEntityExtensionButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectArchetypeExtensionButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectTimeCycleModifierButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectCarGeneratorButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectGrassButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectWaterQuadButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectCollisionButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectNavMeshButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectPathButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectTrainTrackButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectDistantLodLightsButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectMloInstanceButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectScenarioButton = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.ToolbarMoveButton = new System.Windows.Forms.ToolStripButton(); + this.ToolbarRotateButton = new System.Windows.Forms.ToolStripButton(); + this.ToolbarScaleButton = new System.Windows.Forms.ToolStripButton(); + this.ToolbarTransformSpaceButton = new System.Windows.Forms.ToolStripSplitButton(); + this.ToolbarObjectSpaceButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarWorldSpaceButton = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.ToolbarUndoButton = new System.Windows.Forms.ToolStripSplitButton(); + this.ToolbarUndoListButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarRedoButton = new System.Windows.Forms.ToolStripSplitButton(); + this.ToolbarRedoListButton = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.ToolbarInfoWindowButton = new System.Windows.Forms.ToolStripButton(); + this.ToolbarProjectWindowButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.ToolbarAddItemButton = new System.Windows.Forms.ToolStripButton(); + this.ToolbarDeleteItemButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.ToolbarCopyButton = new System.Windows.Forms.ToolStripButton(); + this.ToolbarPasteButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); + this.ToolbarCameraModeButton = new System.Windows.Forms.ToolStripSplitButton(); + this.ToolbarCameraPerspectiveButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarCameraMapViewButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarCameraOrthographicButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarPanel = new System.Windows.Forms.Panel(); + this.ToolbarNewScenarioButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarOpenScenarioButton = new System.Windows.Forms.ToolStripMenuItem(); + this.StatusStrip.SuspendLayout(); + this.ToolsPanel.SuspendLayout(); + this.ToolsTabControl.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.ViewTabControl.SuspendLayout(); + this.ViewWorldTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.WorldDetailDistTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.WorldLodDistTrackBar)).BeginInit(); + this.ViewYmapsTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.DetailTrackBar)).BeginInit(); + this.ViewModelTabPage.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.SelectionTabControl.SuspendLayout(); + this.SelectionEntityTabPage.SuspendLayout(); + this.SelectionArchetypeTabPage.SuspendLayout(); + this.SelectionDrawableTabPage.SuspendLayout(); + this.tabControl3.SuspendLayout(); + this.tabPage11.SuspendLayout(); + this.tabPage12.SuspendLayout(); + this.tabPage13.SuspendLayout(); + this.SelectionExtensionTabPage.SuspendLayout(); + this.tabPage4.SuspendLayout(); + this.OptionsTabControl.SuspendLayout(); + this.tabPage8.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.MapViewDetailTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.CollisionMeshRangeTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.FieldOfViewTrackBar)).BeginInit(); + this.tabPage14.SuspendLayout(); + this.tabPage9.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.BoundsRangeTrackBar)).BeginInit(); + this.tabPage10.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.CloudParamTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.TimeSpeedTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.TimeOfDayTrackBar)).BeginInit(); + this.ConsolePanel.SuspendLayout(); + this.SelectedMarkerPanel.SuspendLayout(); + this.ToolsMenu.SuspendLayout(); + this.Toolbar.SuspendLayout(); + this.ToolbarPanel.SuspendLayout(); + this.SuspendLayout(); + // + // StatusStrip + // + this.StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StatusLabel, + this.MousedLabel, + this.StatsLabel}); + this.StatusStrip.Location = new System.Drawing.Point(0, 689); + this.StatusStrip.Name = "StatusStrip"; + this.StatusStrip.Size = new System.Drawing.Size(984, 22); + this.StatusStrip.TabIndex = 0; + this.StatusStrip.Text = "statusStrip1"; + // + // StatusLabel + // + this.StatusLabel.BackColor = System.Drawing.SystemColors.Control; + this.StatusLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.Size = new System.Drawing.Size(878, 17); + this.StatusLabel.Spring = true; + this.StatusLabel.Text = "Initialising"; + this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // MousedLabel + // + this.MousedLabel.BackColor = System.Drawing.SystemColors.Control; + this.MousedLabel.Name = "MousedLabel"; + this.MousedLabel.Size = new System.Drawing.Size(16, 17); + this.MousedLabel.Text = " "; + // + // StatsLabel + // + this.StatsLabel.BackColor = System.Drawing.SystemColors.Control; + this.StatsLabel.Name = "StatsLabel"; + this.StatsLabel.Size = new System.Drawing.Size(75, 17); + this.StatsLabel.Text = "0 geometries"; + // + // ModelComboBox + // + this.ModelComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ModelComboBox.FormattingEnabled = true; + this.ModelComboBox.Items.AddRange(new object[] { + "dt1_lod_slod3", + "dt1_tc_dufo_core", + "dt1_tc_ufocore", + "ex_office_citymodel_01", + "id1_30_build3_dtl2", + "imp_prop_ship_01a", + "prop_alien_egg_01", + "prop_fruit_stand_02", + "prop_fruit_stand_03", + "dune", + "dune2", + "dune2_hi", + "adder", + "adder_hi", + "kuruma2", + "kuruma2_hi", + "infernus", + "infernus_hi", + "buzzard", + "buzzard_hi", + "rhino", + "rhino_hi", + "lazer", + "lazer_hi", + "duster", + "duster_hi", + "marquis", + "marquis_hi", + "submersible", + "submersible_hi", + "cargobob", + "cargobob_hi", + "sanchez", + "sanchez_hi"}); + this.ModelComboBox.Location = new System.Drawing.Point(44, 7); + this.ModelComboBox.Name = "ModelComboBox"; + this.ModelComboBox.Size = new System.Drawing.Size(150, 21); + this.ModelComboBox.TabIndex = 11; + this.ModelComboBox.SelectedIndexChanged += new System.EventHandler(this.ModelComboBox_SelectedIndexChanged); + this.ModelComboBox.TextUpdate += new System.EventHandler(this.ModelComboBox_TextUpdate); + // + // ToolsPanel + // + this.ToolsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Right))); + this.ToolsPanel.BackColor = System.Drawing.SystemColors.ControlDark; + this.ToolsPanel.Controls.Add(this.ToolsDragPanel); + this.ToolsPanel.Controls.Add(this.AboutButton); + this.ToolsPanel.Controls.Add(this.ToolsButton); + this.ToolsPanel.Controls.Add(this.ToolsPanelExpandButton); + this.ToolsPanel.Controls.Add(this.ToolsTabControl); + this.ToolsPanel.Controls.Add(this.ToolsPanelHideButton); + this.ToolsPanel.Location = new System.Drawing.Point(754, 12); + this.ToolsPanel.Name = "ToolsPanel"; + this.ToolsPanel.Size = new System.Drawing.Size(218, 665); + this.ToolsPanel.TabIndex = 2; + this.ToolsPanel.Visible = false; + // + // ToolsDragPanel + // + this.ToolsDragPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.ToolsDragPanel.Cursor = System.Windows.Forms.Cursors.VSplit; + this.ToolsDragPanel.Location = new System.Drawing.Point(0, 0); + this.ToolsDragPanel.Name = "ToolsDragPanel"; + this.ToolsDragPanel.Size = new System.Drawing.Size(4, 665); + this.ToolsDragPanel.TabIndex = 16; + this.ToolsDragPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ToolsDragPanel_MouseDown); + this.ToolsDragPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ToolsDragPanel_MouseMove); + this.ToolsDragPanel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ToolsDragPanel_MouseUp); + // + // AboutButton + // + this.AboutButton.Location = new System.Drawing.Point(64, 3); + this.AboutButton.Name = "AboutButton"; + this.AboutButton.Size = new System.Drawing.Size(55, 23); + this.AboutButton.TabIndex = 15; + this.AboutButton.Text = "About..."; + this.AboutButton.UseVisualStyleBackColor = true; + this.AboutButton.Click += new System.EventHandler(this.AboutButton_Click); + // + // ToolsButton + // + this.ToolsButton.Location = new System.Drawing.Point(3, 3); + this.ToolsButton.Name = "ToolsButton"; + this.ToolsButton.Size = new System.Drawing.Size(55, 23); + this.ToolsButton.TabIndex = 14; + this.ToolsButton.Text = "Tools..."; + this.ToolsButton.UseVisualStyleBackColor = true; + this.ToolsButton.Click += new System.EventHandler(this.ToolsButton_Click); + // + // ToolsPanelExpandButton + // + this.ToolsPanelExpandButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ToolsPanelExpandButton.Location = new System.Drawing.Point(149, 3); + this.ToolsPanelExpandButton.Name = "ToolsPanelExpandButton"; + this.ToolsPanelExpandButton.Size = new System.Drawing.Size(30, 23); + this.ToolsPanelExpandButton.TabIndex = 13; + this.ToolsPanelExpandButton.Text = "<<"; + this.ToolsPanelExpandButton.UseVisualStyleBackColor = true; + this.ToolsPanelExpandButton.Click += new System.EventHandler(this.ToolsPanelExpandButton_Click); + // + // ToolsTabControl + // + this.ToolsTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ToolsTabControl.Controls.Add(this.tabPage1); + this.ToolsTabControl.Controls.Add(this.tabPage2); + this.ToolsTabControl.Controls.Add(this.tabPage3); + this.ToolsTabControl.Controls.Add(this.tabPage4); + this.ToolsTabControl.Location = new System.Drawing.Point(3, 30); + this.ToolsTabControl.Name = "ToolsTabControl"; + this.ToolsTabControl.SelectedIndex = 0; + this.ToolsTabControl.Size = new System.Drawing.Size(213, 632); + this.ToolsTabControl.TabIndex = 12; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.ViewTabControl); + this.tabPage1.Controls.Add(this.label3); + this.tabPage1.Controls.Add(this.ViewModeComboBox); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(205, 606); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "View"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // ViewTabControl + // + this.ViewTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ViewTabControl.Controls.Add(this.ViewWorldTabPage); + this.ViewTabControl.Controls.Add(this.ViewYmapsTabPage); + this.ViewTabControl.Controls.Add(this.ViewModelTabPage); + this.ViewTabControl.Location = new System.Drawing.Point(0, 32); + this.ViewTabControl.Name = "ViewTabControl"; + this.ViewTabControl.SelectedIndex = 0; + this.ViewTabControl.Size = new System.Drawing.Size(202, 574); + this.ViewTabControl.TabIndex = 12; + // + // ViewWorldTabPage + // + this.ViewWorldTabPage.Controls.Add(this.EnableModsCheckBox); + this.ViewWorldTabPage.Controls.Add(this.label30); + this.ViewWorldTabPage.Controls.Add(this.DlcLevelComboBox); + this.ViewWorldTabPage.Controls.Add(this.EnableDlcCheckBox); + this.ViewWorldTabPage.Controls.Add(this.WorldYmapWeatherFilterCheckBox); + this.ViewWorldTabPage.Controls.Add(this.WorldYmapTimeFilterCheckBox); + this.ViewWorldTabPage.Controls.Add(this.WorldScriptedYmapsCheckBox); + this.ViewWorldTabPage.Controls.Add(this.WorldDetailDistLabel); + this.ViewWorldTabPage.Controls.Add(this.label18); + this.ViewWorldTabPage.Controls.Add(this.WorldDetailDistTrackBar); + this.ViewWorldTabPage.Controls.Add(this.WorldLodDistLabel); + this.ViewWorldTabPage.Controls.Add(this.label16); + this.ViewWorldTabPage.Controls.Add(this.WorldLodDistTrackBar); + this.ViewWorldTabPage.Controls.Add(this.label15); + this.ViewWorldTabPage.Controls.Add(this.WorldMaxLodComboBox); + this.ViewWorldTabPage.Location = new System.Drawing.Point(4, 22); + this.ViewWorldTabPage.Name = "ViewWorldTabPage"; + this.ViewWorldTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ViewWorldTabPage.Size = new System.Drawing.Size(194, 548); + this.ViewWorldTabPage.TabIndex = 0; + this.ViewWorldTabPage.Text = "World"; + this.ViewWorldTabPage.UseVisualStyleBackColor = true; + // + // EnableModsCheckBox + // + this.EnableModsCheckBox.AutoSize = true; + this.EnableModsCheckBox.Enabled = false; + this.EnableModsCheckBox.Location = new System.Drawing.Point(6, 280); + this.EnableModsCheckBox.Name = "EnableModsCheckBox"; + this.EnableModsCheckBox.Size = new System.Drawing.Size(88, 17); + this.EnableModsCheckBox.TabIndex = 68; + this.EnableModsCheckBox.Text = "Enable Mods"; + this.EnableModsCheckBox.UseVisualStyleBackColor = true; + this.EnableModsCheckBox.CheckedChanged += new System.EventHandler(this.EnableModsCheckBox_CheckedChanged); + // + // label30 + // + this.label30.AutoSize = true; + this.label30.Location = new System.Drawing.Point(1, 337); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(60, 13); + this.label30.TabIndex = 70; + this.label30.Text = "DLC Level:"; + // + // DlcLevelComboBox + // + this.DlcLevelComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.DlcLevelComboBox.Enabled = false; + this.DlcLevelComboBox.FormattingEnabled = true; + this.DlcLevelComboBox.Items.AddRange(new object[] { + ""}); + this.DlcLevelComboBox.Location = new System.Drawing.Point(62, 334); + this.DlcLevelComboBox.Name = "DlcLevelComboBox"; + this.DlcLevelComboBox.Size = new System.Drawing.Size(126, 21); + this.DlcLevelComboBox.TabIndex = 70; + this.DlcLevelComboBox.SelectedIndexChanged += new System.EventHandler(this.DlcLevelComboBox_SelectedIndexChanged); + this.DlcLevelComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.DlcLevelComboBox_KeyPress); + // + // EnableDlcCheckBox + // + this.EnableDlcCheckBox.AutoSize = true; + this.EnableDlcCheckBox.Enabled = false; + this.EnableDlcCheckBox.Location = new System.Drawing.Point(6, 311); + this.EnableDlcCheckBox.Name = "EnableDlcCheckBox"; + this.EnableDlcCheckBox.Size = new System.Drawing.Size(83, 17); + this.EnableDlcCheckBox.TabIndex = 69; + this.EnableDlcCheckBox.Text = "Enable DLC"; + this.EnableDlcCheckBox.UseVisualStyleBackColor = true; + this.EnableDlcCheckBox.CheckedChanged += new System.EventHandler(this.EnableDlcCheckBox_CheckedChanged); + // + // WorldYmapWeatherFilterCheckBox + // + this.WorldYmapWeatherFilterCheckBox.AutoSize = true; + this.WorldYmapWeatherFilterCheckBox.Checked = true; + this.WorldYmapWeatherFilterCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.WorldYmapWeatherFilterCheckBox.Location = new System.Drawing.Point(6, 237); + this.WorldYmapWeatherFilterCheckBox.Name = "WorldYmapWeatherFilterCheckBox"; + this.WorldYmapWeatherFilterCheckBox.Size = new System.Drawing.Size(136, 17); + this.WorldYmapWeatherFilterCheckBox.TabIndex = 67; + this.WorldYmapWeatherFilterCheckBox.Text = "Filter ymaps by weather"; + this.WorldYmapWeatherFilterCheckBox.UseVisualStyleBackColor = true; + this.WorldYmapWeatherFilterCheckBox.CheckedChanged += new System.EventHandler(this.WorldYmapWeatherFilterCheckBox_CheckedChanged); + // + // WorldYmapTimeFilterCheckBox + // + this.WorldYmapTimeFilterCheckBox.AutoSize = true; + this.WorldYmapTimeFilterCheckBox.Checked = true; + this.WorldYmapTimeFilterCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.WorldYmapTimeFilterCheckBox.Location = new System.Drawing.Point(6, 214); + this.WorldYmapTimeFilterCheckBox.Name = "WorldYmapTimeFilterCheckBox"; + this.WorldYmapTimeFilterCheckBox.Size = new System.Drawing.Size(149, 17); + this.WorldYmapTimeFilterCheckBox.TabIndex = 66; + this.WorldYmapTimeFilterCheckBox.Text = "Filter ymaps by time of day"; + this.WorldYmapTimeFilterCheckBox.UseVisualStyleBackColor = true; + this.WorldYmapTimeFilterCheckBox.CheckedChanged += new System.EventHandler(this.WorldYmapTimeFilterCheckBox_CheckedChanged); + // + // WorldScriptedYmapsCheckBox + // + this.WorldScriptedYmapsCheckBox.AutoSize = true; + this.WorldScriptedYmapsCheckBox.Checked = true; + this.WorldScriptedYmapsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.WorldScriptedYmapsCheckBox.Location = new System.Drawing.Point(6, 182); + this.WorldScriptedYmapsCheckBox.Name = "WorldScriptedYmapsCheckBox"; + this.WorldScriptedYmapsCheckBox.Size = new System.Drawing.Size(126, 17); + this.WorldScriptedYmapsCheckBox.TabIndex = 65; + this.WorldScriptedYmapsCheckBox.Text = "Show scripted ymaps"; + this.WorldScriptedYmapsCheckBox.UseVisualStyleBackColor = true; + this.WorldScriptedYmapsCheckBox.CheckedChanged += new System.EventHandler(this.WorldScriptedYmapsCheckBox_CheckedChanged); + // + // WorldDetailDistLabel + // + this.WorldDetailDistLabel.AutoSize = true; + this.WorldDetailDistLabel.Location = new System.Drawing.Point(87, 94); + this.WorldDetailDistLabel.Name = "WorldDetailDistLabel"; + this.WorldDetailDistLabel.Size = new System.Drawing.Size(22, 13); + this.WorldDetailDistLabel.TabIndex = 64; + this.WorldDetailDistLabel.Text = "1.0"; + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(1, 94); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(80, 13); + this.label18.TabIndex = 63; + this.label18.Text = "Detail distance:"; + // + // WorldDetailDistTrackBar + // + this.WorldDetailDistTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.WorldDetailDistTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.WorldDetailDistTrackBar.LargeChange = 10; + this.WorldDetailDistTrackBar.Location = new System.Drawing.Point(6, 110); + this.WorldDetailDistTrackBar.Maximum = 30; + this.WorldDetailDistTrackBar.Name = "WorldDetailDistTrackBar"; + this.WorldDetailDistTrackBar.Size = new System.Drawing.Size(182, 45); + this.WorldDetailDistTrackBar.TabIndex = 62; + this.WorldDetailDistTrackBar.TickFrequency = 2; + this.WorldDetailDistTrackBar.Value = 10; + this.WorldDetailDistTrackBar.Scroll += new System.EventHandler(this.WorldDetailDistTrackBar_Scroll); + // + // WorldLodDistLabel + // + this.WorldLodDistLabel.AutoSize = true; + this.WorldLodDistLabel.Location = new System.Drawing.Point(82, 39); + this.WorldLodDistLabel.Name = "WorldLodDistLabel"; + this.WorldLodDistLabel.Size = new System.Drawing.Size(22, 13); + this.WorldLodDistLabel.TabIndex = 61; + this.WorldLodDistLabel.Text = "1.0"; + this.WorldLodDistLabel.Visible = false; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(1, 39); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(75, 13); + this.label16.TabIndex = 60; + this.label16.Text = "LOD distance:"; + this.label16.Visible = false; + // + // WorldLodDistTrackBar + // + this.WorldLodDistTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.WorldLodDistTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.WorldLodDistTrackBar.LargeChange = 10; + this.WorldLodDistTrackBar.Location = new System.Drawing.Point(6, 55); + this.WorldLodDistTrackBar.Maximum = 30; + this.WorldLodDistTrackBar.Name = "WorldLodDistTrackBar"; + this.WorldLodDistTrackBar.Size = new System.Drawing.Size(182, 45); + this.WorldLodDistTrackBar.TabIndex = 59; + this.WorldLodDistTrackBar.TickFrequency = 2; + this.WorldLodDistTrackBar.Value = 10; + this.WorldLodDistTrackBar.Visible = false; + this.WorldLodDistTrackBar.Scroll += new System.EventHandler(this.WorldLodDistTrackBar_Scroll); + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(1, 9); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(55, 13); + this.label15.TabIndex = 58; + this.label15.Text = "Max LOD:"; + // + // WorldMaxLodComboBox + // + this.WorldMaxLodComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.WorldMaxLodComboBox.FormattingEnabled = true; + this.WorldMaxLodComboBox.Items.AddRange(new object[] { + "ORPHANHD", + "HD", + "LOD", + "SLOD1", + "SLOD2", + "SLOD3", + "SLOD4"}); + this.WorldMaxLodComboBox.Location = new System.Drawing.Point(62, 6); + this.WorldMaxLodComboBox.Name = "WorldMaxLodComboBox"; + this.WorldMaxLodComboBox.Size = new System.Drawing.Size(126, 21); + this.WorldMaxLodComboBox.TabIndex = 57; + this.WorldMaxLodComboBox.SelectedIndexChanged += new System.EventHandler(this.WorldMaxLodComboBox_SelectedIndexChanged); + this.WorldMaxLodComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.WorldMaxLodComboBox_KeyPress); + // + // ViewYmapsTabPage + // + this.ViewYmapsTabPage.Controls.Add(this.ShowYmapChildrenCheckBox); + this.ViewYmapsTabPage.Controls.Add(this.label2); + this.ViewYmapsTabPage.Controls.Add(this.DetailTrackBar); + this.ViewYmapsTabPage.Controls.Add(this.DynamicLODCheckBox); + this.ViewYmapsTabPage.Controls.Add(this.YmapsTextBox); + this.ViewYmapsTabPage.Location = new System.Drawing.Point(4, 22); + this.ViewYmapsTabPage.Name = "ViewYmapsTabPage"; + this.ViewYmapsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.ViewYmapsTabPage.Size = new System.Drawing.Size(194, 548); + this.ViewYmapsTabPage.TabIndex = 1; + this.ViewYmapsTabPage.Text = "Ymaps"; + this.ViewYmapsTabPage.UseVisualStyleBackColor = true; + // + // ShowYmapChildrenCheckBox + // + this.ShowYmapChildrenCheckBox.AutoSize = true; + this.ShowYmapChildrenCheckBox.Enabled = false; + this.ShowYmapChildrenCheckBox.Location = new System.Drawing.Point(6, 59); + this.ShowYmapChildrenCheckBox.Name = "ShowYmapChildrenCheckBox"; + this.ShowYmapChildrenCheckBox.Size = new System.Drawing.Size(93, 17); + this.ShowYmapChildrenCheckBox.TabIndex = 35; + this.ShowYmapChildrenCheckBox.Text = "Show children"; + this.ShowYmapChildrenCheckBox.UseVisualStyleBackColor = true; + this.ShowYmapChildrenCheckBox.CheckedChanged += new System.EventHandler(this.ShowYmapChildrenCheckBox_CheckedChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 88); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(77, 13); + this.label2.TabIndex = 8; + this.label2.Text = "Ymaps to load:"; + // + // DetailTrackBar + // + this.DetailTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.DetailTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.DetailTrackBar.Location = new System.Drawing.Point(6, 24); + this.DetailTrackBar.Maximum = 20; + this.DetailTrackBar.Name = "DetailTrackBar"; + this.DetailTrackBar.Size = new System.Drawing.Size(182, 45); + this.DetailTrackBar.TabIndex = 34; + this.DetailTrackBar.Value = 5; + this.DetailTrackBar.Scroll += new System.EventHandler(this.DetailTrackBar_Scroll); + // + // DynamicLODCheckBox + // + this.DynamicLODCheckBox.AutoSize = true; + this.DynamicLODCheckBox.Checked = true; + this.DynamicLODCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.DynamicLODCheckBox.Location = new System.Drawing.Point(6, 6); + this.DynamicLODCheckBox.Name = "DynamicLODCheckBox"; + this.DynamicLODCheckBox.Size = new System.Drawing.Size(92, 17); + this.DynamicLODCheckBox.TabIndex = 33; + this.DynamicLODCheckBox.Text = "Dynamic LOD"; + this.DynamicLODCheckBox.UseVisualStyleBackColor = true; + this.DynamicLODCheckBox.CheckedChanged += new System.EventHandler(this.DynamicLODCheckBox_CheckedChanged); + // + // YmapsTextBox + // + this.YmapsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YmapsTextBox.Location = new System.Drawing.Point(0, 104); + this.YmapsTextBox.Multiline = true; + this.YmapsTextBox.Name = "YmapsTextBox"; + this.YmapsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.YmapsTextBox.Size = new System.Drawing.Size(194, 444); + this.YmapsTextBox.TabIndex = 36; + this.YmapsTextBox.Text = resources.GetString("YmapsTextBox.Text"); + this.YmapsTextBox.TextChanged += new System.EventHandler(this.YmapsTextBox_TextChanged); + // + // ViewModelTabPage + // + this.ViewModelTabPage.Controls.Add(this.label1); + this.ViewModelTabPage.Controls.Add(this.ModelComboBox); + this.ViewModelTabPage.Location = new System.Drawing.Point(4, 22); + this.ViewModelTabPage.Name = "ViewModelTabPage"; + this.ViewModelTabPage.Size = new System.Drawing.Size(194, 548); + this.ViewModelTabPage.TabIndex = 2; + this.ViewModelTabPage.Text = "Model"; + this.ViewModelTabPage.UseVisualStyleBackColor = true; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(-1, 10); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(39, 13); + this.label1.TabIndex = 5; + this.label1.Text = "Model:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(3, 8); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(37, 13); + this.label3.TabIndex = 11; + this.label3.Text = "Mode:"; + // + // ViewModeComboBox + // + this.ViewModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.ViewModeComboBox.FormattingEnabled = true; + this.ViewModeComboBox.Items.AddRange(new object[] { + "World view", + "Ymap view", + "Model view"}); + this.ViewModeComboBox.Location = new System.Drawing.Point(48, 5); + this.ViewModeComboBox.Name = "ViewModeComboBox"; + this.ViewModeComboBox.Size = new System.Drawing.Size(111, 21); + this.ViewModeComboBox.TabIndex = 10; + this.ViewModeComboBox.SelectedIndexChanged += new System.EventHandler(this.ViewModeComboBox_SelectedIndexChanged); + this.ViewModeComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ViewModeComboBox_KeyPress); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.label27); + this.tabPage2.Controls.Add(this.CameraPositionTextBox); + this.tabPage2.Controls.Add(this.AddSelectionMarkerButton); + this.tabPage2.Controls.Add(this.AddCurrentPositonMarkerButton); + this.tabPage2.Controls.Add(this.ResetMarkersButton); + this.tabPage2.Controls.Add(this.ClearMarkersButton); + this.tabPage2.Controls.Add(this.GoToButton); + this.tabPage2.Controls.Add(this.ShowLocatorCheckBox); + this.tabPage2.Controls.Add(this.label6); + this.tabPage2.Controls.Add(this.LocateTextBox); + this.tabPage2.Controls.Add(this.label7); + this.tabPage2.Controls.Add(this.AddMarkersButton); + this.tabPage2.Controls.Add(this.MultiFindTextBox); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(205, 606); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Markers"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // label27 + // + this.label27.AutoSize = true; + this.label27.Location = new System.Drawing.Point(-2, 50); + this.label27.Name = "label27"; + this.label27.Size = new System.Drawing.Size(121, 13); + this.label27.TabIndex = 22; + this.label27.Text = "Current camera position:"; + // + // CameraPositionTextBox + // + this.CameraPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CameraPositionTextBox.Location = new System.Drawing.Point(0, 67); + this.CameraPositionTextBox.Name = "CameraPositionTextBox"; + this.CameraPositionTextBox.Size = new System.Drawing.Size(205, 20); + this.CameraPositionTextBox.TabIndex = 16; + this.CameraPositionTextBox.Text = "0, 0, 0"; + // + // AddSelectionMarkerButton + // + this.AddSelectionMarkerButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.AddSelectionMarkerButton.Location = new System.Drawing.Point(0, 536); + this.AddSelectionMarkerButton.Name = "AddSelectionMarkerButton"; + this.AddSelectionMarkerButton.Size = new System.Drawing.Size(97, 23); + this.AddSelectionMarkerButton.TabIndex = 22; + this.AddSelectionMarkerButton.Text = "Add selection"; + this.AddSelectionMarkerButton.UseVisualStyleBackColor = true; + this.AddSelectionMarkerButton.Click += new System.EventHandler(this.AddSelectionMarkerButton_Click); + // + // AddCurrentPositonMarkerButton + // + this.AddCurrentPositonMarkerButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.AddCurrentPositonMarkerButton.Location = new System.Drawing.Point(0, 507); + this.AddCurrentPositonMarkerButton.Name = "AddCurrentPositonMarkerButton"; + this.AddCurrentPositonMarkerButton.Size = new System.Drawing.Size(97, 23); + this.AddCurrentPositonMarkerButton.TabIndex = 20; + this.AddCurrentPositonMarkerButton.Text = "Add current pos"; + this.AddCurrentPositonMarkerButton.UseVisualStyleBackColor = true; + this.AddCurrentPositonMarkerButton.Click += new System.EventHandler(this.AddCurrentPositonMarkerButton_Click); + // + // ResetMarkersButton + // + this.ResetMarkersButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ResetMarkersButton.Location = new System.Drawing.Point(108, 507); + this.ResetMarkersButton.Name = "ResetMarkersButton"; + this.ResetMarkersButton.Size = new System.Drawing.Size(97, 23); + this.ResetMarkersButton.TabIndex = 21; + this.ResetMarkersButton.Text = "Default markers"; + this.ResetMarkersButton.UseVisualStyleBackColor = true; + this.ResetMarkersButton.Click += new System.EventHandler(this.ResetMarkersButton_Click); + // + // ClearMarkersButton + // + this.ClearMarkersButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ClearMarkersButton.Location = new System.Drawing.Point(108, 478); + this.ClearMarkersButton.Name = "ClearMarkersButton"; + this.ClearMarkersButton.Size = new System.Drawing.Size(97, 23); + this.ClearMarkersButton.TabIndex = 19; + this.ClearMarkersButton.Text = "Clear markers"; + this.ClearMarkersButton.UseVisualStyleBackColor = true; + this.ClearMarkersButton.Click += new System.EventHandler(this.ClearMarkersButton_Click); + // + // GoToButton + // + this.GoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.GoToButton.Location = new System.Drawing.Point(162, 24); + this.GoToButton.Name = "GoToButton"; + this.GoToButton.Size = new System.Drawing.Size(43, 22); + this.GoToButton.TabIndex = 15; + this.GoToButton.Text = "Go to"; + this.GoToButton.UseVisualStyleBackColor = true; + this.GoToButton.Click += new System.EventHandler(this.GoToButton_Click); + // + // ShowLocatorCheckBox + // + this.ShowLocatorCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ShowLocatorCheckBox.AutoSize = true; + this.ShowLocatorCheckBox.Location = new System.Drawing.Point(101, 8); + this.ShowLocatorCheckBox.Name = "ShowLocatorCheckBox"; + this.ShowLocatorCheckBox.Size = new System.Drawing.Size(88, 17); + this.ShowLocatorCheckBox.TabIndex = 13; + this.ShowLocatorCheckBox.Text = "Show marker"; + this.ShowLocatorCheckBox.UseVisualStyleBackColor = true; + this.ShowLocatorCheckBox.CheckedChanged += new System.EventHandler(this.ShowLocatorCheckBox_CheckedChanged); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(-2, 8); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(79, 13); + this.label6.TabIndex = 13; + this.label6.Text = "Locate: X, Y, Z"; + // + // LocateTextBox + // + this.LocateTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.LocateTextBox.Location = new System.Drawing.Point(0, 25); + this.LocateTextBox.Name = "LocateTextBox"; + this.LocateTextBox.Size = new System.Drawing.Size(156, 20); + this.LocateTextBox.TabIndex = 14; + this.LocateTextBox.Text = "0, 0, 0"; + this.LocateTextBox.TextChanged += new System.EventHandler(this.LocateTextBox_TextChanged); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(-2, 101); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(122, 13); + this.label7.TabIndex = 11; + this.label7.Text = "Multi-find: X, Y, Z, Name"; + // + // AddMarkersButton + // + this.AddMarkersButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.AddMarkersButton.Location = new System.Drawing.Point(0, 478); + this.AddMarkersButton.Name = "AddMarkersButton"; + this.AddMarkersButton.Size = new System.Drawing.Size(97, 23); + this.AddMarkersButton.TabIndex = 18; + this.AddMarkersButton.Text = "Add markers"; + this.AddMarkersButton.UseVisualStyleBackColor = true; + this.AddMarkersButton.Click += new System.EventHandler(this.AddMarkersButton_Click); + // + // MultiFindTextBox + // + this.MultiFindTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MultiFindTextBox.Location = new System.Drawing.Point(0, 117); + this.MultiFindTextBox.Multiline = true; + this.MultiFindTextBox.Name = "MultiFindTextBox"; + this.MultiFindTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.MultiFindTextBox.Size = new System.Drawing.Size(205, 355); + this.MultiFindTextBox.TabIndex = 17; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.label25); + this.tabPage3.Controls.Add(this.SelectionModeComboBox); + this.tabPage3.Controls.Add(this.SelectionNameTextBox); + this.tabPage3.Controls.Add(this.SelectionTabControl); + this.tabPage3.Controls.Add(this.MouseSelectCheckBox); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(205, 606); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Selection"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(6, 33); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(37, 13); + this.label25.TabIndex = 28; + this.label25.Text = "Mode:"; + // + // SelectionModeComboBox + // + this.SelectionModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.SelectionModeComboBox.FormattingEnabled = true; + this.SelectionModeComboBox.Items.AddRange(new object[] { + "Entity", + "Entity Extension", + "Archetype Extension", + "Time Cycle Modifier", + "Car Generator", + "Grass", + "Water Quad", + "Collision", + "Nav Mesh", + "Path", + "Train Track", + "Distant Lod Lights", + "Mlo Instance", + "Scenario"}); + this.SelectionModeComboBox.Location = new System.Drawing.Point(51, 30); + this.SelectionModeComboBox.Name = "SelectionModeComboBox"; + this.SelectionModeComboBox.Size = new System.Drawing.Size(121, 21); + this.SelectionModeComboBox.TabIndex = 23; + this.SelectionModeComboBox.SelectedIndexChanged += new System.EventHandler(this.SelectionModeComboBox_SelectedIndexChanged); + this.SelectionModeComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.SelectionModeComboBox_KeyPress); + // + // SelectionNameTextBox + // + this.SelectionNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectionNameTextBox.BackColor = System.Drawing.Color.White; + this.SelectionNameTextBox.Location = new System.Drawing.Point(3, 66); + this.SelectionNameTextBox.Name = "SelectionNameTextBox"; + this.SelectionNameTextBox.ReadOnly = true; + this.SelectionNameTextBox.Size = new System.Drawing.Size(199, 20); + this.SelectionNameTextBox.TabIndex = 26; + this.SelectionNameTextBox.Text = "Nothing selected"; + // + // SelectionTabControl + // + this.SelectionTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectionTabControl.Controls.Add(this.SelectionEntityTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionArchetypeTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionDrawableTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionExtensionTabPage); + this.SelectionTabControl.Location = new System.Drawing.Point(0, 95); + this.SelectionTabControl.Margin = new System.Windows.Forms.Padding(0); + this.SelectionTabControl.Name = "SelectionTabControl"; + this.SelectionTabControl.SelectedIndex = 0; + this.SelectionTabControl.Size = new System.Drawing.Size(205, 511); + this.SelectionTabControl.TabIndex = 28; + // + // SelectionEntityTabPage + // + this.SelectionEntityTabPage.Controls.Add(this.SelEntityPropertyGrid); + this.SelectionEntityTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionEntityTabPage.Name = "SelectionEntityTabPage"; + this.SelectionEntityTabPage.Padding = new System.Windows.Forms.Padding(3); + this.SelectionEntityTabPage.Size = new System.Drawing.Size(197, 485); + this.SelectionEntityTabPage.TabIndex = 0; + this.SelectionEntityTabPage.Text = "Entity"; + this.SelectionEntityTabPage.UseVisualStyleBackColor = true; + // + // SelEntityPropertyGrid + // + this.SelEntityPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelEntityPropertyGrid.HelpVisible = false; + this.SelEntityPropertyGrid.Location = new System.Drawing.Point(0, 6); + this.SelEntityPropertyGrid.Name = "SelEntityPropertyGrid"; + this.SelEntityPropertyGrid.PropertySort = System.Windows.Forms.PropertySort.NoSort; + this.SelEntityPropertyGrid.ReadOnly = true; + this.SelEntityPropertyGrid.Size = new System.Drawing.Size(197, 476); + this.SelEntityPropertyGrid.TabIndex = 35; + this.SelEntityPropertyGrid.ToolbarVisible = false; + // + // SelectionArchetypeTabPage + // + this.SelectionArchetypeTabPage.Controls.Add(this.SelArchetypePropertyGrid); + this.SelectionArchetypeTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionArchetypeTabPage.Name = "SelectionArchetypeTabPage"; + this.SelectionArchetypeTabPage.Padding = new System.Windows.Forms.Padding(3); + this.SelectionArchetypeTabPage.Size = new System.Drawing.Size(197, 485); + this.SelectionArchetypeTabPage.TabIndex = 1; + this.SelectionArchetypeTabPage.Text = "Archetype"; + this.SelectionArchetypeTabPage.UseVisualStyleBackColor = true; + // + // SelArchetypePropertyGrid + // + this.SelArchetypePropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelArchetypePropertyGrid.HelpVisible = false; + this.SelArchetypePropertyGrid.Location = new System.Drawing.Point(0, 6); + this.SelArchetypePropertyGrid.Name = "SelArchetypePropertyGrid"; + this.SelArchetypePropertyGrid.PropertySort = System.Windows.Forms.PropertySort.NoSort; + this.SelArchetypePropertyGrid.ReadOnly = true; + this.SelArchetypePropertyGrid.Size = new System.Drawing.Size(197, 476); + this.SelArchetypePropertyGrid.TabIndex = 36; + this.SelArchetypePropertyGrid.ToolbarVisible = false; + // + // SelectionDrawableTabPage + // + this.SelectionDrawableTabPage.Controls.Add(this.tabControl3); + this.SelectionDrawableTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionDrawableTabPage.Margin = new System.Windows.Forms.Padding(0); + this.SelectionDrawableTabPage.Name = "SelectionDrawableTabPage"; + this.SelectionDrawableTabPage.Size = new System.Drawing.Size(197, 485); + this.SelectionDrawableTabPage.TabIndex = 2; + this.SelectionDrawableTabPage.Text = "Drawable"; + this.SelectionDrawableTabPage.UseVisualStyleBackColor = true; + // + // tabControl3 + // + this.tabControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tabControl3.Controls.Add(this.tabPage11); + this.tabControl3.Controls.Add(this.tabPage12); + this.tabControl3.Controls.Add(this.tabPage13); + this.tabControl3.Location = new System.Drawing.Point(-4, 7); + this.tabControl3.Name = "tabControl3"; + this.tabControl3.SelectedIndex = 0; + this.tabControl3.Size = new System.Drawing.Size(205, 478); + this.tabControl3.TabIndex = 28; + // + // tabPage11 + // + this.tabPage11.Controls.Add(this.SelDrawablePropertyGrid); + this.tabPage11.Location = new System.Drawing.Point(4, 22); + this.tabPage11.Margin = new System.Windows.Forms.Padding(0); + this.tabPage11.Name = "tabPage11"; + this.tabPage11.Size = new System.Drawing.Size(197, 452); + this.tabPage11.TabIndex = 0; + this.tabPage11.Text = "Info"; + this.tabPage11.UseVisualStyleBackColor = true; + // + // SelDrawablePropertyGrid + // + this.SelDrawablePropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawablePropertyGrid.HelpVisible = false; + this.SelDrawablePropertyGrid.Location = new System.Drawing.Point(0, 0); + this.SelDrawablePropertyGrid.Name = "SelDrawablePropertyGrid"; + this.SelDrawablePropertyGrid.PropertySort = System.Windows.Forms.PropertySort.NoSort; + this.SelDrawablePropertyGrid.ReadOnly = true; + this.SelDrawablePropertyGrid.Size = new System.Drawing.Size(197, 452); + this.SelDrawablePropertyGrid.TabIndex = 37; + this.SelDrawablePropertyGrid.ToolbarVisible = false; + // + // tabPage12 + // + this.tabPage12.Controls.Add(this.SelDrawableModelsTreeView); + this.tabPage12.Location = new System.Drawing.Point(4, 22); + this.tabPage12.Name = "tabPage12"; + this.tabPage12.Padding = new System.Windows.Forms.Padding(3); + this.tabPage12.Size = new System.Drawing.Size(197, 452); + this.tabPage12.TabIndex = 1; + this.tabPage12.Text = "Models"; + this.tabPage12.UseVisualStyleBackColor = true; + // + // SelDrawableModelsTreeView + // + this.SelDrawableModelsTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawableModelsTreeView.CheckBoxes = true; + this.SelDrawableModelsTreeView.Location = new System.Drawing.Point(0, 0); + this.SelDrawableModelsTreeView.Name = "SelDrawableModelsTreeView"; + this.SelDrawableModelsTreeView.ShowRootLines = false; + this.SelDrawableModelsTreeView.Size = new System.Drawing.Size(197, 452); + this.SelDrawableModelsTreeView.TabIndex = 39; + this.SelDrawableModelsTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.SelDrawableModelsTreeView_AfterCheck); + this.SelDrawableModelsTreeView.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.SelDrawableModelsTreeView_NodeMouseDoubleClick); + this.SelDrawableModelsTreeView.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.SelDrawableModelsTreeView_KeyPress); + // + // tabPage13 + // + this.tabPage13.Controls.Add(this.SelDrawableTexturesTreeView); + this.tabPage13.Location = new System.Drawing.Point(4, 22); + this.tabPage13.Name = "tabPage13"; + this.tabPage13.Size = new System.Drawing.Size(197, 452); + this.tabPage13.TabIndex = 2; + this.tabPage13.Text = "Textures"; + this.tabPage13.UseVisualStyleBackColor = true; + // + // SelDrawableTexturesTreeView + // + this.SelDrawableTexturesTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawableTexturesTreeView.Location = new System.Drawing.Point(0, 0); + this.SelDrawableTexturesTreeView.Name = "SelDrawableTexturesTreeView"; + this.SelDrawableTexturesTreeView.ShowRootLines = false; + this.SelDrawableTexturesTreeView.Size = new System.Drawing.Size(197, 452); + this.SelDrawableTexturesTreeView.TabIndex = 40; + // + // SelectionExtensionTabPage + // + this.SelectionExtensionTabPage.Controls.Add(this.SelExtensionPropertyGrid); + this.SelectionExtensionTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionExtensionTabPage.Name = "SelectionExtensionTabPage"; + this.SelectionExtensionTabPage.Size = new System.Drawing.Size(197, 485); + this.SelectionExtensionTabPage.TabIndex = 3; + this.SelectionExtensionTabPage.Text = "Ext"; + this.SelectionExtensionTabPage.UseVisualStyleBackColor = true; + // + // SelExtensionPropertyGrid + // + this.SelExtensionPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelExtensionPropertyGrid.HelpVisible = false; + this.SelExtensionPropertyGrid.Location = new System.Drawing.Point(0, 6); + this.SelExtensionPropertyGrid.Name = "SelExtensionPropertyGrid"; + this.SelExtensionPropertyGrid.PropertySort = System.Windows.Forms.PropertySort.NoSort; + this.SelExtensionPropertyGrid.ReadOnly = true; + this.SelExtensionPropertyGrid.Size = new System.Drawing.Size(197, 476); + this.SelExtensionPropertyGrid.TabIndex = 36; + this.SelExtensionPropertyGrid.ToolbarVisible = false; + // + // MouseSelectCheckBox + // + this.MouseSelectCheckBox.AutoSize = true; + this.MouseSelectCheckBox.Location = new System.Drawing.Point(8, 7); + this.MouseSelectCheckBox.Name = "MouseSelectCheckBox"; + this.MouseSelectCheckBox.Size = new System.Drawing.Size(143, 17); + this.MouseSelectCheckBox.TabIndex = 22; + this.MouseSelectCheckBox.Text = "Mouse select (right click)"; + this.MouseSelectCheckBox.UseVisualStyleBackColor = true; + this.MouseSelectCheckBox.CheckedChanged += new System.EventHandler(this.MouseSelectCheckBox_CheckedChanged); + // + // tabPage4 + // + this.tabPage4.Controls.Add(this.OptionsTabControl); + this.tabPage4.Controls.Add(this.StatusBarCheckBox); + this.tabPage4.Controls.Add(this.QuitButton); + this.tabPage4.Controls.Add(this.ReloadSettingsButton); + this.tabPage4.Controls.Add(this.SaveSettingsButton); + this.tabPage4.Controls.Add(this.ReloadShadersButton); + this.tabPage4.Controls.Add(this.ErrorConsoleCheckBox); + this.tabPage4.Location = new System.Drawing.Point(4, 22); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Size = new System.Drawing.Size(205, 606); + this.tabPage4.TabIndex = 3; + this.tabPage4.Text = "Options"; + this.tabPage4.UseVisualStyleBackColor = true; + // + // OptionsTabControl + // + this.OptionsTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.OptionsTabControl.Controls.Add(this.tabPage8); + this.OptionsTabControl.Controls.Add(this.tabPage14); + this.OptionsTabControl.Controls.Add(this.tabPage9); + this.OptionsTabControl.Controls.Add(this.tabPage10); + this.OptionsTabControl.Location = new System.Drawing.Point(0, 3); + this.OptionsTabControl.Name = "OptionsTabControl"; + this.OptionsTabControl.SelectedIndex = 0; + this.OptionsTabControl.Size = new System.Drawing.Size(208, 508); + this.OptionsTabControl.TabIndex = 50; + // + // tabPage8 + // + this.tabPage8.Controls.Add(this.AdvancedSettingsButton); + this.tabPage8.Controls.Add(this.ControlSettingsButton); + this.tabPage8.Controls.Add(this.MapViewDetailLabel); + this.tabPage8.Controls.Add(this.label28); + this.tabPage8.Controls.Add(this.MapViewDetailTrackBar); + this.tabPage8.Controls.Add(this.CameraModeComboBox); + this.tabPage8.Controls.Add(this.label24); + this.tabPage8.Controls.Add(this.WaterQuadsCheckBox); + this.tabPage8.Controls.Add(this.FieldOfViewLabel); + this.tabPage8.Controls.Add(this.label22); + this.tabPage8.Controls.Add(this.TimedEntitiesAlwaysOnCheckBox); + this.tabPage8.Controls.Add(this.GrassCheckBox); + this.tabPage8.Controls.Add(this.InteriorsCheckBox); + this.tabPage8.Controls.Add(this.CollisionMeshLayerDrawableCheckBox); + this.tabPage8.Controls.Add(this.CollisionMeshLayer2CheckBox); + this.tabPage8.Controls.Add(this.CollisionMeshLayer1CheckBox); + this.tabPage8.Controls.Add(this.label13); + this.tabPage8.Controls.Add(this.CollisionMeshLayer0CheckBox); + this.tabPage8.Controls.Add(this.label12); + this.tabPage8.Controls.Add(this.CollisionMeshRangeTrackBar); + this.tabPage8.Controls.Add(this.CollisionMeshesCheckBox); + this.tabPage8.Controls.Add(this.FullScreenCheckBox); + this.tabPage8.Controls.Add(this.TimedEntitiesCheckBox); + this.tabPage8.Controls.Add(this.FieldOfViewTrackBar); + this.tabPage8.Location = new System.Drawing.Point(4, 22); + this.tabPage8.Name = "tabPage8"; + this.tabPage8.Padding = new System.Windows.Forms.Padding(3); + this.tabPage8.Size = new System.Drawing.Size(200, 482); + this.tabPage8.TabIndex = 0; + this.tabPage8.Text = "General"; + this.tabPage8.UseVisualStyleBackColor = true; + // + // AdvancedSettingsButton + // + this.AdvancedSettingsButton.Location = new System.Drawing.Point(101, 456); + this.AdvancedSettingsButton.Name = "AdvancedSettingsButton"; + this.AdvancedSettingsButton.Size = new System.Drawing.Size(93, 23); + this.AdvancedSettingsButton.TabIndex = 61; + this.AdvancedSettingsButton.Text = "Advanced..."; + this.AdvancedSettingsButton.UseVisualStyleBackColor = true; + this.AdvancedSettingsButton.Click += new System.EventHandler(this.AdvancedSettingsButton_Click); + // + // ControlSettingsButton + // + this.ControlSettingsButton.Location = new System.Drawing.Point(2, 456); + this.ControlSettingsButton.Name = "ControlSettingsButton"; + this.ControlSettingsButton.Size = new System.Drawing.Size(93, 23); + this.ControlSettingsButton.TabIndex = 60; + this.ControlSettingsButton.Text = "Controls..."; + this.ControlSettingsButton.UseVisualStyleBackColor = true; + this.ControlSettingsButton.Click += new System.EventHandler(this.ControlSettingsButton_Click); + // + // MapViewDetailLabel + // + this.MapViewDetailLabel.AutoSize = true; + this.MapViewDetailLabel.Location = new System.Drawing.Point(94, 391); + this.MapViewDetailLabel.Name = "MapViewDetailLabel"; + this.MapViewDetailLabel.Size = new System.Drawing.Size(22, 13); + this.MapViewDetailLabel.TabIndex = 66; + this.MapViewDetailLabel.Text = "1.0"; + // + // label28 + // + this.label28.AutoSize = true; + this.label28.Location = new System.Drawing.Point(4, 391); + this.label28.Name = "label28"; + this.label28.Size = new System.Drawing.Size(84, 13); + this.label28.TabIndex = 65; + this.label28.Text = "Map view detail:"; + // + // MapViewDetailTrackBar + // + this.MapViewDetailTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MapViewDetailTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.MapViewDetailTrackBar.Enabled = false; + this.MapViewDetailTrackBar.LargeChange = 1; + this.MapViewDetailTrackBar.Location = new System.Drawing.Point(6, 407); + this.MapViewDetailTrackBar.Maximum = 30; + this.MapViewDetailTrackBar.Minimum = 2; + this.MapViewDetailTrackBar.Name = "MapViewDetailTrackBar"; + this.MapViewDetailTrackBar.Size = new System.Drawing.Size(188, 45); + this.MapViewDetailTrackBar.TabIndex = 58; + this.MapViewDetailTrackBar.TickFrequency = 2; + this.MapViewDetailTrackBar.Value = 10; + this.MapViewDetailTrackBar.Scroll += new System.EventHandler(this.MapViewDetailTrackBar_Scroll); + // + // CameraModeComboBox + // + this.CameraModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CameraModeComboBox.FormattingEnabled = true; + this.CameraModeComboBox.Items.AddRange(new object[] { + "Perspective", + "Orthographic", + "2D Map"}); + this.CameraModeComboBox.Location = new System.Drawing.Point(82, 305); + this.CameraModeComboBox.Name = "CameraModeComboBox"; + this.CameraModeComboBox.Size = new System.Drawing.Size(112, 21); + this.CameraModeComboBox.TabIndex = 56; + this.CameraModeComboBox.SelectedIndexChanged += new System.EventHandler(this.CameraModeComboBox_SelectedIndexChanged); + this.CameraModeComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.CameraModeComboBox_KeyPress); + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(4, 308); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(75, 13); + this.label24.TabIndex = 63; + this.label24.Text = "Camera mode:"; + // + // WaterQuadsCheckBox + // + this.WaterQuadsCheckBox.AutoSize = true; + this.WaterQuadsCheckBox.Checked = true; + this.WaterQuadsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.WaterQuadsCheckBox.Location = new System.Drawing.Point(10, 104); + this.WaterQuadsCheckBox.Name = "WaterQuadsCheckBox"; + this.WaterQuadsCheckBox.Size = new System.Drawing.Size(114, 17); + this.WaterQuadsCheckBox.TabIndex = 39; + this.WaterQuadsCheckBox.Text = "Show water quads"; + this.WaterQuadsCheckBox.UseVisualStyleBackColor = true; + this.WaterQuadsCheckBox.CheckedChanged += new System.EventHandler(this.WaterQuadsCheckBox_CheckedChanged); + // + // FieldOfViewLabel + // + this.FieldOfViewLabel.AutoSize = true; + this.FieldOfViewLabel.Location = new System.Drawing.Point(79, 335); + this.FieldOfViewLabel.Name = "FieldOfViewLabel"; + this.FieldOfViewLabel.Size = new System.Drawing.Size(22, 13); + this.FieldOfViewLabel.TabIndex = 59; + this.FieldOfViewLabel.Text = "1.0"; + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(4, 335); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(69, 13); + this.label22.TabIndex = 58; + this.label22.Text = "Field of view:"; + // + // TimedEntitiesAlwaysOnCheckBox + // + this.TimedEntitiesAlwaysOnCheckBox.AutoSize = true; + this.TimedEntitiesAlwaysOnCheckBox.Location = new System.Drawing.Point(131, 58); + this.TimedEntitiesAlwaysOnCheckBox.Name = "TimedEntitiesAlwaysOnCheckBox"; + this.TimedEntitiesAlwaysOnCheckBox.Size = new System.Drawing.Size(58, 17); + this.TimedEntitiesAlwaysOnCheckBox.TabIndex = 37; + this.TimedEntitiesAlwaysOnCheckBox.Text = "always"; + this.TimedEntitiesAlwaysOnCheckBox.UseVisualStyleBackColor = true; + this.TimedEntitiesAlwaysOnCheckBox.CheckedChanged += new System.EventHandler(this.TimedEntitiesAlwaysOnCheckBox_CheckedChanged); + // + // GrassCheckBox + // + this.GrassCheckBox.AutoSize = true; + this.GrassCheckBox.Checked = true; + this.GrassCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.GrassCheckBox.Location = new System.Drawing.Point(10, 35); + this.GrassCheckBox.Name = "GrassCheckBox"; + this.GrassCheckBox.Size = new System.Drawing.Size(81, 17); + this.GrassCheckBox.TabIndex = 35; + this.GrassCheckBox.Text = "Show grass"; + this.GrassCheckBox.UseVisualStyleBackColor = true; + this.GrassCheckBox.CheckedChanged += new System.EventHandler(this.GrassCheckBox_CheckedChanged); + // + // InteriorsCheckBox + // + this.InteriorsCheckBox.AutoSize = true; + this.InteriorsCheckBox.Checked = true; + this.InteriorsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.InteriorsCheckBox.Location = new System.Drawing.Point(10, 81); + this.InteriorsCheckBox.Name = "InteriorsCheckBox"; + this.InteriorsCheckBox.Size = new System.Drawing.Size(92, 17); + this.InteriorsCheckBox.TabIndex = 38; + this.InteriorsCheckBox.Text = "Show interiors"; + this.InteriorsCheckBox.UseVisualStyleBackColor = true; + this.InteriorsCheckBox.CheckedChanged += new System.EventHandler(this.InteriorsCheckBox_CheckedChanged); + // + // CollisionMeshLayerDrawableCheckBox + // + this.CollisionMeshLayerDrawableCheckBox.AutoSize = true; + this.CollisionMeshLayerDrawableCheckBox.Checked = true; + this.CollisionMeshLayerDrawableCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.CollisionMeshLayerDrawableCheckBox.Location = new System.Drawing.Point(118, 247); + this.CollisionMeshLayerDrawableCheckBox.Name = "CollisionMeshLayerDrawableCheckBox"; + this.CollisionMeshLayerDrawableCheckBox.Size = new System.Drawing.Size(71, 17); + this.CollisionMeshLayerDrawableCheckBox.TabIndex = 52; + this.CollisionMeshLayerDrawableCheckBox.Text = "Drawable"; + this.CollisionMeshLayerDrawableCheckBox.UseVisualStyleBackColor = true; + this.CollisionMeshLayerDrawableCheckBox.CheckedChanged += new System.EventHandler(this.CollisionMeshLayerDrawableCheckBox_CheckedChanged); + // + // CollisionMeshLayer2CheckBox + // + this.CollisionMeshLayer2CheckBox.AutoSize = true; + this.CollisionMeshLayer2CheckBox.Checked = true; + this.CollisionMeshLayer2CheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.CollisionMeshLayer2CheckBox.Location = new System.Drawing.Point(82, 247); + this.CollisionMeshLayer2CheckBox.Name = "CollisionMeshLayer2CheckBox"; + this.CollisionMeshLayer2CheckBox.Size = new System.Drawing.Size(32, 17); + this.CollisionMeshLayer2CheckBox.TabIndex = 51; + this.CollisionMeshLayer2CheckBox.Text = "2"; + this.CollisionMeshLayer2CheckBox.UseVisualStyleBackColor = true; + this.CollisionMeshLayer2CheckBox.CheckedChanged += new System.EventHandler(this.CollisionMeshLayer2CheckBox_CheckedChanged); + // + // CollisionMeshLayer1CheckBox + // + this.CollisionMeshLayer1CheckBox.AutoSize = true; + this.CollisionMeshLayer1CheckBox.Checked = true; + this.CollisionMeshLayer1CheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.CollisionMeshLayer1CheckBox.Location = new System.Drawing.Point(46, 247); + this.CollisionMeshLayer1CheckBox.Name = "CollisionMeshLayer1CheckBox"; + this.CollisionMeshLayer1CheckBox.Size = new System.Drawing.Size(32, 17); + this.CollisionMeshLayer1CheckBox.TabIndex = 50; + this.CollisionMeshLayer1CheckBox.Text = "1"; + this.CollisionMeshLayer1CheckBox.UseVisualStyleBackColor = true; + this.CollisionMeshLayer1CheckBox.CheckedChanged += new System.EventHandler(this.CollisionMeshLayer1CheckBox_CheckedChanged); + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(4, 229); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(106, 13); + this.label13.TabIndex = 54; + this.label13.Text = "Collision mesh layers:"; + // + // CollisionMeshLayer0CheckBox + // + this.CollisionMeshLayer0CheckBox.AutoSize = true; + this.CollisionMeshLayer0CheckBox.Checked = true; + this.CollisionMeshLayer0CheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.CollisionMeshLayer0CheckBox.Location = new System.Drawing.Point(10, 247); + this.CollisionMeshLayer0CheckBox.Name = "CollisionMeshLayer0CheckBox"; + this.CollisionMeshLayer0CheckBox.Size = new System.Drawing.Size(32, 17); + this.CollisionMeshLayer0CheckBox.TabIndex = 49; + this.CollisionMeshLayer0CheckBox.Text = "0"; + this.CollisionMeshLayer0CheckBox.UseVisualStyleBackColor = true; + this.CollisionMeshLayer0CheckBox.CheckedChanged += new System.EventHandler(this.CollisionMeshLayer0CheckBox_CheckedChanged); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(4, 178); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(106, 13); + this.label12.TabIndex = 51; + this.label12.Text = "Collision mesh range:"; + // + // CollisionMeshRangeTrackBar + // + this.CollisionMeshRangeTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CollisionMeshRangeTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.CollisionMeshRangeTrackBar.LargeChange = 1; + this.CollisionMeshRangeTrackBar.Location = new System.Drawing.Point(6, 194); + this.CollisionMeshRangeTrackBar.Minimum = 1; + this.CollisionMeshRangeTrackBar.Name = "CollisionMeshRangeTrackBar"; + this.CollisionMeshRangeTrackBar.Size = new System.Drawing.Size(188, 45); + this.CollisionMeshRangeTrackBar.TabIndex = 48; + this.CollisionMeshRangeTrackBar.Value = 6; + this.CollisionMeshRangeTrackBar.Scroll += new System.EventHandler(this.CollisionMeshRangeTrackBar_Scroll); + // + // CollisionMeshesCheckBox + // + this.CollisionMeshesCheckBox.AutoSize = true; + this.CollisionMeshesCheckBox.Location = new System.Drawing.Point(10, 156); + this.CollisionMeshesCheckBox.Name = "CollisionMeshesCheckBox"; + this.CollisionMeshesCheckBox.Size = new System.Drawing.Size(132, 17); + this.CollisionMeshesCheckBox.TabIndex = 47; + this.CollisionMeshesCheckBox.Text = "Show collision meshes"; + this.CollisionMeshesCheckBox.UseVisualStyleBackColor = true; + this.CollisionMeshesCheckBox.CheckedChanged += new System.EventHandler(this.CollisionMeshesCheckBox_CheckedChanged); + // + // FullScreenCheckBox + // + this.FullScreenCheckBox.AutoSize = true; + this.FullScreenCheckBox.Location = new System.Drawing.Point(10, 9); + this.FullScreenCheckBox.Name = "FullScreenCheckBox"; + this.FullScreenCheckBox.Size = new System.Drawing.Size(173, 17); + this.FullScreenCheckBox.TabIndex = 28; + this.FullScreenCheckBox.Text = "Full screen (borderless window)"; + this.FullScreenCheckBox.UseVisualStyleBackColor = true; + this.FullScreenCheckBox.CheckedChanged += new System.EventHandler(this.FullScreenCheckBox_CheckedChanged); + // + // TimedEntitiesCheckBox + // + this.TimedEntitiesCheckBox.AutoSize = true; + this.TimedEntitiesCheckBox.Checked = true; + this.TimedEntitiesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.TimedEntitiesCheckBox.Location = new System.Drawing.Point(10, 58); + this.TimedEntitiesCheckBox.Name = "TimedEntitiesCheckBox"; + this.TimedEntitiesCheckBox.Size = new System.Drawing.Size(117, 17); + this.TimedEntitiesCheckBox.TabIndex = 36; + this.TimedEntitiesCheckBox.Text = "Show timed entities"; + this.TimedEntitiesCheckBox.UseVisualStyleBackColor = true; + this.TimedEntitiesCheckBox.CheckedChanged += new System.EventHandler(this.TimedEntitiesCheckBox_CheckedChanged); + // + // FieldOfViewTrackBar + // + this.FieldOfViewTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.FieldOfViewTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.FieldOfViewTrackBar.LargeChange = 1; + this.FieldOfViewTrackBar.Location = new System.Drawing.Point(6, 351); + this.FieldOfViewTrackBar.Maximum = 200; + this.FieldOfViewTrackBar.Minimum = 10; + this.FieldOfViewTrackBar.Name = "FieldOfViewTrackBar"; + this.FieldOfViewTrackBar.Size = new System.Drawing.Size(188, 45); + this.FieldOfViewTrackBar.TabIndex = 57; + this.FieldOfViewTrackBar.TickFrequency = 10; + this.FieldOfViewTrackBar.Value = 100; + this.FieldOfViewTrackBar.Scroll += new System.EventHandler(this.FieldOfViewTrackBar_Scroll); + // + // tabPage14 + // + this.tabPage14.Controls.Add(this.WireframeCheckBox); + this.tabPage14.Controls.Add(this.RenderModeComboBox); + this.tabPage14.Controls.Add(this.label11); + this.tabPage14.Controls.Add(this.TextureSamplerComboBox); + this.tabPage14.Controls.Add(this.TextureCoordsComboBox); + this.tabPage14.Controls.Add(this.label10); + this.tabPage14.Controls.Add(this.AnisotropicFilteringCheckBox); + this.tabPage14.Controls.Add(this.ProxiesCheckBox); + this.tabPage14.Controls.Add(this.WaitForChildrenCheckBox); + this.tabPage14.Controls.Add(this.label14); + this.tabPage14.Location = new System.Drawing.Point(4, 22); + this.tabPage14.Name = "tabPage14"; + this.tabPage14.Size = new System.Drawing.Size(200, 482); + this.tabPage14.TabIndex = 3; + this.tabPage14.Text = "Render"; + this.tabPage14.UseVisualStyleBackColor = true; + // + // WireframeCheckBox + // + this.WireframeCheckBox.AutoSize = true; + this.WireframeCheckBox.Location = new System.Drawing.Point(10, 115); + this.WireframeCheckBox.Name = "WireframeCheckBox"; + this.WireframeCheckBox.Size = new System.Drawing.Size(74, 17); + this.WireframeCheckBox.TabIndex = 49; + this.WireframeCheckBox.Text = "Wireframe"; + this.WireframeCheckBox.UseVisualStyleBackColor = true; + this.WireframeCheckBox.CheckedChanged += new System.EventHandler(this.WireframeCheckBox_CheckedChanged); + // + // RenderModeComboBox + // + this.RenderModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.RenderModeComboBox.FormattingEnabled = true; + this.RenderModeComboBox.Items.AddRange(new object[] { + "Default", + "Single texture", + "Vertex normals", + "Vertex tangents", + "Vertex colour 1", + "Vertex colour 2", + "Texture coord 1", + "Texture coord 2", + "Texture coord 3"}); + this.RenderModeComboBox.Location = new System.Drawing.Point(80, 16); + this.RenderModeComboBox.Name = "RenderModeComboBox"; + this.RenderModeComboBox.Size = new System.Drawing.Size(114, 21); + this.RenderModeComboBox.TabIndex = 46; + this.RenderModeComboBox.SelectedIndexChanged += new System.EventHandler(this.RenderModeComboBox_SelectedIndexChanged); + this.RenderModeComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.RenderModeComboBox_KeyPress); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(4, 46); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(67, 13); + this.label11.TabIndex = 50; + this.label11.Text = "Tex sampler:"; + // + // TextureSamplerComboBox + // + this.TextureSamplerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.TextureSamplerComboBox.Enabled = false; + this.TextureSamplerComboBox.FormattingEnabled = true; + this.TextureSamplerComboBox.Location = new System.Drawing.Point(80, 43); + this.TextureSamplerComboBox.Name = "TextureSamplerComboBox"; + this.TextureSamplerComboBox.Size = new System.Drawing.Size(114, 21); + this.TextureSamplerComboBox.TabIndex = 47; + this.TextureSamplerComboBox.SelectedIndexChanged += new System.EventHandler(this.TextureSamplerComboBox_SelectedIndexChanged); + this.TextureSamplerComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.TextureSamplerComboBox_KeyPress); + // + // TextureCoordsComboBox + // + this.TextureCoordsComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.TextureCoordsComboBox.Enabled = false; + this.TextureCoordsComboBox.FormattingEnabled = true; + this.TextureCoordsComboBox.Items.AddRange(new object[] { + "Texture coord 1", + "Texture coord 2", + "Texture coord 3"}); + this.TextureCoordsComboBox.Location = new System.Drawing.Point(80, 70); + this.TextureCoordsComboBox.Name = "TextureCoordsComboBox"; + this.TextureCoordsComboBox.Size = new System.Drawing.Size(114, 21); + this.TextureCoordsComboBox.TabIndex = 48; + this.TextureCoordsComboBox.SelectedIndexChanged += new System.EventHandler(this.TextureCoordsComboBox_SelectedIndexChanged); + this.TextureCoordsComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.TextureCoordsComboBox_KeyPress); + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(4, 19); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(74, 13); + this.label10.TabIndex = 48; + this.label10.Text = "Render mode:"; + // + // AnisotropicFilteringCheckBox + // + this.AnisotropicFilteringCheckBox.AutoSize = true; + this.AnisotropicFilteringCheckBox.Checked = true; + this.AnisotropicFilteringCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.AnisotropicFilteringCheckBox.Location = new System.Drawing.Point(10, 138); + this.AnisotropicFilteringCheckBox.Name = "AnisotropicFilteringCheckBox"; + this.AnisotropicFilteringCheckBox.Size = new System.Drawing.Size(114, 17); + this.AnisotropicFilteringCheckBox.TabIndex = 50; + this.AnisotropicFilteringCheckBox.Text = "Anisotropic filtering"; + this.AnisotropicFilteringCheckBox.UseVisualStyleBackColor = true; + this.AnisotropicFilteringCheckBox.CheckedChanged += new System.EventHandler(this.AnisotropicFilteringCheckBox_CheckedChanged); + // + // ProxiesCheckBox + // + this.ProxiesCheckBox.AutoSize = true; + this.ProxiesCheckBox.Location = new System.Drawing.Point(10, 199); + this.ProxiesCheckBox.Name = "ProxiesCheckBox"; + this.ProxiesCheckBox.Size = new System.Drawing.Size(89, 17); + this.ProxiesCheckBox.TabIndex = 52; + this.ProxiesCheckBox.Text = "Show proxies"; + this.ProxiesCheckBox.UseVisualStyleBackColor = true; + this.ProxiesCheckBox.CheckedChanged += new System.EventHandler(this.ProxiesCheckBox_CheckedChanged); + // + // WaitForChildrenCheckBox + // + this.WaitForChildrenCheckBox.AutoSize = true; + this.WaitForChildrenCheckBox.Checked = true; + this.WaitForChildrenCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.WaitForChildrenCheckBox.Location = new System.Drawing.Point(10, 161); + this.WaitForChildrenCheckBox.Name = "WaitForChildrenCheckBox"; + this.WaitForChildrenCheckBox.Size = new System.Drawing.Size(138, 17); + this.WaitForChildrenCheckBox.TabIndex = 51; + this.WaitForChildrenCheckBox.Text = "Wait for children to load"; + this.WaitForChildrenCheckBox.UseVisualStyleBackColor = true; + this.WaitForChildrenCheckBox.CheckedChanged += new System.EventHandler(this.WaitForChildrenCheckBox_CheckedChanged); + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(4, 73); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(63, 13); + this.label14.TabIndex = 56; + this.label14.Text = "Tex coords:"; + // + // tabPage9 + // + this.tabPage9.Controls.Add(this.NavMeshesCheckBox); + this.tabPage9.Controls.Add(this.TrainPathsCheckBox); + this.tabPage9.Controls.Add(this.PathsDepthClipCheckBox); + this.tabPage9.Controls.Add(this.PathBoundsCheckBox); + this.tabPage9.Controls.Add(this.SelectionWidgetCheckBox); + this.tabPage9.Controls.Add(this.MarkerStyleComboBox); + this.tabPage9.Controls.Add(this.ShowToolbarCheckBox); + this.tabPage9.Controls.Add(this.label4); + this.tabPage9.Controls.Add(this.LocatorStyleComboBox); + this.tabPage9.Controls.Add(this.label5); + this.tabPage9.Controls.Add(this.MarkerDepthClipCheckBox); + this.tabPage9.Controls.Add(this.label9); + this.tabPage9.Controls.Add(this.PathsCheckBox); + this.tabPage9.Controls.Add(this.SelectionBoundsCheckBox); + this.tabPage9.Controls.Add(this.BoundsDepthClipCheckBox); + this.tabPage9.Controls.Add(this.BoundsRangeTrackBar); + this.tabPage9.Controls.Add(this.BoundsStyleComboBox); + this.tabPage9.Controls.Add(this.label8); + this.tabPage9.Location = new System.Drawing.Point(4, 22); + this.tabPage9.Name = "tabPage9"; + this.tabPage9.Padding = new System.Windows.Forms.Padding(3); + this.tabPage9.Size = new System.Drawing.Size(200, 482); + this.tabPage9.TabIndex = 1; + this.tabPage9.Text = "Helpers"; + this.tabPage9.UseVisualStyleBackColor = true; + // + // NavMeshesCheckBox + // + this.NavMeshesCheckBox.AutoSize = true; + this.NavMeshesCheckBox.Location = new System.Drawing.Point(10, 365); + this.NavMeshesCheckBox.Name = "NavMeshesCheckBox"; + this.NavMeshesCheckBox.Size = new System.Drawing.Size(113, 17); + this.NavMeshesCheckBox.TabIndex = 51; + this.NavMeshesCheckBox.Text = "Show nav meshes"; + this.NavMeshesCheckBox.UseVisualStyleBackColor = true; + this.NavMeshesCheckBox.CheckedChanged += new System.EventHandler(this.NavMeshesCheckBox_CheckedChanged); + // + // TrainPathsCheckBox + // + this.TrainPathsCheckBox.AutoSize = true; + this.TrainPathsCheckBox.Location = new System.Drawing.Point(10, 342); + this.TrainPathsCheckBox.Name = "TrainPathsCheckBox"; + this.TrainPathsCheckBox.Size = new System.Drawing.Size(105, 17); + this.TrainPathsCheckBox.TabIndex = 50; + this.TrainPathsCheckBox.Text = "Show train paths"; + this.TrainPathsCheckBox.UseVisualStyleBackColor = true; + this.TrainPathsCheckBox.CheckedChanged += new System.EventHandler(this.TrainPathsCheckBox_CheckedChanged); + // + // PathsDepthClipCheckBox + // + this.PathsDepthClipCheckBox.AutoSize = true; + this.PathsDepthClipCheckBox.Location = new System.Drawing.Point(10, 388); + this.PathsDepthClipCheckBox.Name = "PathsDepthClipCheckBox"; + this.PathsDepthClipCheckBox.Size = new System.Drawing.Size(102, 17); + this.PathsDepthClipCheckBox.TabIndex = 52; + this.PathsDepthClipCheckBox.Text = "Paths depth clip"; + this.PathsDepthClipCheckBox.UseVisualStyleBackColor = true; + this.PathsDepthClipCheckBox.CheckedChanged += new System.EventHandler(this.PathsDepthClipCheckBox_CheckedChanged); + // + // PathBoundsCheckBox + // + this.PathBoundsCheckBox.AutoSize = true; + this.PathBoundsCheckBox.Checked = true; + this.PathBoundsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.PathBoundsCheckBox.Location = new System.Drawing.Point(98, 319); + this.PathBoundsCheckBox.Name = "PathBoundsCheckBox"; + this.PathBoundsCheckBox.Size = new System.Drawing.Size(86, 17); + this.PathBoundsCheckBox.TabIndex = 49; + this.PathBoundsCheckBox.Text = "Path bounds"; + this.PathBoundsCheckBox.UseVisualStyleBackColor = true; + this.PathBoundsCheckBox.CheckedChanged += new System.EventHandler(this.PathBoundsCheckBox_CheckedChanged); + // + // SelectionWidgetCheckBox + // + this.SelectionWidgetCheckBox.AutoSize = true; + this.SelectionWidgetCheckBox.Checked = true; + this.SelectionWidgetCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.SelectionWidgetCheckBox.Location = new System.Drawing.Point(10, 241); + this.SelectionWidgetCheckBox.Name = "SelectionWidgetCheckBox"; + this.SelectionWidgetCheckBox.Size = new System.Drawing.Size(87, 17); + this.SelectionWidgetCheckBox.TabIndex = 46; + this.SelectionWidgetCheckBox.Text = "Show widget"; + this.SelectionWidgetCheckBox.UseVisualStyleBackColor = true; + this.SelectionWidgetCheckBox.CheckedChanged += new System.EventHandler(this.SelectionWidgetCheckBox_CheckedChanged); + // + // MarkerStyleComboBox + // + this.MarkerStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.MarkerStyleComboBox.FormattingEnabled = true; + this.MarkerStyleComboBox.Location = new System.Drawing.Point(80, 6); + this.MarkerStyleComboBox.Name = "MarkerStyleComboBox"; + this.MarkerStyleComboBox.Size = new System.Drawing.Size(114, 21); + this.MarkerStyleComboBox.TabIndex = 38; + this.MarkerStyleComboBox.SelectedIndexChanged += new System.EventHandler(this.MarkerStyleComboBox_SelectedIndexChanged); + this.MarkerStyleComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.MarkerStyleComboBox_KeyPress); + // + // ShowToolbarCheckBox + // + this.ShowToolbarCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.ShowToolbarCheckBox.AutoSize = true; + this.ShowToolbarCheckBox.Location = new System.Drawing.Point(10, 264); + this.ShowToolbarCheckBox.Name = "ShowToolbarCheckBox"; + this.ShowToolbarCheckBox.Size = new System.Drawing.Size(108, 17); + this.ShowToolbarCheckBox.TabIndex = 47; + this.ShowToolbarCheckBox.Text = "Show Toolbar (T)"; + this.ShowToolbarCheckBox.UseVisualStyleBackColor = true; + this.ShowToolbarCheckBox.CheckedChanged += new System.EventHandler(this.ShowToolbarCheckBox_CheckedChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(4, 9); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 13); + this.label4.TabIndex = 17; + this.label4.Text = "Marker style:"; + // + // LocatorStyleComboBox + // + this.LocatorStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.LocatorStyleComboBox.FormattingEnabled = true; + this.LocatorStyleComboBox.Location = new System.Drawing.Point(80, 33); + this.LocatorStyleComboBox.Name = "LocatorStyleComboBox"; + this.LocatorStyleComboBox.Size = new System.Drawing.Size(114, 21); + this.LocatorStyleComboBox.TabIndex = 39; + this.LocatorStyleComboBox.SelectedIndexChanged += new System.EventHandler(this.LocatorStyleComboBox_SelectedIndexChanged); + this.LocatorStyleComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.LocatorStyleComboBox_KeyPress); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(4, 36); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(70, 13); + this.label5.TabIndex = 19; + this.label5.Text = "Locator style:"; + // + // MarkerDepthClipCheckBox + // + this.MarkerDepthClipCheckBox.AutoSize = true; + this.MarkerDepthClipCheckBox.Location = new System.Drawing.Point(10, 60); + this.MarkerDepthClipCheckBox.Name = "MarkerDepthClipCheckBox"; + this.MarkerDepthClipCheckBox.Size = new System.Drawing.Size(108, 17); + this.MarkerDepthClipCheckBox.TabIndex = 40; + this.MarkerDepthClipCheckBox.Text = "Marker depth clip"; + this.MarkerDepthClipCheckBox.UseVisualStyleBackColor = true; + this.MarkerDepthClipCheckBox.Visible = false; + this.MarkerDepthClipCheckBox.CheckedChanged += new System.EventHandler(this.MarkerDepthClipCheckBox_CheckedChanged); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(4, 151); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(76, 13); + this.label9.TabIndex = 27; + this.label9.Text = "Bounds range:"; + // + // PathsCheckBox + // + this.PathsCheckBox.AutoSize = true; + this.PathsCheckBox.Location = new System.Drawing.Point(10, 319); + this.PathsCheckBox.Name = "PathsCheckBox"; + this.PathsCheckBox.Size = new System.Drawing.Size(82, 17); + this.PathsCheckBox.TabIndex = 48; + this.PathsCheckBox.Text = "Show paths"; + this.PathsCheckBox.UseVisualStyleBackColor = true; + this.PathsCheckBox.CheckedChanged += new System.EventHandler(this.PathsCheckBox_CheckedChanged); + // + // SelectionBoundsCheckBox + // + this.SelectionBoundsCheckBox.AutoSize = true; + this.SelectionBoundsCheckBox.Checked = true; + this.SelectionBoundsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.SelectionBoundsCheckBox.Location = new System.Drawing.Point(10, 218); + this.SelectionBoundsCheckBox.Name = "SelectionBoundsCheckBox"; + this.SelectionBoundsCheckBox.Size = new System.Drawing.Size(136, 17); + this.SelectionBoundsCheckBox.TabIndex = 45; + this.SelectionBoundsCheckBox.Text = "Show selection bounds"; + this.SelectionBoundsCheckBox.UseVisualStyleBackColor = true; + this.SelectionBoundsCheckBox.CheckedChanged += new System.EventHandler(this.SelectionBoundsCheckBox_CheckedChanged); + // + // BoundsDepthClipCheckBox + // + this.BoundsDepthClipCheckBox.AutoSize = true; + this.BoundsDepthClipCheckBox.Checked = true; + this.BoundsDepthClipCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.BoundsDepthClipCheckBox.Location = new System.Drawing.Point(10, 129); + this.BoundsDepthClipCheckBox.Name = "BoundsDepthClipCheckBox"; + this.BoundsDepthClipCheckBox.Size = new System.Drawing.Size(111, 17); + this.BoundsDepthClipCheckBox.TabIndex = 42; + this.BoundsDepthClipCheckBox.Text = "Bounds depth clip"; + this.BoundsDepthClipCheckBox.UseVisualStyleBackColor = true; + this.BoundsDepthClipCheckBox.CheckedChanged += new System.EventHandler(this.BoundsDepthClipCheckBox_CheckedChanged); + // + // BoundsRangeTrackBar + // + this.BoundsRangeTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.BoundsRangeTrackBar.LargeChange = 10; + this.BoundsRangeTrackBar.Location = new System.Drawing.Point(15, 167); + this.BoundsRangeTrackBar.Maximum = 100; + this.BoundsRangeTrackBar.Minimum = 1; + this.BoundsRangeTrackBar.Name = "BoundsRangeTrackBar"; + this.BoundsRangeTrackBar.Size = new System.Drawing.Size(179, 45); + this.BoundsRangeTrackBar.TabIndex = 43; + this.BoundsRangeTrackBar.TickFrequency = 10; + this.BoundsRangeTrackBar.Value = 100; + this.BoundsRangeTrackBar.Scroll += new System.EventHandler(this.BoundsRangeTrackBar_Scroll); + // + // BoundsStyleComboBox + // + this.BoundsStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.BoundsStyleComboBox.FormattingEnabled = true; + this.BoundsStyleComboBox.Items.AddRange(new object[] { + "None", + "Boxes", + "Spheres"}); + this.BoundsStyleComboBox.Location = new System.Drawing.Point(80, 102); + this.BoundsStyleComboBox.Name = "BoundsStyleComboBox"; + this.BoundsStyleComboBox.Size = new System.Drawing.Size(114, 21); + this.BoundsStyleComboBox.TabIndex = 41; + this.BoundsStyleComboBox.SelectedIndexChanged += new System.EventHandler(this.BoundsStyleComboBox_SelectedIndexChanged); + this.BoundsStyleComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.BoundsStyleComboBox_KeyPress); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(4, 105); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(70, 13); + this.label8.TabIndex = 25; + this.label8.Text = "Bounds style:"; + // + // tabPage10 + // + this.tabPage10.Controls.Add(this.WeatherRegionComboBox); + this.tabPage10.Controls.Add(this.label29); + this.tabPage10.Controls.Add(this.CloudParamTrackBar); + this.tabPage10.Controls.Add(this.CloudParamComboBox); + this.tabPage10.Controls.Add(this.label23); + this.tabPage10.Controls.Add(this.CloudsComboBox); + this.tabPage10.Controls.Add(this.label21); + this.tabPage10.Controls.Add(this.TimeSpeedLabel); + this.tabPage10.Controls.Add(this.label20); + this.tabPage10.Controls.Add(this.TimeSpeedTrackBar); + this.tabPage10.Controls.Add(this.TimeStartStopButton); + this.tabPage10.Controls.Add(this.ArtificialAmbientLightCheckBox); + this.tabPage10.Controls.Add(this.NaturalAmbientLightCheckBox); + this.tabPage10.Controls.Add(this.DistantLODLightsCheckBox); + this.tabPage10.Controls.Add(this.HDRRenderingCheckBox); + this.tabPage10.Controls.Add(this.ControlTimeOfDayCheckBox); + this.tabPage10.Controls.Add(this.TimeOfDayLabel); + this.tabPage10.Controls.Add(this.label19); + this.tabPage10.Controls.Add(this.TimeOfDayTrackBar); + this.tabPage10.Controls.Add(this.WeatherComboBox); + this.tabPage10.Controls.Add(this.label17); + this.tabPage10.Controls.Add(this.ControlLightDirectionCheckBox); + this.tabPage10.Controls.Add(this.SkydomeCheckBox); + this.tabPage10.Controls.Add(this.ShadowsCheckBox); + this.tabPage10.Location = new System.Drawing.Point(4, 22); + this.tabPage10.Name = "tabPage10"; + this.tabPage10.Size = new System.Drawing.Size(200, 482); + this.tabPage10.TabIndex = 2; + this.tabPage10.Text = "Lighting"; + this.tabPage10.UseVisualStyleBackColor = true; + // + // WeatherRegionComboBox + // + this.WeatherRegionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.WeatherRegionComboBox.FormattingEnabled = true; + this.WeatherRegionComboBox.Items.AddRange(new object[] { + "GLOBAL", + "URBAN"}); + this.WeatherRegionComboBox.Location = new System.Drawing.Point(61, 355); + this.WeatherRegionComboBox.Name = "WeatherRegionComboBox"; + this.WeatherRegionComboBox.Size = new System.Drawing.Size(133, 21); + this.WeatherRegionComboBox.TabIndex = 43; + this.WeatherRegionComboBox.SelectedIndexChanged += new System.EventHandler(this.WeatherRegionComboBox_SelectedIndexChanged); + this.WeatherRegionComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.WeatherRegionComboBox_KeyPress); + // + // label29 + // + this.label29.AutoSize = true; + this.label29.Location = new System.Drawing.Point(4, 358); + this.label29.Name = "label29"; + this.label29.Size = new System.Drawing.Size(44, 13); + this.label29.TabIndex = 64; + this.label29.Text = "Region:"; + // + // CloudParamTrackBar + // + this.CloudParamTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CloudParamTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.CloudParamTrackBar.LargeChange = 10; + this.CloudParamTrackBar.Location = new System.Drawing.Point(6, 436); + this.CloudParamTrackBar.Maximum = 200; + this.CloudParamTrackBar.Name = "CloudParamTrackBar"; + this.CloudParamTrackBar.Size = new System.Drawing.Size(188, 45); + this.CloudParamTrackBar.TabIndex = 63; + this.CloudParamTrackBar.TickFrequency = 10; + this.CloudParamTrackBar.Value = 100; + this.CloudParamTrackBar.Scroll += new System.EventHandler(this.CloudParamTrackBar_Scroll); + // + // CloudParamComboBox + // + this.CloudParamComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CloudParamComboBox.FormattingEnabled = true; + this.CloudParamComboBox.Items.AddRange(new object[] { + ""}); + this.CloudParamComboBox.Location = new System.Drawing.Point(78, 409); + this.CloudParamComboBox.Name = "CloudParamComboBox"; + this.CloudParamComboBox.Size = new System.Drawing.Size(116, 21); + this.CloudParamComboBox.TabIndex = 62; + this.CloudParamComboBox.SelectedIndexChanged += new System.EventHandler(this.CloudParamComboBox_SelectedIndexChanged); + this.CloudParamComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.CloudParamComboBox_KeyPress); + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(4, 412); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(69, 13); + this.label23.TabIndex = 61; + this.label23.Text = "Cloud param:"; + // + // CloudsComboBox + // + this.CloudsComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CloudsComboBox.FormattingEnabled = true; + this.CloudsComboBox.Items.AddRange(new object[] { + ""}); + this.CloudsComboBox.Location = new System.Drawing.Point(61, 382); + this.CloudsComboBox.Name = "CloudsComboBox"; + this.CloudsComboBox.Size = new System.Drawing.Size(133, 21); + this.CloudsComboBox.TabIndex = 60; + this.CloudsComboBox.SelectedIndexChanged += new System.EventHandler(this.CloudsComboBox_SelectedIndexChanged); + this.CloudsComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.CloudsComboBox_KeyPress); + // + // label21 + // + this.label21.AutoSize = true; + this.label21.Location = new System.Drawing.Point(4, 385); + this.label21.Name = "label21"; + this.label21.Size = new System.Drawing.Size(42, 13); + this.label21.TabIndex = 59; + this.label21.Text = "Clouds:"; + // + // TimeSpeedLabel + // + this.TimeSpeedLabel.AutoSize = true; + this.TimeSpeedLabel.Location = new System.Drawing.Point(78, 263); + this.TimeSpeedLabel.Name = "TimeSpeedLabel"; + this.TimeSpeedLabel.Size = new System.Drawing.Size(63, 13); + this.TimeSpeedLabel.TabIndex = 58; + this.TimeSpeedLabel.Text = "0.5 min/sec"; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(3, 263); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(65, 13); + this.label20.TabIndex = 57; + this.label20.Text = "Time speed:"; + // + // TimeSpeedTrackBar + // + this.TimeSpeedTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TimeSpeedTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.TimeSpeedTrackBar.Location = new System.Drawing.Point(61, 279); + this.TimeSpeedTrackBar.Maximum = 100; + this.TimeSpeedTrackBar.Minimum = 40; + this.TimeSpeedTrackBar.Name = "TimeSpeedTrackBar"; + this.TimeSpeedTrackBar.Size = new System.Drawing.Size(133, 45); + this.TimeSpeedTrackBar.TabIndex = 41; + this.TimeSpeedTrackBar.TickFrequency = 5; + this.TimeSpeedTrackBar.Value = 50; + this.TimeSpeedTrackBar.Scroll += new System.EventHandler(this.TimeSpeedTrackBar_Scroll); + // + // TimeStartStopButton + // + this.TimeStartStopButton.Location = new System.Drawing.Point(10, 279); + this.TimeStartStopButton.Name = "TimeStartStopButton"; + this.TimeStartStopButton.Size = new System.Drawing.Size(45, 23); + this.TimeStartStopButton.TabIndex = 40; + this.TimeStartStopButton.Text = "Start"; + this.TimeStartStopButton.UseVisualStyleBackColor = true; + this.TimeStartStopButton.Click += new System.EventHandler(this.TimeStartStopButton_Click); + // + // ArtificialAmbientLightCheckBox + // + this.ArtificialAmbientLightCheckBox.AutoSize = true; + this.ArtificialAmbientLightCheckBox.Checked = true; + this.ArtificialAmbientLightCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.ArtificialAmbientLightCheckBox.Location = new System.Drawing.Point(10, 129); + this.ArtificialAmbientLightCheckBox.Name = "ArtificialAmbientLightCheckBox"; + this.ArtificialAmbientLightCheckBox.Size = new System.Drawing.Size(124, 17); + this.ArtificialAmbientLightCheckBox.TabIndex = 36; + this.ArtificialAmbientLightCheckBox.Text = "Artificial ambient light"; + this.ArtificialAmbientLightCheckBox.UseVisualStyleBackColor = true; + this.ArtificialAmbientLightCheckBox.CheckedChanged += new System.EventHandler(this.ArtificialAmbientLightCheckBox_CheckedChanged); + // + // NaturalAmbientLightCheckBox + // + this.NaturalAmbientLightCheckBox.AutoSize = true; + this.NaturalAmbientLightCheckBox.Checked = true; + this.NaturalAmbientLightCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.NaturalAmbientLightCheckBox.Location = new System.Drawing.Point(10, 106); + this.NaturalAmbientLightCheckBox.Name = "NaturalAmbientLightCheckBox"; + this.NaturalAmbientLightCheckBox.Size = new System.Drawing.Size(122, 17); + this.NaturalAmbientLightCheckBox.TabIndex = 35; + this.NaturalAmbientLightCheckBox.Text = "Natural ambient light"; + this.NaturalAmbientLightCheckBox.UseVisualStyleBackColor = true; + this.NaturalAmbientLightCheckBox.CheckedChanged += new System.EventHandler(this.NaturalAmbientLightCheckBox_CheckedChanged); + // + // DistantLODLightsCheckBox + // + this.DistantLODLightsCheckBox.AutoSize = true; + this.DistantLODLightsCheckBox.Checked = true; + this.DistantLODLightsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.DistantLODLightsCheckBox.Location = new System.Drawing.Point(10, 83); + this.DistantLODLightsCheckBox.Name = "DistantLODLightsCheckBox"; + this.DistantLODLightsCheckBox.Size = new System.Drawing.Size(111, 17); + this.DistantLODLightsCheckBox.TabIndex = 34; + this.DistantLODLightsCheckBox.Text = "Distant LOD lights"; + this.DistantLODLightsCheckBox.UseVisualStyleBackColor = true; + this.DistantLODLightsCheckBox.CheckedChanged += new System.EventHandler(this.DistantLODLightsCheckBox_CheckedChanged); + // + // HDRRenderingCheckBox + // + this.HDRRenderingCheckBox.AutoSize = true; + this.HDRRenderingCheckBox.Checked = true; + this.HDRRenderingCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.HDRRenderingCheckBox.Location = new System.Drawing.Point(10, 9); + this.HDRRenderingCheckBox.Name = "HDRRenderingCheckBox"; + this.HDRRenderingCheckBox.Size = new System.Drawing.Size(97, 17); + this.HDRRenderingCheckBox.TabIndex = 31; + this.HDRRenderingCheckBox.Text = "HDR rendering"; + this.HDRRenderingCheckBox.UseVisualStyleBackColor = true; + this.HDRRenderingCheckBox.CheckedChanged += new System.EventHandler(this.HDRRenderingCheckBox_CheckedChanged); + // + // ControlTimeOfDayCheckBox + // + this.ControlTimeOfDayCheckBox.AutoSize = true; + this.ControlTimeOfDayCheckBox.Checked = true; + this.ControlTimeOfDayCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.ControlTimeOfDayCheckBox.Location = new System.Drawing.Point(10, 180); + this.ControlTimeOfDayCheckBox.Name = "ControlTimeOfDayCheckBox"; + this.ControlTimeOfDayCheckBox.Size = new System.Drawing.Size(166, 17); + this.ControlTimeOfDayCheckBox.TabIndex = 38; + this.ControlTimeOfDayCheckBox.Text = "Control time of day (right-drag)"; + this.ControlTimeOfDayCheckBox.UseVisualStyleBackColor = true; + this.ControlTimeOfDayCheckBox.CheckedChanged += new System.EventHandler(this.ControlTimeOfDayCheckBox_CheckedChanged); + // + // TimeOfDayLabel + // + this.TimeOfDayLabel.AutoSize = true; + this.TimeOfDayLabel.Location = new System.Drawing.Point(75, 208); + this.TimeOfDayLabel.Name = "TimeOfDayLabel"; + this.TimeOfDayLabel.Size = new System.Drawing.Size(34, 13); + this.TimeOfDayLabel.TabIndex = 54; + this.TimeOfDayLabel.Text = "12:00"; + // + // label19 + // + this.label19.AutoSize = true; + this.label19.Location = new System.Drawing.Point(4, 208); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(65, 13); + this.label19.TabIndex = 53; + this.label19.Text = "Time of day:"; + // + // TimeOfDayTrackBar + // + this.TimeOfDayTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TimeOfDayTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.TimeOfDayTrackBar.LargeChange = 60; + this.TimeOfDayTrackBar.Location = new System.Drawing.Point(6, 224); + this.TimeOfDayTrackBar.Maximum = 1440; + this.TimeOfDayTrackBar.Name = "TimeOfDayTrackBar"; + this.TimeOfDayTrackBar.Size = new System.Drawing.Size(188, 45); + this.TimeOfDayTrackBar.TabIndex = 39; + this.TimeOfDayTrackBar.TickFrequency = 60; + this.TimeOfDayTrackBar.Value = 720; + this.TimeOfDayTrackBar.Scroll += new System.EventHandler(this.TimeOfDayTrackBar_Scroll); + // + // WeatherComboBox + // + this.WeatherComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.WeatherComboBox.FormattingEnabled = true; + this.WeatherComboBox.Items.AddRange(new object[] { + ""}); + this.WeatherComboBox.Location = new System.Drawing.Point(61, 328); + this.WeatherComboBox.Name = "WeatherComboBox"; + this.WeatherComboBox.Size = new System.Drawing.Size(133, 21); + this.WeatherComboBox.TabIndex = 42; + this.WeatherComboBox.SelectedIndexChanged += new System.EventHandler(this.WeatherComboBox_SelectedIndexChanged); + this.WeatherComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.WeatherComboBox_KeyPress); + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(4, 331); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(51, 13); + this.label17.TabIndex = 39; + this.label17.Text = "Weather:"; + // + // ControlLightDirectionCheckBox + // + this.ControlLightDirectionCheckBox.AutoSize = true; + this.ControlLightDirectionCheckBox.Location = new System.Drawing.Point(10, 157); + this.ControlLightDirectionCheckBox.Name = "ControlLightDirectionCheckBox"; + this.ControlLightDirectionCheckBox.Size = new System.Drawing.Size(177, 17); + this.ControlLightDirectionCheckBox.TabIndex = 37; + this.ControlLightDirectionCheckBox.Text = "Control light direction (right-drag)"; + this.ControlLightDirectionCheckBox.UseVisualStyleBackColor = true; + this.ControlLightDirectionCheckBox.CheckedChanged += new System.EventHandler(this.ControlLightDirectionCheckBox_CheckedChanged); + // + // SkydomeCheckBox + // + this.SkydomeCheckBox.AutoSize = true; + this.SkydomeCheckBox.Checked = true; + this.SkydomeCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.SkydomeCheckBox.Location = new System.Drawing.Point(10, 55); + this.SkydomeCheckBox.Name = "SkydomeCheckBox"; + this.SkydomeCheckBox.Size = new System.Drawing.Size(70, 17); + this.SkydomeCheckBox.TabIndex = 33; + this.SkydomeCheckBox.Text = "Skydome"; + this.SkydomeCheckBox.UseVisualStyleBackColor = true; + this.SkydomeCheckBox.CheckedChanged += new System.EventHandler(this.SkydomeCheckbox_CheckedChanged); + // + // ShadowsCheckBox + // + this.ShadowsCheckBox.AutoSize = true; + this.ShadowsCheckBox.Location = new System.Drawing.Point(10, 32); + this.ShadowsCheckBox.Name = "ShadowsCheckBox"; + this.ShadowsCheckBox.Size = new System.Drawing.Size(70, 17); + this.ShadowsCheckBox.TabIndex = 32; + this.ShadowsCheckBox.Text = "Shadows"; + this.ShadowsCheckBox.UseVisualStyleBackColor = true; + this.ShadowsCheckBox.CheckedChanged += new System.EventHandler(this.ShadowsCheckBox_CheckedChanged); + // + // StatusBarCheckBox + // + this.StatusBarCheckBox.AutoSize = true; + this.StatusBarCheckBox.Checked = true; + this.StatusBarCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.StatusBarCheckBox.Location = new System.Drawing.Point(119, 517); + this.StatusBarCheckBox.Name = "StatusBarCheckBox"; + this.StatusBarCheckBox.Size = new System.Drawing.Size(74, 17); + this.StatusBarCheckBox.TabIndex = 145; + this.StatusBarCheckBox.Text = "Status bar"; + this.StatusBarCheckBox.UseVisualStyleBackColor = true; + this.StatusBarCheckBox.CheckedChanged += new System.EventHandler(this.StatusBarCheckBox_CheckedChanged); + // + // QuitButton + // + this.QuitButton.Location = new System.Drawing.Point(105, 569); + this.QuitButton.Name = "QuitButton"; + this.QuitButton.Size = new System.Drawing.Size(93, 23); + this.QuitButton.TabIndex = 149; + this.QuitButton.Text = "Quit"; + this.QuitButton.UseVisualStyleBackColor = true; + this.QuitButton.Click += new System.EventHandler(this.QuitButton_Click); + // + // ReloadSettingsButton + // + this.ReloadSettingsButton.Enabled = false; + this.ReloadSettingsButton.Location = new System.Drawing.Point(6, 540); + this.ReloadSettingsButton.Name = "ReloadSettingsButton"; + this.ReloadSettingsButton.Size = new System.Drawing.Size(93, 23); + this.ReloadSettingsButton.TabIndex = 146; + this.ReloadSettingsButton.Text = "Reload settings"; + this.ReloadSettingsButton.UseVisualStyleBackColor = true; + this.ReloadSettingsButton.Visible = false; + this.ReloadSettingsButton.Click += new System.EventHandler(this.ReloadSettingsButton_Click); + // + // SaveSettingsButton + // + this.SaveSettingsButton.Location = new System.Drawing.Point(105, 540); + this.SaveSettingsButton.Name = "SaveSettingsButton"; + this.SaveSettingsButton.Size = new System.Drawing.Size(93, 23); + this.SaveSettingsButton.TabIndex = 147; + this.SaveSettingsButton.Text = "Save settings"; + this.SaveSettingsButton.UseVisualStyleBackColor = true; + this.SaveSettingsButton.Click += new System.EventHandler(this.SaveSettingsButton_Click); + // + // ReloadShadersButton + // + this.ReloadShadersButton.Location = new System.Drawing.Point(6, 569); + this.ReloadShadersButton.Name = "ReloadShadersButton"; + this.ReloadShadersButton.Size = new System.Drawing.Size(93, 23); + this.ReloadShadersButton.TabIndex = 148; + this.ReloadShadersButton.Text = "Reload shaders"; + this.ReloadShadersButton.UseVisualStyleBackColor = true; + this.ReloadShadersButton.Click += new System.EventHandler(this.ReloadShadersButton_Click); + // + // ErrorConsoleCheckBox + // + this.ErrorConsoleCheckBox.AutoSize = true; + this.ErrorConsoleCheckBox.Location = new System.Drawing.Point(14, 517); + this.ErrorConsoleCheckBox.Name = "ErrorConsoleCheckBox"; + this.ErrorConsoleCheckBox.Size = new System.Drawing.Size(88, 17); + this.ErrorConsoleCheckBox.TabIndex = 144; + this.ErrorConsoleCheckBox.Text = "Error console"; + this.ErrorConsoleCheckBox.UseVisualStyleBackColor = true; + this.ErrorConsoleCheckBox.CheckedChanged += new System.EventHandler(this.ErrorConsoleCheckBox_CheckedChanged); + // + // ToolsPanelHideButton + // + this.ToolsPanelHideButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ToolsPanelHideButton.Location = new System.Drawing.Point(185, 3); + this.ToolsPanelHideButton.Name = "ToolsPanelHideButton"; + this.ToolsPanelHideButton.Size = new System.Drawing.Size(30, 23); + this.ToolsPanelHideButton.TabIndex = 4; + this.ToolsPanelHideButton.Text = ">>"; + this.ToolsPanelHideButton.UseVisualStyleBackColor = true; + this.ToolsPanelHideButton.Click += new System.EventHandler(this.ToolsPanelHideButton_Click); + // + // ToolsPanelShowButton + // + this.ToolsPanelShowButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ToolsPanelShowButton.Location = new System.Drawing.Point(939, 15); + this.ToolsPanelShowButton.Name = "ToolsPanelShowButton"; + this.ToolsPanelShowButton.Size = new System.Drawing.Size(30, 23); + this.ToolsPanelShowButton.TabIndex = 0; + this.ToolsPanelShowButton.Text = "<<"; + this.ToolsPanelShowButton.UseVisualStyleBackColor = true; + this.ToolsPanelShowButton.Click += new System.EventHandler(this.ToolsPanelShowButton_Click); + // + // ConsolePanel + // + this.ConsolePanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ConsolePanel.BackColor = System.Drawing.SystemColors.Control; + this.ConsolePanel.Controls.Add(this.ConsoleTextBox); + this.ConsolePanel.Location = new System.Drawing.Point(12, 576); + this.ConsolePanel.Name = "ConsolePanel"; + this.ConsolePanel.Size = new System.Drawing.Size(736, 101); + this.ConsolePanel.TabIndex = 3; + this.ConsolePanel.Visible = false; + // + // ConsoleTextBox + // + this.ConsoleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ConsoleTextBox.Location = new System.Drawing.Point(3, 3); + this.ConsoleTextBox.Multiline = true; + this.ConsoleTextBox.Name = "ConsoleTextBox"; + this.ConsoleTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.ConsoleTextBox.Size = new System.Drawing.Size(730, 95); + this.ConsoleTextBox.TabIndex = 0; + // + // StatsUpdateTimer + // + this.StatsUpdateTimer.Enabled = true; + this.StatsUpdateTimer.Interval = 500; + this.StatsUpdateTimer.Tick += new System.EventHandler(this.StatsUpdateTimer_Tick); + // + // SelectedMarkerPanel + // + this.SelectedMarkerPanel.BackColor = System.Drawing.Color.White; + this.SelectedMarkerPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.SelectedMarkerPanel.Controls.Add(this.SelectedMarkerPositionTextBox); + this.SelectedMarkerPanel.Controls.Add(this.SelectedMarkerNameTextBox); + this.SelectedMarkerPanel.Location = new System.Drawing.Point(12, 64); + this.SelectedMarkerPanel.Name = "SelectedMarkerPanel"; + this.SelectedMarkerPanel.Size = new System.Drawing.Size(180, 42); + this.SelectedMarkerPanel.TabIndex = 5; + this.SelectedMarkerPanel.Visible = false; + // + // SelectedMarkerPositionTextBox + // + this.SelectedMarkerPositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectedMarkerPositionTextBox.BackColor = System.Drawing.Color.White; + this.SelectedMarkerPositionTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.SelectedMarkerPositionTextBox.Location = new System.Drawing.Point(3, 22); + this.SelectedMarkerPositionTextBox.Name = "SelectedMarkerPositionTextBox"; + this.SelectedMarkerPositionTextBox.ReadOnly = true; + this.SelectedMarkerPositionTextBox.Size = new System.Drawing.Size(172, 13); + this.SelectedMarkerPositionTextBox.TabIndex = 1; + // + // SelectedMarkerNameTextBox + // + this.SelectedMarkerNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectedMarkerNameTextBox.BackColor = System.Drawing.Color.White; + this.SelectedMarkerNameTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.SelectedMarkerNameTextBox.Location = new System.Drawing.Point(3, 3); + this.SelectedMarkerNameTextBox.Name = "SelectedMarkerNameTextBox"; + this.SelectedMarkerNameTextBox.ReadOnly = true; + this.SelectedMarkerNameTextBox.Size = new System.Drawing.Size(172, 13); + this.SelectedMarkerNameTextBox.TabIndex = 0; + // + // ToolsMenu + // + this.ToolsMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolsMenuRPFBrowser, + this.ToolsMenuRPFExplorer, + this.ToolsMenuSelectionInfo, + this.ToolsMenuProjectWindow, + this.ToolsMenuWorldSearch, + this.ToolsMenuBinarySearch, + this.ToolsMenuJenkGen, + this.ToolsMenuJenkInd, + this.ToolsMenuExtractScripts, + this.ToolsMenuExtractTextures, + this.ToolsMenuExtractRawFiles, + this.ToolsMenuExtractShaders, + this.ToolsMenuOptions}); + this.ToolsMenu.Name = "ToolsMenu"; + this.ToolsMenu.Size = new System.Drawing.Size(166, 290); + // + // ToolsMenuRPFBrowser + // + this.ToolsMenuRPFBrowser.Name = "ToolsMenuRPFBrowser"; + this.ToolsMenuRPFBrowser.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuRPFBrowser.Text = "RPF Browser..."; + this.ToolsMenuRPFBrowser.Click += new System.EventHandler(this.ToolsMenuRPFBrowser_Click); + // + // ToolsMenuRPFExplorer + // + this.ToolsMenuRPFExplorer.Name = "ToolsMenuRPFExplorer"; + this.ToolsMenuRPFExplorer.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuRPFExplorer.Text = "RPF Explorer..."; + this.ToolsMenuRPFExplorer.Click += new System.EventHandler(this.ToolsMenuRPFExplorer_Click); + // + // ToolsMenuSelectionInfo + // + this.ToolsMenuSelectionInfo.Name = "ToolsMenuSelectionInfo"; + this.ToolsMenuSelectionInfo.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuSelectionInfo.Text = "Selection info..."; + this.ToolsMenuSelectionInfo.Click += new System.EventHandler(this.ToolsMenuSelectionInfo_Click); + // + // ToolsMenuProjectWindow + // + this.ToolsMenuProjectWindow.Enabled = false; + this.ToolsMenuProjectWindow.Name = "ToolsMenuProjectWindow"; + this.ToolsMenuProjectWindow.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuProjectWindow.Text = "Project window..."; + this.ToolsMenuProjectWindow.Click += new System.EventHandler(this.ToolsMenuProjectWindow_Click); + // + // ToolsMenuWorldSearch + // + this.ToolsMenuWorldSearch.Name = "ToolsMenuWorldSearch"; + this.ToolsMenuWorldSearch.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuWorldSearch.Text = "World search..."; + this.ToolsMenuWorldSearch.Click += new System.EventHandler(this.ToolsMenuWorldSearch_Click); + // + // ToolsMenuBinarySearch + // + this.ToolsMenuBinarySearch.Name = "ToolsMenuBinarySearch"; + this.ToolsMenuBinarySearch.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuBinarySearch.Text = "Binary search..."; + this.ToolsMenuBinarySearch.Click += new System.EventHandler(this.ToolsMenuBinarySearch_Click); + // + // ToolsMenuJenkGen + // + this.ToolsMenuJenkGen.Name = "ToolsMenuJenkGen"; + this.ToolsMenuJenkGen.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuJenkGen.Text = "JenkGen..."; + this.ToolsMenuJenkGen.Click += new System.EventHandler(this.ToolsMenuJenkGen_Click); + // + // ToolsMenuJenkInd + // + this.ToolsMenuJenkInd.Enabled = false; + this.ToolsMenuJenkInd.Name = "ToolsMenuJenkInd"; + this.ToolsMenuJenkInd.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuJenkInd.Text = "JenkInd..."; + this.ToolsMenuJenkInd.Click += new System.EventHandler(this.ToolsMenuJenkInd_Click); + // + // ToolsMenuExtractScripts + // + this.ToolsMenuExtractScripts.Name = "ToolsMenuExtractScripts"; + this.ToolsMenuExtractScripts.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuExtractScripts.Text = "Extract scripts..."; + this.ToolsMenuExtractScripts.Click += new System.EventHandler(this.ToolsMenuExtractScripts_Click); + // + // ToolsMenuExtractTextures + // + this.ToolsMenuExtractTextures.Name = "ToolsMenuExtractTextures"; + this.ToolsMenuExtractTextures.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuExtractTextures.Text = "Extract textures..."; + this.ToolsMenuExtractTextures.Click += new System.EventHandler(this.ToolsMenuExtractTextures_Click); + // + // ToolsMenuExtractRawFiles + // + this.ToolsMenuExtractRawFiles.Name = "ToolsMenuExtractRawFiles"; + this.ToolsMenuExtractRawFiles.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuExtractRawFiles.Text = "Extract raw files..."; + this.ToolsMenuExtractRawFiles.Click += new System.EventHandler(this.ToolsMenuExtractRawFiles_Click); + // + // ToolsMenuExtractShaders + // + this.ToolsMenuExtractShaders.Name = "ToolsMenuExtractShaders"; + this.ToolsMenuExtractShaders.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuExtractShaders.Text = "Extract shaders..."; + this.ToolsMenuExtractShaders.Click += new System.EventHandler(this.ToolsMenuExtractShaders_Click); + // + // ToolsMenuOptions + // + this.ToolsMenuOptions.Name = "ToolsMenuOptions"; + this.ToolsMenuOptions.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuOptions.Text = "Options..."; + this.ToolsMenuOptions.Click += new System.EventHandler(this.ToolsMenuOptions_Click); + // + // Toolbar + // + this.Toolbar.Dock = System.Windows.Forms.DockStyle.None; + this.Toolbar.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.Toolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolbarNewButton, + this.ToolbarOpenButton, + this.ToolbarSaveButton, + this.ToolbarSaveAllButton, + this.toolStripSeparator5, + this.ToolbarSelectButton, + this.toolStripSeparator1, + this.ToolbarMoveButton, + this.ToolbarRotateButton, + this.ToolbarScaleButton, + this.ToolbarTransformSpaceButton, + this.toolStripSeparator2, + this.ToolbarUndoButton, + this.ToolbarRedoButton, + this.toolStripSeparator3, + this.ToolbarInfoWindowButton, + this.ToolbarProjectWindowButton, + this.toolStripSeparator4, + this.ToolbarAddItemButton, + this.ToolbarDeleteItemButton, + this.toolStripSeparator6, + this.ToolbarCopyButton, + this.ToolbarPasteButton, + this.toolStripSeparator7, + this.ToolbarCameraModeButton}); + this.Toolbar.Location = new System.Drawing.Point(1, 0); + this.Toolbar.Name = "Toolbar"; + this.Toolbar.Size = new System.Drawing.Size(553, 25); + this.Toolbar.TabIndex = 6; + this.Toolbar.Text = "toolStrip1"; + // + // ToolbarNewButton + // + this.ToolbarNewButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarNewButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolbarNewProjectButton, + this.ToolbarNewYmapButton, + this.ToolbarNewYndButton, + this.ToolbarNewTrainsButton, + this.ToolbarNewScenarioButton}); + this.ToolbarNewButton.Enabled = false; + this.ToolbarNewButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarNewButton.Image"))); + this.ToolbarNewButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarNewButton.Name = "ToolbarNewButton"; + this.ToolbarNewButton.Size = new System.Drawing.Size(32, 22); + this.ToolbarNewButton.Text = "New..."; + this.ToolbarNewButton.ToolTipText = "New... (Ctrl+N)"; + this.ToolbarNewButton.ButtonClick += new System.EventHandler(this.ToolbarNewButton_ButtonClick); + // + // ToolbarNewProjectButton + // + this.ToolbarNewProjectButton.Name = "ToolbarNewProjectButton"; + this.ToolbarNewProjectButton.Size = new System.Drawing.Size(164, 22); + this.ToolbarNewProjectButton.Text = "New project"; + this.ToolbarNewProjectButton.Click += new System.EventHandler(this.ToolbarNewProjectButton_Click); + // + // ToolbarNewYmapButton + // + this.ToolbarNewYmapButton.Name = "ToolbarNewYmapButton"; + this.ToolbarNewYmapButton.Size = new System.Drawing.Size(164, 22); + this.ToolbarNewYmapButton.Text = "New ymap file"; + this.ToolbarNewYmapButton.Click += new System.EventHandler(this.ToolbarNewYmapButton_Click); + // + // ToolbarNewYndButton + // + this.ToolbarNewYndButton.Name = "ToolbarNewYndButton"; + this.ToolbarNewYndButton.Size = new System.Drawing.Size(164, 22); + this.ToolbarNewYndButton.Text = "New ynd file"; + this.ToolbarNewYndButton.Click += new System.EventHandler(this.ToolbarNewYndButton_Click); + // + // ToolbarNewTrainsButton + // + this.ToolbarNewTrainsButton.Name = "ToolbarNewTrainsButton"; + this.ToolbarNewTrainsButton.Size = new System.Drawing.Size(164, 22); + this.ToolbarNewTrainsButton.Text = "New trains file"; + this.ToolbarNewTrainsButton.Click += new System.EventHandler(this.ToolbarNewTrainsButton_Click); + // + // ToolbarOpenButton + // + this.ToolbarOpenButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarOpenButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolbarOpenProjectButton, + this.ToolbarOpenYmapButton, + this.ToolbarOpenYndButton, + this.ToolbarOpenTrainsButton, + this.ToolbarOpenScenarioButton}); + this.ToolbarOpenButton.Enabled = false; + this.ToolbarOpenButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarOpenButton.Image"))); + this.ToolbarOpenButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarOpenButton.Name = "ToolbarOpenButton"; + this.ToolbarOpenButton.Size = new System.Drawing.Size(32, 22); + this.ToolbarOpenButton.Text = "Open..."; + this.ToolbarOpenButton.ToolTipText = "Open... (Ctrl+O)"; + this.ToolbarOpenButton.ButtonClick += new System.EventHandler(this.ToolbarOpenButton_ButtonClick); + // + // ToolbarOpenProjectButton + // + this.ToolbarOpenProjectButton.Name = "ToolbarOpenProjectButton"; + this.ToolbarOpenProjectButton.Size = new System.Drawing.Size(178, 22); + this.ToolbarOpenProjectButton.Text = "Open project..."; + this.ToolbarOpenProjectButton.Click += new System.EventHandler(this.ToolbarOpenProjectButton_Click); + // + // ToolbarOpenYmapButton + // + this.ToolbarOpenYmapButton.Name = "ToolbarOpenYmapButton"; + this.ToolbarOpenYmapButton.Size = new System.Drawing.Size(178, 22); + this.ToolbarOpenYmapButton.Text = "Open ymap file..."; + this.ToolbarOpenYmapButton.Click += new System.EventHandler(this.ToolbarOpenYmapButton_Click); + // + // ToolbarOpenYndButton + // + this.ToolbarOpenYndButton.Name = "ToolbarOpenYndButton"; + this.ToolbarOpenYndButton.Size = new System.Drawing.Size(178, 22); + this.ToolbarOpenYndButton.Text = "Open ynd file..."; + this.ToolbarOpenYndButton.Click += new System.EventHandler(this.ToolbarOpenYndButton_Click); + // + // ToolbarOpenTrainsButton + // + this.ToolbarOpenTrainsButton.Name = "ToolbarOpenTrainsButton"; + this.ToolbarOpenTrainsButton.Size = new System.Drawing.Size(178, 22); + this.ToolbarOpenTrainsButton.Text = "Open trains file..."; + this.ToolbarOpenTrainsButton.Click += new System.EventHandler(this.ToolbarOpenTrainsButton_Click); + // + // ToolbarSaveButton + // + this.ToolbarSaveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarSaveButton.Enabled = false; + this.ToolbarSaveButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarSaveButton.Image"))); + this.ToolbarSaveButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarSaveButton.Name = "ToolbarSaveButton"; + this.ToolbarSaveButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarSaveButton.Text = "Save"; + this.ToolbarSaveButton.ToolTipText = "Save (Ctrl+S)"; + this.ToolbarSaveButton.Click += new System.EventHandler(this.ToolbarSaveButton_Click); + // + // ToolbarSaveAllButton + // + this.ToolbarSaveAllButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarSaveAllButton.Enabled = false; + this.ToolbarSaveAllButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarSaveAllButton.Image"))); + this.ToolbarSaveAllButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarSaveAllButton.Name = "ToolbarSaveAllButton"; + this.ToolbarSaveAllButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarSaveAllButton.Text = "Save All"; + this.ToolbarSaveAllButton.ToolTipText = "Save All (Ctrl+Shift+S)"; + this.ToolbarSaveAllButton.Click += new System.EventHandler(this.ToolbarSaveAllButton_Click); + // + // toolStripSeparator5 + // + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new System.Drawing.Size(6, 25); + // + // ToolbarSelectButton + // + this.ToolbarSelectButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarSelectButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolbarSelectEntityButton, + this.ToolbarSelectEntityExtensionButton, + this.ToolbarSelectArchetypeExtensionButton, + this.ToolbarSelectTimeCycleModifierButton, + this.ToolbarSelectCarGeneratorButton, + this.ToolbarSelectGrassButton, + this.ToolbarSelectWaterQuadButton, + this.ToolbarSelectCollisionButton, + this.ToolbarSelectNavMeshButton, + this.ToolbarSelectPathButton, + this.ToolbarSelectTrainTrackButton, + this.ToolbarSelectDistantLodLightsButton, + this.ToolbarSelectMloInstanceButton, + this.ToolbarSelectScenarioButton}); + this.ToolbarSelectButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarSelectButton.Image"))); + this.ToolbarSelectButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarSelectButton.Name = "ToolbarSelectButton"; + this.ToolbarSelectButton.Size = new System.Drawing.Size(32, 22); + this.ToolbarSelectButton.Text = "toolStripSplitButton1"; + this.ToolbarSelectButton.ToolTipText = "Select objects / Exit edit mode (C, Q)"; + this.ToolbarSelectButton.ButtonClick += new System.EventHandler(this.ToolbarSelectButton_ButtonClick); + // + // ToolbarSelectEntityButton + // + this.ToolbarSelectEntityButton.Checked = true; + this.ToolbarSelectEntityButton.CheckState = System.Windows.Forms.CheckState.Checked; + this.ToolbarSelectEntityButton.Name = "ToolbarSelectEntityButton"; + this.ToolbarSelectEntityButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectEntityButton.Text = "Entity"; + this.ToolbarSelectEntityButton.Click += new System.EventHandler(this.ToolbarSelectEntityButton_Click); + // + // ToolbarSelectEntityExtensionButton + // + this.ToolbarSelectEntityExtensionButton.Name = "ToolbarSelectEntityExtensionButton"; + this.ToolbarSelectEntityExtensionButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectEntityExtensionButton.Text = "Entity Extension"; + this.ToolbarSelectEntityExtensionButton.Click += new System.EventHandler(this.ToolbarSelectEntityExtensionButton_Click); + // + // ToolbarSelectArchetypeExtensionButton + // + this.ToolbarSelectArchetypeExtensionButton.Name = "ToolbarSelectArchetypeExtensionButton"; + this.ToolbarSelectArchetypeExtensionButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectArchetypeExtensionButton.Text = "Archetype Extension"; + this.ToolbarSelectArchetypeExtensionButton.Click += new System.EventHandler(this.ToolbarSelectArchetypeExtensionButton_Click); + // + // ToolbarSelectTimeCycleModifierButton + // + this.ToolbarSelectTimeCycleModifierButton.Name = "ToolbarSelectTimeCycleModifierButton"; + this.ToolbarSelectTimeCycleModifierButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectTimeCycleModifierButton.Text = "Time Cycle Modifier"; + this.ToolbarSelectTimeCycleModifierButton.Click += new System.EventHandler(this.ToolbarSelectTimeCycleModifierButton_Click); + // + // ToolbarSelectCarGeneratorButton + // + this.ToolbarSelectCarGeneratorButton.Name = "ToolbarSelectCarGeneratorButton"; + this.ToolbarSelectCarGeneratorButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectCarGeneratorButton.Text = "Car Generator"; + this.ToolbarSelectCarGeneratorButton.Click += new System.EventHandler(this.ToolbarSelectCarGeneratorButton_Click); + // + // ToolbarSelectGrassButton + // + this.ToolbarSelectGrassButton.Name = "ToolbarSelectGrassButton"; + this.ToolbarSelectGrassButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectGrassButton.Text = "Grass"; + this.ToolbarSelectGrassButton.Click += new System.EventHandler(this.ToolbarSelectGrassButton_Click); + // + // ToolbarSelectWaterQuadButton + // + this.ToolbarSelectWaterQuadButton.Name = "ToolbarSelectWaterQuadButton"; + this.ToolbarSelectWaterQuadButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectWaterQuadButton.Text = "Water Quad"; + this.ToolbarSelectWaterQuadButton.Click += new System.EventHandler(this.ToolbarSelectWaterQuadButton_Click); + // + // ToolbarSelectCollisionButton + // + this.ToolbarSelectCollisionButton.Name = "ToolbarSelectCollisionButton"; + this.ToolbarSelectCollisionButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectCollisionButton.Text = "Collision"; + this.ToolbarSelectCollisionButton.Click += new System.EventHandler(this.ToolbarSelectCollisionButton_Click); + // + // ToolbarSelectNavMeshButton + // + this.ToolbarSelectNavMeshButton.Name = "ToolbarSelectNavMeshButton"; + this.ToolbarSelectNavMeshButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectNavMeshButton.Text = "Nav Mesh"; + this.ToolbarSelectNavMeshButton.Click += new System.EventHandler(this.ToolbarSelectNavMeshButton_Click); + // + // ToolbarSelectPathButton + // + this.ToolbarSelectPathButton.Name = "ToolbarSelectPathButton"; + this.ToolbarSelectPathButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectPathButton.Text = "Path"; + this.ToolbarSelectPathButton.Click += new System.EventHandler(this.ToolbarSelectPathButton_Click); + // + // ToolbarSelectTrainTrackButton + // + this.ToolbarSelectTrainTrackButton.Name = "ToolbarSelectTrainTrackButton"; + this.ToolbarSelectTrainTrackButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectTrainTrackButton.Text = "Train Track"; + this.ToolbarSelectTrainTrackButton.Click += new System.EventHandler(this.ToolbarSelectTrainTrackButton_Click); + // + // ToolbarSelectDistantLodLightsButton + // + this.ToolbarSelectDistantLodLightsButton.Name = "ToolbarSelectDistantLodLightsButton"; + this.ToolbarSelectDistantLodLightsButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectDistantLodLightsButton.Text = "Distant Lod Lights"; + this.ToolbarSelectDistantLodLightsButton.Click += new System.EventHandler(this.ToolbarSelectDistantLodLightsButton_Click); + // + // ToolbarSelectMloInstanceButton + // + this.ToolbarSelectMloInstanceButton.Name = "ToolbarSelectMloInstanceButton"; + this.ToolbarSelectMloInstanceButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectMloInstanceButton.Text = "Mlo Instance"; + this.ToolbarSelectMloInstanceButton.Click += new System.EventHandler(this.ToolbarSelectMloInstanceButton_Click); + // + // ToolbarSelectScenarioButton + // + this.ToolbarSelectScenarioButton.Name = "ToolbarSelectScenarioButton"; + this.ToolbarSelectScenarioButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectScenarioButton.Text = "Scenario"; + this.ToolbarSelectScenarioButton.Click += new System.EventHandler(this.ToolbarSelectScenarioButton_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); + // + // ToolbarMoveButton + // + this.ToolbarMoveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarMoveButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarMoveButton.Image"))); + this.ToolbarMoveButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarMoveButton.Name = "ToolbarMoveButton"; + this.ToolbarMoveButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarMoveButton.Text = "Move"; + this.ToolbarMoveButton.ToolTipText = "Move (W)"; + this.ToolbarMoveButton.Click += new System.EventHandler(this.ToolbarMoveButton_Click); + // + // ToolbarRotateButton + // + this.ToolbarRotateButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarRotateButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarRotateButton.Image"))); + this.ToolbarRotateButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarRotateButton.Name = "ToolbarRotateButton"; + this.ToolbarRotateButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarRotateButton.Text = "Rotate"; + this.ToolbarRotateButton.ToolTipText = "Rotate (E)"; + this.ToolbarRotateButton.Click += new System.EventHandler(this.ToolbarRotateButton_Click); + // + // ToolbarScaleButton + // + this.ToolbarScaleButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarScaleButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarScaleButton.Image"))); + this.ToolbarScaleButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarScaleButton.Name = "ToolbarScaleButton"; + this.ToolbarScaleButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarScaleButton.Text = "Scale"; + this.ToolbarScaleButton.ToolTipText = "Scale (R)"; + this.ToolbarScaleButton.Click += new System.EventHandler(this.ToolbarScaleButton_Click); + // + // ToolbarTransformSpaceButton + // + this.ToolbarTransformSpaceButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarTransformSpaceButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolbarObjectSpaceButton, + this.ToolbarWorldSpaceButton}); + this.ToolbarTransformSpaceButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarTransformSpaceButton.Image"))); + this.ToolbarTransformSpaceButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarTransformSpaceButton.Name = "ToolbarTransformSpaceButton"; + this.ToolbarTransformSpaceButton.Size = new System.Drawing.Size(32, 22); + this.ToolbarTransformSpaceButton.Text = "Toggle transform space"; + this.ToolbarTransformSpaceButton.ButtonClick += new System.EventHandler(this.ToolbarTransformSpaceButton_ButtonClick); + // + // ToolbarObjectSpaceButton + // + this.ToolbarObjectSpaceButton.Checked = true; + this.ToolbarObjectSpaceButton.CheckState = System.Windows.Forms.CheckState.Checked; + this.ToolbarObjectSpaceButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarObjectSpaceButton.Image"))); + this.ToolbarObjectSpaceButton.Name = "ToolbarObjectSpaceButton"; + this.ToolbarObjectSpaceButton.Size = new System.Drawing.Size(142, 22); + this.ToolbarObjectSpaceButton.Text = "Object space"; + this.ToolbarObjectSpaceButton.Click += new System.EventHandler(this.ToolbarObjectSpaceButton_Click); + // + // ToolbarWorldSpaceButton + // + this.ToolbarWorldSpaceButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarWorldSpaceButton.Image"))); + this.ToolbarWorldSpaceButton.Name = "ToolbarWorldSpaceButton"; + this.ToolbarWorldSpaceButton.Size = new System.Drawing.Size(142, 22); + this.ToolbarWorldSpaceButton.Text = "World space"; + this.ToolbarWorldSpaceButton.Click += new System.EventHandler(this.ToolbarWorldSpaceButton_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25); + // + // ToolbarUndoButton + // + this.ToolbarUndoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarUndoButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolbarUndoListButton}); + this.ToolbarUndoButton.Enabled = false; + this.ToolbarUndoButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarUndoButton.Image"))); + this.ToolbarUndoButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarUndoButton.Name = "ToolbarUndoButton"; + this.ToolbarUndoButton.Size = new System.Drawing.Size(32, 22); + this.ToolbarUndoButton.Text = "Undo"; + this.ToolbarUndoButton.ButtonClick += new System.EventHandler(this.ToolbarUndoButton_ButtonClick); + // + // ToolbarUndoListButton + // + this.ToolbarUndoListButton.Name = "ToolbarUndoListButton"; + this.ToolbarUndoListButton.Size = new System.Drawing.Size(121, 22); + this.ToolbarUndoListButton.Text = "Undo list"; + this.ToolbarUndoListButton.Click += new System.EventHandler(this.ToolbarUndoListButton_Click); + // + // ToolbarRedoButton + // + this.ToolbarRedoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarRedoButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolbarRedoListButton}); + this.ToolbarRedoButton.Enabled = false; + this.ToolbarRedoButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarRedoButton.Image"))); + this.ToolbarRedoButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarRedoButton.Name = "ToolbarRedoButton"; + this.ToolbarRedoButton.Size = new System.Drawing.Size(32, 22); + this.ToolbarRedoButton.Text = "Redo"; + this.ToolbarRedoButton.ButtonClick += new System.EventHandler(this.ToolbarRedoButton_ButtonClick); + // + // ToolbarRedoListButton + // + this.ToolbarRedoListButton.Name = "ToolbarRedoListButton"; + this.ToolbarRedoListButton.Size = new System.Drawing.Size(119, 22); + this.ToolbarRedoListButton.Text = "Redo list"; + this.ToolbarRedoListButton.Click += new System.EventHandler(this.ToolbarRedoListButton_Click); + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(6, 25); + // + // ToolbarInfoWindowButton + // + this.ToolbarInfoWindowButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarInfoWindowButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarInfoWindowButton.Image"))); + this.ToolbarInfoWindowButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarInfoWindowButton.Name = "ToolbarInfoWindowButton"; + this.ToolbarInfoWindowButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarInfoWindowButton.Text = "Selection info window"; + this.ToolbarInfoWindowButton.Click += new System.EventHandler(this.ToolbarInfoWindowButton_Click); + // + // ToolbarProjectWindowButton + // + this.ToolbarProjectWindowButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarProjectWindowButton.Enabled = false; + this.ToolbarProjectWindowButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarProjectWindowButton.Image"))); + this.ToolbarProjectWindowButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarProjectWindowButton.Name = "ToolbarProjectWindowButton"; + this.ToolbarProjectWindowButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarProjectWindowButton.Text = "Project window"; + this.ToolbarProjectWindowButton.Click += new System.EventHandler(this.ToolbarProjectWindowButton_Click); + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(6, 25); + // + // ToolbarAddItemButton + // + this.ToolbarAddItemButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarAddItemButton.Enabled = false; + this.ToolbarAddItemButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarAddItemButton.Image"))); + this.ToolbarAddItemButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarAddItemButton.Name = "ToolbarAddItemButton"; + this.ToolbarAddItemButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarAddItemButton.Text = "Add entity"; + this.ToolbarAddItemButton.Click += new System.EventHandler(this.ToolbarAddItemButton_Click); + // + // ToolbarDeleteItemButton + // + this.ToolbarDeleteItemButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarDeleteItemButton.Enabled = false; + this.ToolbarDeleteItemButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarDeleteItemButton.Image"))); + this.ToolbarDeleteItemButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarDeleteItemButton.Name = "ToolbarDeleteItemButton"; + this.ToolbarDeleteItemButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarDeleteItemButton.Text = "Delete entity"; + this.ToolbarDeleteItemButton.Click += new System.EventHandler(this.ToolbarDeleteItemButton_Click); + // + // toolStripSeparator6 + // + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new System.Drawing.Size(6, 25); + // + // ToolbarCopyButton + // + this.ToolbarCopyButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarCopyButton.Enabled = false; + this.ToolbarCopyButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarCopyButton.Image"))); + this.ToolbarCopyButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarCopyButton.Name = "ToolbarCopyButton"; + this.ToolbarCopyButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarCopyButton.Text = "Copy"; + this.ToolbarCopyButton.ToolTipText = "Copy (Ctrl+C)"; + this.ToolbarCopyButton.Click += new System.EventHandler(this.ToolbarCopyButton_Click); + // + // ToolbarPasteButton + // + this.ToolbarPasteButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarPasteButton.Enabled = false; + this.ToolbarPasteButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarPasteButton.Image"))); + this.ToolbarPasteButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarPasteButton.Name = "ToolbarPasteButton"; + this.ToolbarPasteButton.Size = new System.Drawing.Size(23, 22); + this.ToolbarPasteButton.Text = "Paste"; + this.ToolbarPasteButton.ToolTipText = "Paste (Ctrl+V)"; + this.ToolbarPasteButton.Click += new System.EventHandler(this.ToolbarPasteButton_Click); + // + // toolStripSeparator7 + // + this.toolStripSeparator7.Name = "toolStripSeparator7"; + this.toolStripSeparator7.Size = new System.Drawing.Size(6, 25); + // + // ToolbarCameraModeButton + // + this.ToolbarCameraModeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ToolbarCameraModeButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolbarCameraPerspectiveButton, + this.ToolbarCameraMapViewButton, + this.ToolbarCameraOrthographicButton}); + this.ToolbarCameraModeButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarCameraModeButton.Image"))); + this.ToolbarCameraModeButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ToolbarCameraModeButton.Name = "ToolbarCameraModeButton"; + this.ToolbarCameraModeButton.Size = new System.Drawing.Size(32, 22); + this.ToolbarCameraModeButton.Text = "Camera Mode"; + this.ToolbarCameraModeButton.ButtonClick += new System.EventHandler(this.ToolbarCameraModeButton_ButtonClick); + // + // ToolbarCameraPerspectiveButton + // + this.ToolbarCameraPerspectiveButton.Checked = true; + this.ToolbarCameraPerspectiveButton.CheckState = System.Windows.Forms.CheckState.Checked; + this.ToolbarCameraPerspectiveButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarCameraPerspectiveButton.Image"))); + this.ToolbarCameraPerspectiveButton.Name = "ToolbarCameraPerspectiveButton"; + this.ToolbarCameraPerspectiveButton.Size = new System.Drawing.Size(145, 22); + this.ToolbarCameraPerspectiveButton.Text = "Perspective"; + this.ToolbarCameraPerspectiveButton.Click += new System.EventHandler(this.ToolbarCameraPerspectiveButton_Click); + // + // ToolbarCameraMapViewButton + // + this.ToolbarCameraMapViewButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarCameraMapViewButton.Image"))); + this.ToolbarCameraMapViewButton.Name = "ToolbarCameraMapViewButton"; + this.ToolbarCameraMapViewButton.Size = new System.Drawing.Size(145, 22); + this.ToolbarCameraMapViewButton.Text = "Map View"; + this.ToolbarCameraMapViewButton.Click += new System.EventHandler(this.ToolbarCameraMapViewButton_Click); + // + // ToolbarCameraOrthographicButton + // + this.ToolbarCameraOrthographicButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarCameraOrthographicButton.Image"))); + this.ToolbarCameraOrthographicButton.Name = "ToolbarCameraOrthographicButton"; + this.ToolbarCameraOrthographicButton.Size = new System.Drawing.Size(145, 22); + this.ToolbarCameraOrthographicButton.Text = "Orthographic"; + this.ToolbarCameraOrthographicButton.Click += new System.EventHandler(this.ToolbarCameraOrthographicButton_Click); + // + // ToolbarPanel + // + this.ToolbarPanel.BackColor = System.Drawing.SystemColors.Control; + this.ToolbarPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.ToolbarPanel.Controls.Add(this.Toolbar); + this.ToolbarPanel.Location = new System.Drawing.Point(12, 12); + this.ToolbarPanel.Name = "ToolbarPanel"; + this.ToolbarPanel.Size = new System.Drawing.Size(525, 26); + this.ToolbarPanel.TabIndex = 7; + this.ToolbarPanel.Visible = false; + // + // ToolbarNewScenarioButton + // + this.ToolbarNewScenarioButton.Name = "ToolbarNewScenarioButton"; + this.ToolbarNewScenarioButton.Size = new System.Drawing.Size(164, 22); + this.ToolbarNewScenarioButton.Text = "New scenario file"; + this.ToolbarNewScenarioButton.Click += new System.EventHandler(this.ToolbarNewScenarioButton_Click); + // + // ToolbarOpenScenarioButton + // + this.ToolbarOpenScenarioButton.Name = "ToolbarOpenScenarioButton"; + this.ToolbarOpenScenarioButton.Size = new System.Drawing.Size(178, 22); + this.ToolbarOpenScenarioButton.Text = "Open scenario file..."; + this.ToolbarOpenScenarioButton.Click += new System.EventHandler(this.ToolbarOpenScenarioButton_Click); + // + // WorldForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.MidnightBlue; + this.ClientSize = new System.Drawing.Size(984, 711); + this.Controls.Add(this.ToolbarPanel); + this.Controls.Add(this.SelectedMarkerPanel); + this.Controls.Add(this.ConsolePanel); + this.Controls.Add(this.ToolsPanel); + this.Controls.Add(this.StatusStrip); + this.Controls.Add(this.ToolsPanelShowButton); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.KeyPreview = true; + this.Name = "WorldForm"; + this.Text = "CodeWalker"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.WorldForm_FormClosing); + this.Load += new System.EventHandler(this.WorldForm_Load); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.WorldForm_KeyDown); + this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.WorldForm_KeyUp); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.WorldForm_MouseDown); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.WorldForm_MouseMove); + this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.WorldForm_MouseUp); + this.StatusStrip.ResumeLayout(false); + this.StatusStrip.PerformLayout(); + this.ToolsPanel.ResumeLayout(false); + this.ToolsTabControl.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage1.PerformLayout(); + this.ViewTabControl.ResumeLayout(false); + this.ViewWorldTabPage.ResumeLayout(false); + this.ViewWorldTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.WorldDetailDistTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.WorldLodDistTrackBar)).EndInit(); + this.ViewYmapsTabPage.ResumeLayout(false); + this.ViewYmapsTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.DetailTrackBar)).EndInit(); + this.ViewModelTabPage.ResumeLayout(false); + this.ViewModelTabPage.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.tabPage2.PerformLayout(); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + this.SelectionTabControl.ResumeLayout(false); + this.SelectionEntityTabPage.ResumeLayout(false); + this.SelectionArchetypeTabPage.ResumeLayout(false); + this.SelectionDrawableTabPage.ResumeLayout(false); + this.tabControl3.ResumeLayout(false); + this.tabPage11.ResumeLayout(false); + this.tabPage12.ResumeLayout(false); + this.tabPage13.ResumeLayout(false); + this.SelectionExtensionTabPage.ResumeLayout(false); + this.tabPage4.ResumeLayout(false); + this.tabPage4.PerformLayout(); + this.OptionsTabControl.ResumeLayout(false); + this.tabPage8.ResumeLayout(false); + this.tabPage8.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.MapViewDetailTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.CollisionMeshRangeTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.FieldOfViewTrackBar)).EndInit(); + this.tabPage14.ResumeLayout(false); + this.tabPage14.PerformLayout(); + this.tabPage9.ResumeLayout(false); + this.tabPage9.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.BoundsRangeTrackBar)).EndInit(); + this.tabPage10.ResumeLayout(false); + this.tabPage10.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.CloudParamTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.TimeSpeedTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.TimeOfDayTrackBar)).EndInit(); + this.ConsolePanel.ResumeLayout(false); + this.ConsolePanel.PerformLayout(); + this.SelectedMarkerPanel.ResumeLayout(false); + this.SelectedMarkerPanel.PerformLayout(); + this.ToolsMenu.ResumeLayout(false); + this.Toolbar.ResumeLayout(false); + this.Toolbar.PerformLayout(); + this.ToolbarPanel.ResumeLayout(false); + this.ToolbarPanel.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.FolderBrowserDialog FolderBrowserDialog; + private System.Windows.Forms.StatusStrip StatusStrip; + private System.Windows.Forms.ToolStripStatusLabel StatusLabel; + private System.Windows.Forms.ComboBox ModelComboBox; + private System.Windows.Forms.Panel ToolsPanel; + private System.Windows.Forms.Label label2; + private TextBoxFix YmapsTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button ToolsPanelHideButton; + private System.Windows.Forms.Button ToolsPanelShowButton; + private System.Windows.Forms.CheckBox WireframeCheckBox; + private System.Windows.Forms.TabControl ToolsTabControl; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.TabPage tabPage4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox ViewModeComboBox; + private System.Windows.Forms.CheckBox TimedEntitiesCheckBox; + private System.Windows.Forms.CheckBox ErrorConsoleCheckBox; + private System.Windows.Forms.Panel ConsolePanel; + private TextBoxFix ConsoleTextBox; + private System.Windows.Forms.Timer StatsUpdateTimer; + private System.Windows.Forms.ToolStripStatusLabel StatsLabel; + private System.Windows.Forms.TrackBar DetailTrackBar; + private System.Windows.Forms.CheckBox DynamicLODCheckBox; + private System.Windows.Forms.Button ReloadShadersButton; + private System.Windows.Forms.ComboBox MarkerStyleComboBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.ComboBox LocatorStyleComboBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button ClearMarkersButton; + private System.Windows.Forms.Button GoToButton; + private System.Windows.Forms.CheckBox ShowLocatorCheckBox; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox LocateTextBox; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Button AddMarkersButton; + private TextBoxFix MultiFindTextBox; + private System.Windows.Forms.CheckBox MarkerDepthClipCheckBox; + private System.Windows.Forms.Button ResetMarkersButton; + private System.Windows.Forms.Panel SelectedMarkerPanel; + private System.Windows.Forms.TextBox SelectedMarkerPositionTextBox; + private System.Windows.Forms.TextBox SelectedMarkerNameTextBox; + private System.Windows.Forms.CheckBox SkydomeCheckBox; + private System.Windows.Forms.CheckBox BoundsDepthClipCheckBox; + private System.Windows.Forms.CheckBox MouseSelectCheckBox; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.ComboBox BoundsStyleComboBox; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TrackBar BoundsRangeTrackBar; + private System.Windows.Forms.Button AddCurrentPositonMarkerButton; + private System.Windows.Forms.CheckBox SelectionBoundsCheckBox; + private ReadOnlyPropertyGrid SelEntityPropertyGrid; + private ReadOnlyPropertyGrid SelArchetypePropertyGrid; + private System.Windows.Forms.TabControl SelectionTabControl; + private System.Windows.Forms.TabPage SelectionEntityTabPage; + private System.Windows.Forms.TabPage SelectionArchetypeTabPage; + private System.Windows.Forms.ToolStripStatusLabel MousedLabel; + private System.Windows.Forms.TabPage SelectionDrawableTabPage; + private ReadOnlyPropertyGrid SelDrawablePropertyGrid; + private System.Windows.Forms.Button ToolsPanelExpandButton; + private System.Windows.Forms.Button AddSelectionMarkerButton; + private System.Windows.Forms.CheckBox FullScreenCheckBox; + private System.Windows.Forms.Button QuitButton; + private System.Windows.Forms.Button ReloadSettingsButton; + private System.Windows.Forms.Button SaveSettingsButton; + private System.Windows.Forms.Button ToolsButton; + private System.Windows.Forms.ContextMenuStrip ToolsMenu; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuRPFBrowser; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuBinarySearch; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuJenkGen; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuExtractScripts; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuExtractTextures; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuExtractRawFiles; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuExtractShaders; + private System.Windows.Forms.Button AboutButton; + private System.Windows.Forms.CheckBox ShadowsCheckBox; + private System.Windows.Forms.CheckBox StatusBarCheckBox; + private System.Windows.Forms.CheckBox WaitForChildrenCheckBox; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.ComboBox RenderModeComboBox; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.ComboBox TextureSamplerComboBox; + private System.Windows.Forms.TabControl OptionsTabControl; + private System.Windows.Forms.TabPage tabPage8; + private System.Windows.Forms.TabPage tabPage9; + private System.Windows.Forms.CheckBox CollisionMeshesCheckBox; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.TrackBar CollisionMeshRangeTrackBar; + private System.Windows.Forms.CheckBox CollisionMeshLayer2CheckBox; + private System.Windows.Forms.CheckBox CollisionMeshLayer1CheckBox; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.CheckBox CollisionMeshLayer0CheckBox; + private System.Windows.Forms.CheckBox ControlLightDirectionCheckBox; + private System.Windows.Forms.TabControl ViewTabControl; + private System.Windows.Forms.TabPage ViewWorldTabPage; + private System.Windows.Forms.TabPage ViewYmapsTabPage; + private System.Windows.Forms.TabPage ViewModelTabPage; + private System.Windows.Forms.CheckBox ShowYmapChildrenCheckBox; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.ComboBox TextureCoordsComboBox; + private System.Windows.Forms.CheckBox AnisotropicFilteringCheckBox; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.ComboBox WorldMaxLodComboBox; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.TrackBar WorldLodDistTrackBar; + private System.Windows.Forms.Label WorldLodDistLabel; + private System.Windows.Forms.Label WorldDetailDistLabel; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.TrackBar WorldDetailDistTrackBar; + private System.Windows.Forms.CheckBox ProxiesCheckBox; + private System.Windows.Forms.CheckBox CollisionMeshLayerDrawableCheckBox; + private System.Windows.Forms.CheckBox InteriorsCheckBox; + private System.Windows.Forms.TabPage tabPage10; + private System.Windows.Forms.ComboBox WeatherComboBox; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.Label TimeOfDayLabel; + private System.Windows.Forms.Label label19; + private System.Windows.Forms.TrackBar TimeOfDayTrackBar; + private System.Windows.Forms.CheckBox ControlTimeOfDayCheckBox; + private System.Windows.Forms.CheckBox GrassCheckBox; + private System.Windows.Forms.CheckBox TimedEntitiesAlwaysOnCheckBox; + private System.Windows.Forms.CheckBox HDRRenderingCheckBox; + private System.Windows.Forms.CheckBox ArtificialAmbientLightCheckBox; + private System.Windows.Forms.CheckBox NaturalAmbientLightCheckBox; + private System.Windows.Forms.CheckBox DistantLODLightsCheckBox; + private System.Windows.Forms.Label TimeSpeedLabel; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.TrackBar TimeSpeedTrackBar; + private System.Windows.Forms.Button TimeStartStopButton; + private System.Windows.Forms.ComboBox CloudsComboBox; + private System.Windows.Forms.Label label21; + private System.Windows.Forms.Label FieldOfViewLabel; + private System.Windows.Forms.Label label22; + private System.Windows.Forms.TrackBar FieldOfViewTrackBar; + private System.Windows.Forms.TrackBar CloudParamTrackBar; + private System.Windows.Forms.ComboBox CloudParamComboBox; + private System.Windows.Forms.Label label23; + private System.Windows.Forms.TabControl tabControl3; + private System.Windows.Forms.TabPage tabPage11; + private System.Windows.Forms.TabPage tabPage12; + private System.Windows.Forms.TabPage tabPage13; + private TreeViewFix SelDrawableModelsTreeView; + private TreeViewFix SelDrawableTexturesTreeView; + private System.Windows.Forms.CheckBox PathsCheckBox; + private System.Windows.Forms.TabPage tabPage14; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuProjectWindow; + private System.Windows.Forms.CheckBox WaterQuadsCheckBox; + private System.Windows.Forms.ComboBox CameraModeComboBox; + private System.Windows.Forms.Label label24; + private System.Windows.Forms.CheckBox SelectionWidgetCheckBox; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuSelectionInfo; + private System.Windows.Forms.Label label27; + private System.Windows.Forms.TextBox CameraPositionTextBox; + private System.Windows.Forms.Label MapViewDetailLabel; + private System.Windows.Forms.Label label28; + private System.Windows.Forms.TrackBar MapViewDetailTrackBar; + private System.Windows.Forms.CheckBox WorldScriptedYmapsCheckBox; + private System.Windows.Forms.ComboBox WeatherRegionComboBox; + private System.Windows.Forms.Label label29; + private System.Windows.Forms.CheckBox WorldYmapWeatherFilterCheckBox; + private System.Windows.Forms.CheckBox WorldYmapTimeFilterCheckBox; + private System.Windows.Forms.Label label30; + private System.Windows.Forms.ComboBox DlcLevelComboBox; + private System.Windows.Forms.CheckBox EnableDlcCheckBox; + private ToolStripFix Toolbar; + private System.Windows.Forms.Panel ToolbarPanel; + private System.Windows.Forms.ToolStripButton ToolbarMoveButton; + private System.Windows.Forms.ToolStripButton ToolbarRotateButton; + private System.Windows.Forms.ToolStripButton ToolbarScaleButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripButton ToolbarInfoWindowButton; + private System.Windows.Forms.ToolStripButton ToolbarProjectWindowButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripButton ToolbarAddItemButton; + private System.Windows.Forms.ToolStripButton ToolbarDeleteItemButton; + private System.Windows.Forms.ToolStripSplitButton ToolbarNewButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarNewProjectButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarNewYmapButton; + private System.Windows.Forms.ToolStripSplitButton ToolbarOpenButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarOpenProjectButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarOpenYmapButton; + private System.Windows.Forms.ToolStripButton ToolbarSaveButton; + private System.Windows.Forms.ToolStripButton ToolbarSaveAllButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.ToolStripSplitButton ToolbarUndoButton; + private System.Windows.Forms.ToolStripSplitButton ToolbarRedoButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; + private System.Windows.Forms.ToolStripButton ToolbarCopyButton; + private System.Windows.Forms.ToolStripButton ToolbarPasteButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarUndoListButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarRedoListButton; + private System.Windows.Forms.CheckBox ShowToolbarCheckBox; + private System.Windows.Forms.ToolStripSplitButton ToolbarTransformSpaceButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarObjectSpaceButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarWorldSpaceButton; + private System.Windows.Forms.TextBox SelectionNameTextBox; + private System.Windows.Forms.Label label25; + private System.Windows.Forms.ComboBox SelectionModeComboBox; + private System.Windows.Forms.TabPage SelectionExtensionTabPage; + private ReadOnlyPropertyGrid SelExtensionPropertyGrid; + private System.Windows.Forms.CheckBox EnableModsCheckBox; + private System.Windows.Forms.Button AdvancedSettingsButton; + private System.Windows.Forms.Button ControlSettingsButton; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuOptions; + private ToolStripSplitButtonFix ToolbarSelectButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectEntityButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectEntityExtensionButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectArchetypeExtensionButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectTimeCycleModifierButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectCarGeneratorButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectGrassButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectWaterQuadButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectCollisionButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectPathButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectDistantLodLightsButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectMloInstanceButton; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuJenkInd; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectTrainTrackButton; + private System.Windows.Forms.CheckBox PathBoundsCheckBox; + private System.Windows.Forms.ToolStripMenuItem ToolbarNewYndButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarNewTrainsButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarOpenYndButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarOpenTrainsButton; + private System.Windows.Forms.CheckBox PathsDepthClipCheckBox; + private System.Windows.Forms.CheckBox TrainPathsCheckBox; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectNavMeshButton; + private System.Windows.Forms.CheckBox NavMeshesCheckBox; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; + private System.Windows.Forms.ToolStripSplitButton ToolbarCameraModeButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarCameraPerspectiveButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarCameraMapViewButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarCameraOrthographicButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectScenarioButton; + private System.Windows.Forms.Panel ToolsDragPanel; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuWorldSearch; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuRPFExplorer; + private System.Windows.Forms.ToolStripMenuItem ToolbarNewScenarioButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarOpenScenarioButton; + } +} \ No newline at end of file diff --git a/WorldForm.cs b/WorldForm.cs new file mode 100644 index 0000000..49aac50 --- /dev/null +++ b/WorldForm.cs @@ -0,0 +1,9462 @@ +using CodeWalker.GameFiles; +using CodeWalker.Properties; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Threading; +using CodeWalker.Rendering; +using Device = SharpDX.Direct3D11.Device; +using Buffer = SharpDX.Direct3D11.Buffer; +using DriverType = SharpDX.Direct3D.DriverType; +using System.Runtime.InteropServices; +using System.Collections.Concurrent; +using CodeWalker.World; +using System.Diagnostics; +using SharpDX; +using CodeWalker.Utils; +using System.Globalization; +using CodeWalker.Project; +using System.Collections.Specialized; +using SharpDX.XInput; + +namespace CodeWalker +{ + public partial class WorldForm : Form, DXForm + { + public Form Form { get { return this; } } //for DXForm/DXManager use + DXManager dxman = new DXManager(); + public DXManager DXMan { get { return dxman; } } + Device currentdevice; + public Device Device { get { return currentdevice; } } + object rendersyncroot = new object(); + public object RenderSyncRoot { get { return rendersyncroot; } } + + ShaderManager shaders; + + volatile bool formopen = false; + volatile bool running = false; + volatile bool pauserendering = false; + volatile bool initialised = false; + + Stopwatch frametimer = new Stopwatch(); + Camera camera = new Camera(); + Space space = new Space(); + Timecycle timecycle = new Timecycle(); + Weather weather = new Weather(); + Clouds clouds = new Clouds(); + Water water = new Water(); + Trains trains = new Trains(); + Scenarios scenarios = new Scenarios(); + PopZones popzones = new PopZones(); + + + bool MouseLButtonDown = false; + bool MouseRButtonDown = false; + int MouseX; + int MouseY; + System.Drawing.Point MouseDownPoint; + System.Drawing.Point MouseLastPoint; + + bool rendermaps = false; + bool renderworld = false; + int startupviewmode = 0; //0=world, 1=ymap, 2=model + string modelname = "dt1_tc_dufo_core";//"dt1_11_fount_decal";// + string[] ymaplist; + bool rendertimedents = Settings.Default.ShowTimedEntities; + bool rendertimedentsalways = false; + bool renderinteriors = true; + bool renderproxies = false; + bool renderchildents = false; + Vector3 prevworldpos = new Vector3(0, 0, 100); //also the start pos + + bool usedynamiclod = Settings.Default.DynamicLOD; + float lodthreshold = 50.0f / (0.1f + (float)Settings.Default.DetailDist); //to match formula for the DetailTrackBar value + bool waitforchildrentoload = true; + + public GameFileCache GameFileCache { get { return gameFileCache; } } + GameFileCache gameFileCache = new GameFileCache(); + RenderableCache renderableCache = new RenderableCache(); + + + WorldControlMode ControlMode = WorldControlMode.Free; + + object MouseControlSyncRoot = new object(); + int MouseControlX = 0; + int MouseControlY = 0; + int MouseControlWheel = 0; + MouseButtons MouseControlButtons = MouseButtons.None; + MouseButtons MouseControlButtonsPrev = MouseButtons.None; + + bool ControlFireToggle = false; + + Entity camEntity = new Entity(); + PedEntity pedEntity = new PedEntity(); + volatile bool kbmovefwd = false; + volatile bool kbmovebck = false; + volatile bool kbmovelft = false; + volatile bool kbmovergt = false; + volatile bool kbmoveup = false; + volatile bool kbmovedn = false; + volatile bool kbjump = false; + + KeyBindings keyBindings = new KeyBindings(Settings.Default.KeyBindings); + bool iseditmode = false; + + + List Icons; + MapIcon MarkerIcon = null; + MapIcon LocatorIcon = null; + MapMarker LocatorMarker = null; + MapMarker GrabbedMarker = null; + MapMarker SelectedMarker = null; + MapMarker MousedMarker = null; + List Markers = new List(); + List SortedMarkers = new List(); + List MarkerBatch = new List(); + bool RenderLocator = false; + bool markerdepthclip = Settings.Default.MarkerDepthClip; + object markersyncroot = new object(); + object markersortedsyncroot = new object(); + UnitQuad markerquad = null; + + BoundsShaderMode boundsmode = BoundsShaderMode.None; + bool renderboundsclip = Settings.Default.BoundsDepthClip; + float renderboundsmaxrad = 20000.0f; + float renderboundsmaxdist = 10000.0f; + List BoundingBoxes = new List(); + List BoundingSpheres = new List(); + List HilightBoxes = new List(); + + + bool controllightdir = false; //if not, use timecycle + float lightdirx = 2.25f;//radians // approx. light dir on map satellite view + float lightdiry = 0.65f;//radians - used for manual light placement + bool renderskydome = Settings.Default.Skydome; + + bool rendercollisionmeshes = Settings.Default.ShowCollisionMeshes; + List collisionitems = new List(); + int collisionmeshrange = Settings.Default.CollisionMeshRange; + bool[] collisionmeshlayers = { true, true, true }; + bool collisionmeshlayerdrawable = true; + + List renderworldentities = new List(); + List renderworldrenderables = new List(); + Dictionary renderworldVisibleYmapDict = new Dictionary(); + Dictionary renderworldHideFlags = new Dictionary(); + Unk_1264241711 renderworldMaxLOD = Unk_1264241711.LODTYPES_DEPTH_ORPHANHD; + float renderworldLodDistMult = 1.0f; + float renderworldDetailDistMult = 1.0f; + + bool worldymaptimefilter = true; + bool worldymapweatherfilter = true; + + bool rendergrass = true; + bool renderdistlodlights = true; + bool rendernaturalambientlight = true; + bool renderartificialambientlight = true; + ShaderGlobalLights globalLights = new ShaderGlobalLights(); + + bool renderpathbounds = true; + bool renderpaths = false; + List renderpathynds = new List(); + + bool renderwaterquads = true; + List renderwaterquadlist = new List(); + + bool rendertraintracks = false; + List rendertraintracklist = new List(); + + bool rendernavmeshes = false; + List rendernavmeshynvs = new List(); + + bool renderscenariobounds = false; + bool renderscenarios = false; + List renderscenariolist = new List(); + + bool renderpopzones = true; + List renderpopzonelist = new List(); + + + float timeofday = 12.0f; + bool controltimeofday = true; + bool timerunning = false; + float timespeed = 0.5f;//min/sec + string weathertype = ""; + string individualcloudfrag = "contrails"; + + Vector4 currentWindVec = Vector4.Zero; + float currentWindTime = 0.0f; + + bool MapViewEnabled = false; + float MapViewDetail = 1.0f; + int MapViewDragX = 0; + int MapViewDragY = 0; + + bool ShowScriptedYmaps = true; + + bool MouseSelectEnabled = false; + bool ShowSelectionBounds = true; + bool SelectByGeometry = false; //select by geometry needs more work + MapSelection CurMouseHit = new MapSelection(); + MapSelection LastMouseHit = new MapSelection(); + MapSelection PrevMouseHit = new MapSelection(); + + bool MouseRayCollisionEnabled = true; + bool MouseRayCollisionVisible = true; + SpaceRayIntersectResult MouseRayCollision = new SpaceRayIntersectResult(); + + string SelectionModeStr = "Entity"; + MapSelectionMode SelectionMode = MapSelectionMode.Entity; + MapSelection SelectedItem; + WorldInfoForm InfoForm = null; + Dictionary SelectionModelDrawFlags = new Dictionary(); + Dictionary SelectionGeometryDrawFlags = new Dictionary(); + List SelectionLineVerts = new List(); + List SelectionTriVerts = new List(); + + + TransformWidget Widget = new TransformWidget(); + TransformWidget GrabbedWidget = null; + bool ShowWidget = true; + + bool CtrlPressed = false; + bool ShiftPressed = false; + + ProjectForm ProjectForm = null; + + Stack UndoSteps = new Stack(); + Stack RedoSteps = new Stack(); + Vector3 UndoStartPosition; + Quaternion UndoStartRotation; + Vector3 UndoStartScale; + + YmapEntityDef CopiedEntity = null; + YmapCarGen CopiedCarGen = null; + YndNode CopiedPathNode = null; + YnvPoly CopiedNavPoly = null; + TrainTrackNode CopiedTrainNode = null; + ScenarioNode CopiedScenarioNode = null; + + public bool EditEntityPivot { get; set; } = false; + + SettingsForm SettingsForm = null; + + WorldSearchForm SearchForm = null; + + Controller xbcontroller = null; + State xbcontrollerstate; + State xbcontrollerstateprev; + Vector4 xbmainaxes = Vector4.Zero; + Vector4 xbmainaxesprev = Vector4.Zero; + Vector2 xbtrigs = Vector2.Zero; + Vector2 xbtrigsprev = Vector2.Zero; + float xbcontrolvelocity = 0.0f; + + + + bool toolspanelexpanded = false; + int toolspanellastwidth; + bool toolsPanelResizing = false; + int toolsPanelResizeStartX = 0; + int toolsPanelResizeStartLeft = 0; + int toolsPanelResizeStartRight = 0; + + double currentRealTime = 0; + int framecount = 0; + float fcelapsed = 0.0f; + int fps = 0; + + bool initedOk = false; + + + public WorldForm() + { + InitializeComponent(); + + initedOk = dxman.Init(this, false); + } + + + private void Init() + { + //called from WorldForm_Load + + if (!initedOk) + { + Close(); + return; + } + + + MouseWheel += WorldForm_MouseWheel; + + string fldr = Settings.Default.GTAFolder; + if (string.IsNullOrEmpty(fldr) || !Directory.Exists(fldr)) + { + SelectFolderForm f = new SelectFolderForm(); + f.ShowDialog(); + if (f.Result == DialogResult.OK) + { + fldr = f.SelectedFolder; + } + else + { + //MessageBox.Show("No GTAV folder was chosen. CodeWalker will now exit."); + Close(); + return; + } + } + + if (!Directory.Exists(fldr)) + { + MessageBox.Show("The specified folder does not exist:\n" + fldr); + Close(); + return; + } + if (!File.Exists(fldr + "\\gta5.exe")) + { + MessageBox.Show("GTA5.exe not found in folder:\n" + fldr); + Close(); + return; + } + + Settings.Default.GTAFolder = fldr; //seems ok, save it for later + + + Widget.Position = new Vector3(1.0f, 10.0f, 100.0f); + Widget.Rotation = Quaternion.Identity; + Widget.Scale = Vector3.One; + Widget.Visible = false; + Widget.OnPositionChange += Widget_OnPositionChange; + Widget.OnRotationChange += Widget_OnRotationChange; + Widget.OnScaleChange += Widget_OnScaleChange; + + ymaplist = YmapsTextBox.Text.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + ViewModeComboBox.SelectedIndex = startupviewmode; + BoundsStyleComboBox.SelectedIndex = 0; //LoadSettings will handle this + + SelectionModeComboBox.SelectedIndex = 0; //Entity mode + ShowSelectedExtensionTab(false); + + toolspanellastwidth = ToolsPanel.Width * 2; //default expanded size + + + Icons = new List(); + AddIcon("Google Marker", "icon_google_marker_64x64.png", 64, 64, 11.0f, 40.0f, 1.0f); + AddIcon("Glokon Marker", "icon_glokon_normal_32x32.png", 32, 32, 11.0f, 32.0f, 1.0f); + AddIcon("Glokon Debug", "icon_glokon_debug_32x32.png", 32, 32, 11.5f, 32.0f, 1.0f); + MarkerIcon = Icons[1]; + LocatorIcon = Icons[2]; + foreach (MapIcon icon in Icons) + { + MarkerStyleComboBox.Items.Add(icon); + LocatorStyleComboBox.Items.Add(icon); + } + MarkerStyleComboBox.SelectedItem = MarkerIcon; //LoadSettings will handle this + LocatorStyleComboBox.SelectedItem = LocatorIcon; + LocatorMarker = new MapMarker(); + LocatorMarker.Icon = LocatorIcon; + LocatorMarker.IsMovable = true; + //AddDefaultMarkers(); //some POI to start with + + MetaName[] texsamplers = RenderableGeometry.GetTextureSamplerList(); + foreach (var texsampler in texsamplers) + { + TextureSamplerComboBox.Items.Add(texsampler); + } + //TextureSamplerComboBox.SelectedIndex = 0; //LoadSettings will handle this + //RenderModeComboBox.SelectedIndex = 0; //Default + + WorldMaxLodComboBox.SelectedIndex = 0;//should this be a setting? + + WeatherComboBox.SelectedIndex = 0;//show "" until weather types are loaded + + CameraModeComboBox.SelectedIndex = 0; //"Perspective" + + DlcLevelComboBox.SelectedIndex = 0; //show "" until DLC list is loaded + + UpdateToolbarShortcutsText(); + + InitController(); + + + dxman.Start(); + } + + private void InitController() + { + xbcontroller = new Controller(UserIndex.One); + if (!xbcontroller.IsConnected) + { + var controllers = new[] { new Controller(UserIndex.Two), new Controller(UserIndex.Three), new Controller(UserIndex.Four) }; + foreach (var selectControler in controllers) + { + if (selectControler.IsConnected) + { + xbcontroller = selectControler; + xbcontrollerstate = xbcontroller.GetState(); + xbcontrollerstateprev = xbcontrollerstate; + break; + } + } + } + else + { + xbcontrollerstate = xbcontroller.GetState(); + xbcontrollerstateprev = xbcontrollerstate; + } + + } + + + private MapIcon AddIcon(string name, string filename, int texw, int texh, float centerx, float centery, float scale) + { + string filepath = "icons\\" + filename; + try + { + MapIcon mi = new MapIcon(name, filepath, texw, texh, centerx, centery, scale); + Icons.Add(mi); + return mi; + } + catch (Exception ex) + { + MessageBox.Show("Could not load map icon " + filepath + " for " + name + "!\n\n" + ex.ToString()); + } + return null; + } + + + + + public void InitScene(Device device) + { + currentdevice = device; + + int width = ClientSize.Width; + int height = ClientSize.Height; + + try + { + shaders = new ShaderManager(device, dxman); + shaders.OnWindowResize(width, height); //init the buffers + } + catch (Exception ex) + { + MessageBox.Show("Error loading shaders!\n" + ex.ToString()); + return; + } + + + if (Icons != null) + { + foreach (MapIcon icon in Icons) + { + icon.LoadTexture(device, LogError); + } + } + + markerquad = new UnitQuad(device); + + renderableCache.OnDeviceCreated(device); + + camera.OnWindowResize(width, height); //init the projection stuff + camera.FollowEntity = camEntity; + camera.FollowEntity.Position = (startupviewmode!=2) ? prevworldpos : Vector3.Zero;// new Vector3(0.0f, 0.0f, 100.0f); + camera.FollowEntity.Orientation = Quaternion.LookAtLH(Vector3.Zero, Vector3.Up, Vector3.ForwardLH); + + space.AddPersistentEntity(pedEntity); + + + LoadSettings(); + + + formopen = true; + new Thread(new ThreadStart(ContentThread)).Start(); + + frametimer.Start(); + } + public void CleanupScene() + { + formopen = false; + + renderableCache.OnDeviceDestroyed(); + + shaders.Dispose(); + + + if (Icons != null) + { + foreach (MapIcon icon in Icons) + { + icon.UnloadTexture(); + } + } + + markerquad.Dispose(); + + int count = 0; + while (running && (count < 5000)) //wait for the content thread to exit gracefully + { + Thread.Sleep(1); + count++; + } + + currentdevice = null; + } + public void BuffersResized(int w, int h) + { + lock (rendersyncroot) + { + camera.OnWindowResize(w, h); + shaders.OnWindowResize(w, h); + } + } + public void RenderScene(DeviceContext context) + { + float elapsed = (float)frametimer.Elapsed.TotalSeconds; + framecount++; + fcelapsed += elapsed; + if (fcelapsed >= 0.5f) + { + fps = framecount * 2; + framecount = 0; + fcelapsed -= 0.5f; + } + if (elapsed > 0.1f) elapsed = 0.1f; + frametimer.Restart(); + + currentRealTime += elapsed; + + if (pauserendering) return; + + if (!Monitor.TryEnter(rendersyncroot, 50)) + { return; } //couldn't get a lock, try again next time + //Monitor.Enter(rendersyncroot); + + UpdateControlInputs(elapsed); + + UpdateTimeOfDay(elapsed); + + weather.Update(elapsed); + + clouds.Update(elapsed); + + UpdateWindVector(elapsed); + + UpdateGlobalLights(); + + space.Update(elapsed); + + camera.SetMousePosition(MouseLastPoint.X, MouseLastPoint.Y); + + camera.Update(elapsed); + + UpdateWidgets(); + + HilightBoxes.Clear(); + BoundingBoxes.Clear(); + BoundingSpheres.Clear(); + BeginMouseHitTest(); + + + dxman.ClearRenderTarget(context); + + shaders.BeginFrame(context, currentRealTime, elapsed); + + shaders.EnsureShaderTextures(gameFileCache, renderableCache); + + RenderSky(context); + + RenderClouds(context); + + shaders.ClearDepth(context); + + if (renderworld || rendermaps) + { + RenderWorld(); + + if (rendermaps) + { + RenderYmaps(); + } + } + else + { + RenderSingleItem(); + } + + shaders.RenderQueued(context, camera, currentWindVec); + + RenderBounds(context); + + RenderSelection(context); + + RenderMoused(context); + + RenderSelectionGeometry(context); + + shaders.RenderFinalPass(context); + + RenderMarkers(context); + + RenderWidgets(context); + + renderableCache.RenderThreadSync(); + + Monitor.Exit(rendersyncroot); + + UpdateMarkerSelectionPanelInvoke(); + } + + + private void UpdateTimeOfDayLabel() + { + int v = TimeOfDayTrackBar.Value; + float fh = v / 60.0f; + int ih = (int)fh; + int im = v - (ih * 60); + if (ih == 24) ih = 0; + TimeOfDayLabel.Text = string.Format("{0:00}:{1:00}", ih, im); + } + + private void UpdateTimeOfDay(float elapsed) + { + if (timerunning) + { + float helapsed = elapsed * timespeed / 60.0f; + timeofday += helapsed; + while (timeofday >= 24.0f) timeofday -= 24.0f; + while (timeofday < 0.0f) timeofday += 24.0f; + timecycle.SetTime(timeofday); + } + + } + + private void UpdateGlobalLights() + { + Vector3 lightdir = Vector3.Zero;//will be updated before each frame from X and Y vars + Color4 lightdircolour = Color4.White; + Color4 lightdirambcolour = new Color4(0.5f, 0.5f, 0.5f, 1.0f); + Color4 lightnaturalupcolour = new Color4(0.0f); + Color4 lightnaturaldowncolour = new Color4(0.0f); + Color4 lightartificialupcolour = new Color4(0.0f); + Color4 lightartificialdowncolour = new Color4(0.0f); + bool hdr = shaders.hdr; + float hdrint = 1.0f; + Vector3 sundir = Vector3.Up; + Vector3 moondir = Vector3.Down; + Vector3 moonax = Vector3.UnitZ; + + if (controllightdir) + { + float cryd = (float)Math.Cos(lightdiry); + lightdir.X = -(float)Math.Sin(-lightdirx) * cryd; + lightdir.Y = -(float)Math.Cos(-lightdirx) * cryd; + lightdir.Z = (float)Math.Sin(lightdiry); + lightdircolour = Color4.White; + lightdirambcolour = new Color4(0.5f, 0.5f, 0.5f, 1.0f); + if (hdr && (weather != null) && (weather.Inited)) + { + lightdircolour *= weather.CurrentValues.skyHdr; + lightdircolour.Alpha = 1.0f; + lightdirambcolour *= weather.CurrentValues.skyHdr; + lightdirambcolour.Alpha = 1.0f; + hdrint = weather.CurrentValues.skyHdr; + } + sundir = lightdir; + moondir = -lightdir; + } + else + { + float sunroll = timecycle.sun_roll * (float)Math.PI / 180.0f; //122 + float moonroll = timecycle.moon_roll * (float)Math.PI / 180.0f; //-122 + float moonwobamp = timecycle.moon_wobble_amp; //0.2 + float moonwobfreq = timecycle.moon_wobble_freq; //2 + float moonwoboffs = timecycle.moon_wobble_offset; //0.375 + float dayval = (0.5f + (timeofday - 6.0f) / 14.0f); + float nightval = (((timeofday>12.0f)?(timeofday - 7.0f):(timeofday+17.0f)) / 9.0f); + float daycyc = (float)Math.PI * dayval; + float nightcyc = (float)Math.PI * nightval; + Vector3 sdir = new Vector3((float)Math.Sin(daycyc), -(float)Math.Cos(daycyc), 0.0f); + Vector3 mdir = new Vector3(-(float)Math.Sin(nightcyc), 0.0f, -(float)Math.Cos(nightcyc)); + Quaternion saxis = Quaternion.RotationYawPitchRoll(0.0f, sunroll, 0.0f); + Quaternion maxis = Quaternion.RotationYawPitchRoll(0.0f, -moonroll, 0.0f); + sundir = Vector3.Normalize(saxis.Multiply(sdir)); + moondir = Vector3.Normalize(maxis.Multiply(mdir)); + moonax = Vector3.Normalize(maxis.Multiply(Vector3.UnitY)); + //bool usemoon = false; + + lightdir = sundir; + + //if (lightdir.Z < -0.5f) lightdir.Z = -lightdir.Z; //make sure the lightsource is always above the horizon... + + if ((timeofday < 5.0f) || (timeofday > 21.0f)) + { + lightdir = moondir; + //usemoon = true; + } + + if (lightdir.Z < 0) + { + lightdir.Z = 0; //don't let the light source go below the horizon... + } + + //lightdir = Vector3.Normalize(weather.CurrentValues.sunDirection); + + if (weather != null && weather.Inited) + { + lightdircolour = (Color4)weather.CurrentValues.lightDirCol; + lightdirambcolour = (Color4)weather.CurrentValues.lightDirAmbCol; + lightnaturalupcolour = (Color4)weather.CurrentValues.lightNaturalAmbUp; + lightnaturaldowncolour = (Color4)weather.CurrentValues.lightNaturalAmbDown; + lightartificialupcolour = (Color4)weather.CurrentValues.lightArtificialExtUp; + lightartificialdowncolour = (Color4)weather.CurrentValues.lightArtificialExtDown; + float lamult = weather.CurrentValues.lightDirAmbIntensityMult; + float abounce = weather.CurrentValues.lightDirAmbBounce; + float minmult = hdr ? 0.1f : 0.5f; + lightdircolour *= Math.Max(lightdircolour.Alpha, minmult); + lightdirambcolour *= lightdirambcolour.Alpha * lamult; // 0.1f * lamult; + + //if (usemoon) + //{ + // lightdircolour *= weather.CurrentValues.skyMoonIten; + //} + + + lightnaturalupcolour *= lightnaturalupcolour.Alpha * weather.CurrentValues.lightNaturalAmbUpIntensityMult; + lightnaturaldowncolour *= lightnaturaldowncolour.Alpha; + lightartificialupcolour *= lightartificialupcolour.Alpha; + lightartificialdowncolour *= lightartificialdowncolour.Alpha; + + if (!hdr) + { + Color4 maxdirc = new Color4(1.0f); + Color4 maxambc = new Color4(0.5f); + lightdircolour = Color4.Min(lightdircolour, maxdirc); + lightdirambcolour = Color4.Min(lightdirambcolour, maxambc); + lightnaturalupcolour = Color4.Min(lightnaturalupcolour, maxambc); + lightnaturaldowncolour = Color4.Min(lightnaturaldowncolour, maxambc); + lightartificialupcolour = Color4.Min(lightartificialupcolour, maxambc); + lightartificialdowncolour = Color4.Min(lightartificialdowncolour, maxambc); + } + else + { + hdrint = weather.CurrentValues.skyHdr;//.lightDirCol.W; + } + } + + + } + + globalLights.Weather = weather; + globalLights.HdrEnabled = hdr; + globalLights.SpecularEnabled = !MapViewEnabled;//disable specular for map view. + globalLights.HdrIntensity = Math.Max(hdrint, 1.0f); + globalLights.CurrentSunDir = sundir; + globalLights.CurrentMoonDir = moondir; + globalLights.MoonAxis = moonax; + globalLights.Params.LightDir = lightdir; + globalLights.Params.LightDirColour = lightdircolour; + globalLights.Params.LightDirAmbColour = lightdirambcolour; + globalLights.Params.LightNaturalAmbUp = rendernaturalambientlight ? lightnaturalupcolour : Color4.Black; + globalLights.Params.LightNaturalAmbDown = rendernaturalambientlight ? lightnaturaldowncolour : Color4.Black; + globalLights.Params.LightArtificialAmbUp = renderartificialambientlight ? lightartificialupcolour : Color4.Black; + globalLights.Params.LightArtificialAmbDown = renderartificialambientlight ? lightartificialdowncolour : Color4.Black; + + + if (shaders != null) + { + shaders.SetGlobalLightParams(globalLights); + } + + } + + private void UpdateWindVector(float elapsed) + { + //wind still needs a lot of work. + //currently just feed the wind vector with small oscillations... + currentWindTime += elapsed; + if (currentWindTime >= 200.0f) currentWindTime -= 200.0f; + + float dirval = (float)(currentWindTime * 0.01 * Math.PI); + float dirval1 = (float)Math.Sin(currentWindTime * 0.100 * Math.PI) * 0.3f; + float dirval2 = (float)(currentWindTime * 0.333 * Math.PI); + float dirval3 = (float)(currentWindTime * 0.5 * Math.PI); + float dirval4 = (float)Math.Sin(currentWindTime * 0.223 * Math.PI) * 0.4f; + float dirval5 = (float)Math.Sin(currentWindTime * 0.4 * Math.PI) * 5.5f; + + currentWindVec.Z = (float)Math.Sin(dirval) * dirval1 + (float)Math.Cos(dirval2) * dirval4; + currentWindVec.W = (float)Math.Cos(dirval) * dirval5 + (float)Math.Sin(dirval3) * dirval4; + + float strval = (float)(currentWindTime * 0.1 * Math.PI); + float strval2 = (float)(currentWindTime * 0.825 * Math.PI); + float strval3 = (float)(currentWindTime * 0.333 * Math.PI); + float strval4 = (float)(currentWindTime * 0.666 * Math.PI); + float strbase = 0.1f * ((float)Math.Sin(strval * 0.5)); + float strbase2 = 0.02f * ((float)Math.Sin(strval2 * 0.1)); + + currentWindVec.X = (float)Math.Sin(strval) * strbase + ((float)Math.Cos(strval3) * strbase2); + currentWindVec.Y = (float)Math.Cos(strval2) * strbase + ((float)Math.Sin(strval4 - strval3) * strbase2); + } + + private void UpdateControlInputs(float elapsed) + { + var s = Settings.Default; + + float moveSpeed = 50.0f; + + bool xbenable = (xbcontroller != null) && (xbcontroller.IsConnected); + float lx = 0, ly = 0, rx = 0, ry = 0, lt = 0, rt = 0; //input axes + if (xbenable) + { + xbcontrollerstateprev = xbcontrollerstate; + xbcontrollerstate = xbcontroller.GetState(); + xbmainaxesprev = xbmainaxes; + xbtrigsprev = xbtrigs; + xbmainaxes = ControllerMainAxes(); + xbtrigs = ControllerTriggers(); + lx = xbmainaxes.X; + ly = xbmainaxes.Y; + rx = xbmainaxes.Z; + ry = xbmainaxes.W; + lt = xbtrigs.X; + rt = xbtrigs.Y; + float lamt = s.XInputLThumbSensitivity * elapsed; + float ramt = s.XInputRThumbSensitivity * elapsed; + ly = s.XInputLThumbInvert ? ly : -ly; + ry = s.XInputRThumbInvert ? ry : -ry; + lx *= lamt; + ly *= lamt; + rx *= ramt; + ry *= ramt; + + if (ControllerButtonJustPressed(GamepadButtonFlags.Start)) + { + SetControlMode(ControlMode == WorldControlMode.Free ? WorldControlMode.Ped : WorldControlMode.Free); + } + } + + + if (ControlMode == WorldControlMode.Free) + { + + Vector3 movevec = Vector3.Zero; + + if (MapViewEnabled == true) + { + if (kbmovefwd) movevec.Y += 1.0f; + if (kbmovebck) movevec.Y -= 1.0f; + if (kbmovelft) movevec.X -= 1.0f; + if (kbmovergt) movevec.X += 1.0f; + if (kbmoveup) movevec.Y += 1.0f; + if (kbmovedn) movevec.Y -= 1.0f; + movevec *= elapsed * moveSpeed * Math.Min(camera.OrthographicTargetSize * 0.01f, 50.0f); + + + float mapviewscale = 1.0f / camera.Height; + float fdx = MapViewDragX * mapviewscale; + float fdy = MapViewDragY * mapviewscale; + movevec.X -= fdx * camera.OrthographicSize; + movevec.Y += fdy * camera.OrthographicSize; + + } + else + { + //normal movement + if (kbmovefwd) movevec.Z -= 1.0f; + if (kbmovebck) movevec.Z += 1.0f; + if (kbmovelft) movevec.X -= 1.0f; + if (kbmovergt) movevec.X += 1.0f; + if (kbmoveup) movevec.Y += 1.0f; + if (kbmovedn) movevec.Y -= 1.0f; + movevec *= elapsed * moveSpeed * Math.Min(camera.TargetDistance, 20.0f); + } + + + Vector3 movewvec = camera.ViewInvQuaternion.Multiply(movevec); + camEntity.Position += movewvec; + + MapViewDragX = 0; + MapViewDragY = 0; + + + + + if (xbenable) + { + camera.ControllerRotate(lx + rx, ly + ry); + + float zoom = 0.0f; + float zoomspd = s.XInputZoomSpeed; + float zoomamt = zoomspd * elapsed; + if (ControllerButtonPressed(GamepadButtonFlags.DPadUp)) zoom += zoomamt; + if (ControllerButtonPressed(GamepadButtonFlags.DPadDown)) zoom -= zoomamt; + + camera.ControllerZoom(zoom); + + float acc = 0.0f; + float accspd = s.XInputMoveSpeed;//actually accel speed... + acc += rt * accspd; + acc -= lt * accspd; + + Vector3 newdir = camera.ViewDirection; //maybe use the "vehicle" direction...? + xbcontrolvelocity += (acc * elapsed); + + if (ControllerButtonPressed(GamepadButtonFlags.A | GamepadButtonFlags.RightShoulder)) //handbrake... + { + xbcontrolvelocity *= Math.Max(0.75f - elapsed, 0);//not ideal for low fps... + //xbcontrolvelocity = 0.0f; + if (Math.Abs(xbcontrolvelocity) < 0.001f) xbcontrolvelocity = 0.0f; + } + + camEntity.Velocity = newdir * xbcontrolvelocity; + camEntity.Position += camEntity.Velocity * elapsed; + + + //fire! + if (ControllerButtonJustPressed(GamepadButtonFlags.LeftShoulder)) + { + SpawnTestEntity(true); + } + + } + + } + else + { + //"play" mode + + int mcx, mcy, mcw; + MouseButtons mcb, mcbp; + bool mlb = false, mrb = false; + bool mlbjustpressed = false, mrbjustpressed = false; + lock (MouseControlSyncRoot) + { + mcx = MouseControlX; + mcy = MouseControlY; + mcw = MouseControlWheel; + mcb = MouseControlButtons; + mcbp = MouseControlButtonsPrev; + mlb = ((mcb & MouseButtons.Left) > 0); + mrb = ((mcb & MouseButtons.Right) > 0); + mlbjustpressed = mlb && ((mcbp & MouseButtons.Left) == 0); + mrbjustpressed = mrb && ((mcbp & MouseButtons.Right) == 0); + MouseControlX = 0; + MouseControlY = 0; + MouseControlWheel = 0; + MouseControlButtonsPrev = MouseControlButtons; + //MouseControlButtons = MouseButtons.None; + } + + + camera.MouseRotate(mcx, mcy); + + if (xbenable) + { + camera.ControllerRotate(rx, ry); + } + + + + Vector2 movecontrol = new Vector2(xbmainaxes.X, xbmainaxes.Y); //(L stick) + if (kbmovelft) movecontrol.X -= 1.0f; + if (kbmovergt) movecontrol.X += 1.0f; + if (kbmovefwd) movecontrol.Y += 1.0f; + if (kbmovebck) movecontrol.Y -= 1.0f; + movecontrol.X = Math.Min(movecontrol.X, 1.0f); + movecontrol.X = Math.Max(movecontrol.X, -1.0f); + movecontrol.Y = Math.Min(movecontrol.Y, 1.0f); + movecontrol.Y = Math.Max(movecontrol.Y, -1.0f); + + Vector3 fwd = camera.ViewDirection; + Vector3 fwdxy = Vector3.Normalize(new Vector3(fwd.X, fwd.Y, 0)); + Vector3 lftxy = Vector3.Normalize(Vector3.Cross(fwd, Vector3.UnitZ)); + Vector3 move = lftxy * movecontrol.X + fwdxy * movecontrol.Y; + Vector2 movexy = new Vector2(move.X, move.Y); + + + pedEntity.ControlMovement = movexy; + pedEntity.ControlJump = kbjump || ControllerButtonPressed(GamepadButtonFlags.X); + pedEntity.ControlBoost = ShiftPressed || ControllerButtonPressed(GamepadButtonFlags.A | GamepadButtonFlags.RightShoulder | GamepadButtonFlags.LeftShoulder); + + + //Vector3 pedfwd = pedEntity.Orientation.Multiply(Vector3.UnitZ); + + + + + + + bool fire = mlb || (xbtrigs.Y > 0); + if (fire && !ControlFireToggle) + { + SpawnTestEntity(true); + } + ControlFireToggle = fire; + + + } + + + } + + private Vector4 ControllerMainAxes() + { + var gp = xbcontrollerstate.Gamepad; + var ldz = Gamepad.LeftThumbDeadZone; + var rdz = Gamepad.RightThumbDeadZone; + float ltnrng = -(short.MinValue + ldz); + float ltprng = (short.MaxValue - ldz); + float rtnrng = -(short.MinValue + rdz); + float rtprng = (short.MaxValue - rdz); + + float lx = (gp.LeftThumbX < 0) ? Math.Min((gp.LeftThumbX + ldz) / ltnrng, 0) : + (gp.LeftThumbX > 0) ? Math.Max((gp.LeftThumbX - ldz) / ltprng, 0) : 0; + float ly = (gp.LeftThumbY < 0) ? Math.Min((gp.LeftThumbY + ldz) / ltnrng, 0) : + (gp.LeftThumbY > 0) ? Math.Max((gp.LeftThumbY - ldz) / ltprng, 0) : 0; + float rx = (gp.RightThumbX < 0) ? Math.Min((gp.RightThumbX + rdz) / rtnrng, 0) : + (gp.RightThumbX > 0) ? Math.Max((gp.RightThumbX - rdz) / rtprng, 0) : 0; + float ry = (gp.RightThumbY < 0) ? Math.Min((gp.RightThumbY + rdz) / rtnrng, 0) : + (gp.RightThumbY > 0) ? Math.Max((gp.RightThumbY - rdz) / rtprng, 0) : 0; + + return new Vector4(lx, ly, rx, ry); + } + private Vector2 ControllerTriggers() + { + var gp = xbcontrollerstate.Gamepad; + var tt = Gamepad.TriggerThreshold; + float trng = byte.MaxValue - tt; + float lt = Math.Max((gp.LeftTrigger - tt) / trng, 0); + float rt = Math.Max((gp.RightTrigger - tt) / trng, 0); + return new Vector2(lt, rt); + } + private bool ControllerButtonPressed(GamepadButtonFlags b) + { + return ((xbcontrollerstate.Gamepad.Buttons & b) != 0); + } + private bool ControllerButtonJustPressed(GamepadButtonFlags b) + { + return (((xbcontrollerstate.Gamepad.Buttons & b) != 0) && ((xbcontrollerstateprev.Gamepad.Buttons & b) == 0)); + } + + + + private DrawableBase TryGetDrawable(Archetype arche) + { + if (arche == null) return null; + uint drawhash = arche.Hash; + DrawableBase drawable = null; + if ((arche.DrawableDict != 0))// && (arche.DrawableDict != arche.Hash)) + { + //try get drawable from ydd... + YddFile ydd = gameFileCache.GetYdd(arche.DrawableDict); + if (ydd != null) + { + if (ydd.Loaded && (ydd.Dict != null)) + { + Drawable d; + ydd.Dict.TryGetValue(drawhash, out d); //can't out to base class? + drawable = d; + if (drawable == null) + { + return null; //drawable wasn't in dict!! + } + } + else + { + return null; //ydd not loaded yet, or has no dict + } + } + else + { + //return null; //couldn't find drawable dict... quit now? + } + } + if (drawable == null) + { + //try get drawable from ydr. + YdrFile ydr = gameFileCache.GetYdr(drawhash); + if (ydr != null) + { + if (ydr.Loaded) + { + drawable = ydr.Drawable; + } + } + else + { + YftFile yft = gameFileCache.GetYft(drawhash); + if (yft != null) + { + if (yft.Loaded) + { + if (yft.Fragment != null) + { + drawable = yft.Fragment.Drawable; + } + } + } + } + } + + return drawable; + } + + private Renderable TryGetRenderable(Archetype arche, DrawableBase drawable, uint txdHash = 0) + { + if (drawable == null) return null; + //BUG: only last texdict used!! needs to cache textures per archetype........ + //(but is it possible to have the same drawable with different archetypes?) + uint texDict = (arche != null) ? arche.TextureDict.Hash : txdHash; + uint clipDict = (arche != null) ? arche.ClipDict.Hash : 0; + + Renderable rndbl = renderableCache.GetRenderable(drawable); + if (rndbl == null) return null; + + if (clipDict != 0) + { + YcdFile ycd = gameFileCache.GetYcd(clipDict); + if ((ycd != null) && (ycd.Loaded)) + { + ClipMapEntry cme; + if (ycd.ClipMap.TryGetValue(arche.Hash, out cme)) + { + } + else + { } + } + } + + + bool alltexsloaded = true; + int missingtexcount = 0; + for (int mi = 0; mi < rndbl.HDModels.Length; mi++) + { + var model = rndbl.HDModels[mi]; + + //if (!RenderIsModelFinalRender(model) && !renderproxies) + //{ + // continue; //filter out reflection proxy models... + //} + + + foreach (var geom in model.Geometries) + { + if (geom.Textures != null) + { + for (int i = 0; i < geom.Textures.Length; i++) + { + var tex = geom.Textures[i]; + var ttex = tex as Texture; + RenderableTexture rdtex = null; + if ((ttex == null) && (tex != null)) + { + //TextureRef means this RenderableTexture needs to be loaded from texture dict... + if (texDict != 0) + { + YtdFile ytd = gameFileCache.GetYtd(texDict); + if ((ytd != null) && (ytd.Loaded) && (ytd.TextureDict != null)) + { + var dtex = ytd.TextureDict.Lookup(tex.NameHash); + if (dtex == null) + { + //not present in dictionary... check already loaded texture dicts... + var ytd2 = gameFileCache.TryGetTextureDictForTexture(tex.NameHash); + if ((ytd2 != null) && (ytd2.Loaded) && (ytd2.TextureDict != null)) + { + dtex = ytd2.TextureDict.Lookup(tex.NameHash); + } + else + { + //couldn't find texture dict? + //first try going through ytd hierarchy... + dtex = gameFileCache.TryFindTextureInParent(tex.NameHash, texDict); + + + //if (dtex == null) + //{ //try for a texture dict with the same hash as the archetype? + // dtex = gameFileCache.TryFindTextureInParent(tex.TextureRef.NameHash, arche.Hash); + // if (dtex != null) + // { } + //} + } + } + if (dtex != null) + { + geom.Textures[i] = dtex; //cache it for next time to avoid the lookup... + rdtex = renderableCache.GetRenderableTexture(dtex); + } + if (rdtex == null) + { } //nothing to see here :( + } + else if ((ytd == null)) + { + Texture dtex = null; + if (drawable.ShaderGroup.TextureDictionary != null) + { + dtex = drawable.ShaderGroup.TextureDictionary.Lookup(tex.NameHash); + if (dtex == null) + { + //dtex = drawable.ShaderGroup.TextureDictionary.Textures.data_items[0]; + } + } + if (dtex == null) + { + var ytd2 = gameFileCache.TryGetTextureDictForTexture(tex.NameHash); + if ((ytd2 != null) && (ytd2.Loaded) && (ytd2.TextureDict != null)) + { + dtex = ytd2.TextureDict.Lookup(tex.NameHash); + } + if (dtex == null) + { + dtex = gameFileCache.TryFindTextureInParent(tex.NameHash, texDict); + } + } + rdtex = renderableCache.GetRenderableTexture(dtex); + if (rdtex == null) + { missingtexcount -= 2; } //(give extra chance..) couldn't find the texture! :( + } + else if (ytd != null) + { + alltexsloaded = false;//ytd not loaded yet + //missingtexcount++; + } + } + else //no texdict specified, nothing to see here.. + { + var ytd2 = gameFileCache.TryGetTextureDictForTexture(tex.NameHash); + if ((ytd2 != null) && (ytd2.Loaded) && (ytd2.TextureDict != null)) + { + var dtex = ytd2.TextureDict.Lookup(tex.NameHash); + rdtex = renderableCache.GetRenderableTexture(dtex); + } + } + } + else if (ttex != null) //ensure embedded renderable texture + { + rdtex = renderableCache.GetRenderableTexture(ttex); + } + else if (tex == null) + { } //tex wasn't loaded? shouldn't happen.. + + + geom.RenderableTextures[i] = rdtex; + if (rdtex != null) + { + if (!rdtex.IsLoaded) + { + alltexsloaded = false; + missingtexcount++; + } + } + else + { + //alltexsloaded = false; + missingtexcount++; + } + + + } + } + } + } + + rndbl.AllTexturesLoaded = alltexsloaded || (missingtexcount < 2); + + return rndbl; + } + + private bool LodDistTest(ref Vector3 p, ref Vector3 min, ref Vector3 max, float lodDist) + { + //for AABB only! for oriented BBs p must be transformed first... + if (p.X < (min.X - lodDist)) return false; + if (p.X > (max.X + lodDist)) return false; + if (p.Y < (min.Y - lodDist)) return false; + if (p.Y > (max.Y + lodDist)) return false; + if (p.Z < (min.Z - lodDist)) return false; + if (p.Z > (max.Z + lodDist)) return false; + return true; + } + private bool LodDistTest(Vector3 p, Vector3 min, Vector3 max, float lodDist) + { + //for AABB only! for oriented BBs p must be transformed first... + if (p.X < (min.X - lodDist)) return false; + if (p.X > (max.X + lodDist)) return false; + if (p.Y < (min.Y - lodDist)) return false; + if (p.Y > (max.Y + lodDist)) return false; + if (p.Z < (min.Z - lodDist)) return false; + if (p.Z > (max.Z + lodDist)) return false; + return true; + } + + + + private void RenderSky(DeviceContext context) + { + if (MapViewEnabled) return; + if (!renderskydome) return; + if (!weather.Inited) return; + + var shader = shaders.Skydome; + shader.UpdateSkyLocals(weather, globalLights); + + + + + DrawableBase skydomeydr = null; + YddFile skydomeydd = gameFileCache.GetYdd(2640562617); //skydome hash + if ((skydomeydd != null) && (skydomeydd.Loaded) && (skydomeydd.Dict != null)) + { + skydomeydr = skydomeydd.Dict.Values.FirstOrDefault(); + } + + Texture starfield = null; + Texture moon = null; + YtdFile skydomeytd = gameFileCache.GetYtd(2640562617); //skydome hash + if ((skydomeytd != null) && (skydomeytd.Loaded) && (skydomeytd.TextureDict != null) && (skydomeytd.TextureDict.Dict != null)) + { + skydomeytd.TextureDict.Dict.TryGetValue(1064311147, out starfield); //starfield hash + skydomeytd.TextureDict.Dict.TryGetValue(234339206, out moon); //moon-new hash + } + + Renderable sdrnd = null; + if (skydomeydr != null) + { + sdrnd = renderableCache.GetRenderable(skydomeydr); + } + + RenderableTexture sftex = null; + if (starfield != null) + { + sftex = renderableCache.GetRenderableTexture(starfield); + } + + RenderableTexture moontex = null; + if (moon != null) + { + moontex = renderableCache.GetRenderableTexture(moon); + } + + if ((sdrnd != null) && (sdrnd.IsLoaded) && (sftex != null) && (sftex.IsLoaded)) + { + shaders.SetDepthStencilMode(context, DepthStencilMode.DisableAll); + shaders.SetRasterizerMode(context, RasterizerMode.Solid); + + RenderableInst rinst = new RenderableInst(); + rinst.Position = Vector3.Zero; + rinst.CamRel = Vector3.Zero; + rinst.Distance = 0.0f; + rinst.BBMin = skydomeydr.BoundingBoxMin.XYZ(); + rinst.BBMax = skydomeydr.BoundingBoxMax.XYZ(); + rinst.BSCenter = Vector3.Zero; + rinst.Radius = skydomeydr.BoundingSphereRadius; + rinst.Orientation = Quaternion.Identity; + rinst.Scale = Vector3.One; + rinst.TintPaletteIndex = 0; + rinst.Renderable = sdrnd; + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.PTT); + shader.SetSceneVars(context, camera, null, globalLights); + shader.SetEntityVars(context, ref rinst); + + RenderableModel rmod = ((sdrnd.HDModels != null) && (sdrnd.HDModels.Length > 0)) ? sdrnd.HDModels[0] : null; + RenderableGeometry rgeom = ((rmod != null) && (rmod.Geometries != null) && (rmod.Geometries.Length > 0)) ? rmod.Geometries[0] : null; + + if ((rgeom != null) && (rgeom.VertexType == VertexType.PTT)) + { + shader.SetModelVars(context, rmod); + shader.SetTextures(context, sftex); + + rgeom.Render(context); + } + + //shaders.SetRasterizerMode(context, RasterizerMode.SolidDblSided); + //shaders.SetDepthStencilMode(context, DepthStencilMode.Enabled); + shader.RenderSun(context, camera, weather, globalLights); + + + if ((moontex != null) && (moontex.IsLoaded)) + { + shader.RenderMoon(context, camera, weather, globalLights, moontex); + } + + + + shader.UnbindResources(context); + } + + } + + private void RenderClouds(DeviceContext context) + { + if (MapViewEnabled) return; + if (!renderskydome) return; + if (!weather.Inited) return; + if (!clouds.Inited) return; + + + var shader = shaders.Clouds; + + shaders.SetDepthStencilMode(context, DepthStencilMode.DisableAll); + shaders.SetRasterizerMode(context, RasterizerMode.Solid); + shaders.SetDefaultBlendState(context); + //shaders.SetAlphaBlendState(context); + + shader.SetShader(context); + shader.UpdateCloudsLocals(clouds, globalLights); + shader.SetSceneVars(context, camera, null, globalLights); + + var vtype = (VertexType)0; + + if (!string.IsNullOrEmpty(individualcloudfrag)) + { + //render one cloud fragment. + + CloudHatFrag frag = clouds.HatManager.FindFrag(individualcloudfrag); + if (frag == null) return; + + for (int i = 0; i < frag.Layers.Length; i++) + { + CloudHatFragLayer layer = frag.Layers[i]; + uint dhash = JenkHash.GenHash(layer.Filename.ToLower()); + Archetype arch = gameFileCache.GetArchetype(dhash); + if (arch == null) + { continue; } + + if (Math.Max(camera.Position.Z, 0.0f) < layer.HeightTigger) continue; + + var drw = TryGetDrawable(arch); + var rnd = TryGetRenderable(arch, drw); + + if ((rnd == null) || (rnd.IsLoaded == false) || (rnd.AllTexturesLoaded == false)) + { continue; } + + + RenderableInst rinst = new RenderableInst(); + rinst.Position = frag.Position;// Vector3.Zero; + rinst.CamRel = Vector3.Zero;// - camera.Position; + rinst.Distance = rinst.CamRel.Length(); + rinst.BBMin = arch.BBMin; + rinst.BBMax = arch.BBMax; + rinst.BSCenter = frag.Position; + rinst.Radius = arch.BSRadius; + rinst.Orientation = Quaternion.Identity; + rinst.Scale = frag.Scale;// Vector3.One; + rinst.TintPaletteIndex = 0; + rinst.Renderable = rnd; + + shader.SetEntityVars(context, ref rinst); + + + for (int mi = 0; mi < rnd.HDModels.Length; mi++) + { + var model = rnd.HDModels[mi]; + + for (int gi = 0; gi < model.Geometries.Length; gi++) + { + var geom = model.Geometries[gi]; + + if (geom.VertexType != vtype) + { + vtype = geom.VertexType; + shader.SetInputLayout(context, vtype); + } + + shader.SetGeomVars(context, geom); + + geom.Render(context); + } + } + + } + + + } + + + + } + + + private void RenderWorld() + { + //start point for world view mode rendering. + //also used for the water, paths, collisions, nav mesh, and the project window items. + + renderworldentities.Clear(); + renderworldrenderables.Clear(); + renderworldVisibleYmapDict.Clear(); + renderworldHideFlags.Clear(); + + + int hour = worldymaptimefilter ? (int)timeofday : -1; + MetaHash weathertype = worldymapweatherfilter ? ((weather.CurrentWeatherType != null) ? weather.CurrentWeatherType.NameHash : new MetaHash(0)) : new MetaHash(0); + + if (renderworld) + { + space.GetVisibleYmaps(camera, hour, weathertype, renderworldVisibleYmapDict); + + foreach (var ae in space.TemporaryEntities) + { + if (ae.EntityDef == null) continue; //nothing to render... + RenderWorldCalcEntityVisibility(camera, ae.EntityDef); + renderworldentities.Add(ae.EntityDef); + } + } + + if (ProjectForm != null) + { + ProjectForm.GetVisibleYmaps(camera, renderworldVisibleYmapDict); + } + + //float minZ = float.MaxValue; + float maxZ = float.MinValue; + float cvwidth = camera.OrthographicSize * camera.AspectRatio*0.5f; + float cvheight = camera.OrthographicSize*0.5f; + float cvwmin = camera.Position.X - cvwidth; + float cvwmax = camera.Position.X + cvwidth; + float cvhmin = camera.Position.Y - cvheight; + float cvhmax = camera.Position.Y + cvheight; + + foreach (var ymap in renderworldVisibleYmapDict.Values) + { + if (!RenderWorldYmapIsVisible(ymap)) continue; + if (ymap.AllEntities != null) + { + for (int i = 0; i < ymap.AllEntities.Length; i++) + { + var ent = ymap.AllEntities[i]; + ent.LargestChildLodDist = 0; + ent.ChildrenLoading = false; + ent.Rendered = false; + ent.ChildRendered = false; + if (MapViewEnabled) + { + //find the max Z value for positioning camera in map view, to help shadows + if ((ent.Position.Z<1000.0f)&&(ent.BSRadius < 500.0f)) + { + float r = ent.BSRadius; + if (((ent.Position.X + r) > cvwmin) && ((ent.Position.X - r) < cvwmax) && ((ent.Position.Y + r) > cvhmin) && ((ent.Position.Y - r) < cvhmax)) + { + //minZ = Math.Min(minZ, ent.BBMin.Z); + maxZ = Math.Max(maxZ, ent.BBMax.Z); + } + } + } + } + } + } + + if (MapViewEnabled) + { + //move the camera closer to the geometry, to help shadows in map view. + if (maxZ == float.MinValue) maxZ = 1000.0f; + camera.Position.Z = Math.Min(maxZ, 1000.0f); + } + + + foreach (var ymap in renderworldVisibleYmapDict.Values) + { + if (!RenderWorldYmapIsVisible(ymap)) continue; + if (ymap.RootEntities != null) + { + YmapFile pymap; + renderworldVisibleYmapDict.TryGetValue(ymap.CMapData.parent, out pymap); + for (int i = 0; i < ymap.RootEntities.Length; i++) + { + var ent = ymap.RootEntities[i]; + int pind = ent.CEntityDef.parentIndex; + if (pind >= 0) //connect root entities to parents if they have them.. + { + YmapEntityDef p = null; + if ((pymap != null) && (pymap.AllEntities != null)) + { + if ((pind < pymap.AllEntities.Length)) + { + p = pymap.AllEntities[pind]; + ent.Parent = p; + ent.ParentGuid = p.CEntityDef.guid; + ent.ParentName = p.CEntityDef.archetypeName; + } + } + else + { }//should only happen if parent ymap not loaded yet... + } + RenderWorldRecurseCalcEntityVisibility(camera, ent); + } + } + } + + foreach (var ymap in renderworldVisibleYmapDict.Values) + { + if (!RenderWorldYmapIsVisible(ymap)) continue; + if (ymap.RootEntities != null) + { + for (int i = 0; i < ymap.RootEntities.Length; i++) + { + var ent = ymap.RootEntities[i]; + RenderWorldRecurseAddEntities(ent, renderworldentities); + } + } + + UpdateMouseHits(ymap); + } + + + //go through the render list, and try ensure renderables and textures for all. + //if an entity is not fully loaded, set a flag for its parent, then traverse to root + //until found an entity that is fully loaded. + //on a second loop, build a final render list based on the flags. + + for (int i = 0; i < renderworldentities.Count; i++) + { + var ent = renderworldentities[i]; + var arch = ent.Archetype; + var pent = ent.Parent; + + if (renderinteriors && ent.IsMlo) //render Mlo child entities... + { + if ((ent.MloData != null) && (ent.MloData.AllEntities != null)) + { + for (int j = 0; j < ent.MloData.AllEntities.Length; j++) + { + var intent = ent.MloData.AllEntities[j]; + var intarch = intent.Archetype; + if (intarch == null) continue; //missing archetype... + + if (!RenderIsEntityFinalRender(intent)) continue; //proxy or something.. + + intent.CamRel = intent.Position - camera.Position; + intent.Distance = intent.CamRel.Length(); + intent.IsVisible = true; + + var bscent = intent.CamRel + intent.BSCenter; + float bsrad = intent.BSRadius; + if (!camera.ViewFrustum.ContainsSphereNoClipNoOpt(ref bscent, bsrad)) + { + continue; //frustum cull interior ents + } + var intdrbl = TryGetDrawable(intarch); + var intrndbl = TryGetRenderable(intarch, intdrbl); + if (intrndbl == null) continue; //no renderable + if (!(intrndbl.IsLoaded && (intrndbl.AllTexturesLoaded || !waitforchildrentoload))) continue; //not loaded yet + + RenderableEntity intrent = new RenderableEntity(); + intrent.Entity = intent; + intrent.Renderable = intrndbl; + renderworldrenderables.Add(intrent); + } + } + if (rendercollisionmeshes) + { + RenderInteriorCollisionMesh(ent); + } + } + + ent.Rendered = true; + var drawable = TryGetDrawable(arch); + Renderable rndbl = TryGetRenderable(arch, drawable); + if ((rndbl != null) && rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload)) + { + RenderableEntity rent = new RenderableEntity(); + rent.Entity = ent; + rent.Renderable = rndbl; + renderworldrenderables.Add(rent); + + if (pent != null) + { + pent.ChildRendered = true; + } + } + else if (waitforchildrentoload) + { + //todo: render parent if children loading....... + } + } + + for (int i = 0; i < renderworldrenderables.Count; i++) + { + var ent = renderworldrenderables[i].Entity; + if (ent.ChildRendered && !ent.ChildrenLoading) + { + ent.ChildrenRendered = true; + } + } + + for (int i = 0; i < renderworldrenderables.Count; i++) + { + var rent = renderworldrenderables[i]; + var ent = rent.Entity; + var arch = ent.Archetype; + + RenderArchetype(arch, ent, rent.Renderable, false); + } + + + + if (rendergrass) + { + foreach (var ymap in renderworldVisibleYmapDict.Values) + { + if (ymap.GrassInstanceBatches != null) + { + RenderYmapGrass(ymap); + } + } + } + if (renderdistlodlights && timecycle.IsNightTime) + { + foreach (var ymap in renderworldVisibleYmapDict.Values) + { + if (ymap.DistantLODLights != null) + { + RenderYmapDistantLODLights(ymap); + } + } + } + + if (renderwaterquads || (SelectionMode == MapSelectionMode.WaterQuad)) + { + RenderWorldWaterQuads(); + } + if (rendercollisionmeshes || (SelectionMode == MapSelectionMode.Collision)) + { + RenderWorldCollisionMeshes(); + } + if (renderpaths || (SelectionMode == MapSelectionMode.Path)) + { + RenderWorldPaths(); + } + if (rendertraintracks || (SelectionMode == MapSelectionMode.TrainTrack)) + { + RenderWorldTrainTracks(); + } + if (rendernavmeshes || (SelectionMode == MapSelectionMode.NavMesh)) + { + RenderWorldNavMeshes(); + } + if (renderscenarios || (SelectionMode == MapSelectionMode.Scenario)) + { + RenderWorldScenarios(); + } + if (renderpopzones || (SelectionMode == MapSelectionMode.PopZone)) + { + RenderWorldPopZones(); + } + } + private bool RenderWorldYmapIsVisible(YmapFile ymap) + { + if (!ShowScriptedYmaps) + { + if ((ymap._CMapData.flags & 1) > 0) + return false; + } + + return true; + } + private void RenderWorldCalcEntityVisibility(Camera cam, YmapEntityDef ent) + { + ent.CamRel = ent.Position - cam.Position; + ent.Distance = ent.CamRel.Length(); + float distval = ent.Distance; + + if (MapViewEnabled) + { + distval = cam.OrthographicSize / MapViewDetail; + } + + + var loddist = ent.CEntityDef.lodDist; + var cloddist = ent.CEntityDef.childLodDist; + + var loddistmultdef = renderworldLodDistMult * 1.0f; + var loddistmultorph = renderworldDetailDistMult * 1.5f; + var loddistmultarch = renderworldLodDistMult * 1.0f; + + if (loddist <= 0.0f)//usually -1 or -2 + { + if (ent.Archetype != null) + { + loddist = ent.Archetype.LodDist * loddistmultarch; + } + } + else if (ent.CEntityDef.lodLevel == Unk_1264241711.LODTYPES_DEPTH_ORPHANHD) + { + loddist *= loddistmultorph; //orphan view dist adjustment... + } + else + { + loddist *= loddistmultdef; + } + + + if (cloddist <= 0) + { + if (ent.Archetype != null) + { + cloddist = ent.Archetype.LodDist * loddistmultarch; + //cloddist = ent.Archetype.BSRadius * 50.0f; + } + } + else + { + cloddist *= loddistmultdef; + } + if (cloddist == 0) + { + //cloddist = loddist;//always try to show children, based on their loddist + } + + + ent.IsVisible = (distval <= loddist); + ent.ChildrenVisible = (distval <= cloddist) && (ent.CEntityDef.numChildren > 0); + ent.ChildrenLoading = false; + + if ((ent.Parent != null) && (ent.CEntityDef.lodLevel != Unk_1264241711.LODTYPES_DEPTH_ORPHANHD)) + { + if (ent.Parent.CEntityDef.childLodDist == 0.0f) + { + ent.Parent.LargestChildLodDist = Math.Max(ent.Parent.LargestChildLodDist, loddist); + } + } + + if (renderworldMaxLOD != Unk_1264241711.LODTYPES_DEPTH_ORPHANHD) + { + if ((ent.CEntityDef.lodLevel == Unk_1264241711.LODTYPES_DEPTH_ORPHANHD) || + (ent.CEntityDef.lodLevel < renderworldMaxLOD)) + { + ent.IsVisible = false; + ent.ChildrenVisible = false; + } + if (ent.CEntityDef.lodLevel == renderworldMaxLOD) + { + ent.ChildrenVisible = false; + } + } + + if (!ent.IsVisible) + { + ent.ChildrenRendered = false; + } + } + private void RenderWorldRecurseCalcEntityVisibility(Camera cam, YmapEntityDef ent) + { + RenderWorldCalcEntityVisibility(cam, ent); + if (ent.ChildrenVisible) + { + if (ent.Children != null) + { + for (int i = 0; i < ent.Children.Length; i++) + { + var child = ent.Children[i]; + if (child.Ymap == ent.Ymap) + { + RenderWorldRecurseCalcEntityVisibility(cam, child); + } + } + } + } + } + private void RenderWorldRecurseAddEntities(YmapEntityDef ent, List res) + { + //bool useclod = false; //(ent.CEntityDef.childLodDist == 0.0f); + //bool hide = useclod ? (ent.AnyChildVisible /*&& !ent.AnyChildInvisible*/) : ent.ChildrenVisible; + //bool force = !useclod && (ent.Parent != null) && ent.Parent.ChildrenVisible && !hide; + bool hide = ent.ChildrenVisible; + bool force = (ent.Parent != null) && ent.Parent.ChildrenVisible && !hide; + if (force || (ent.IsVisible && !hide)) + { + if (ent.Archetype != null) + { + if (!RenderIsEntityFinalRender(ent)) return; + + var bscent = ent.CamRel + ent.BSCenter; + float bsrad = ent.BSRadius; + if (!camera.ViewFrustum.ContainsSphereNoClipNoOpt(ref bscent, bsrad)) + { + return; //frustum cull + } + + + res.Add(ent); + } + else + { } + } + if (ent.IsVisible && ent.ChildrenVisible && (ent.Children != null)) + { + for (int i = 0; i < ent.Children.Length; i++) + { + var child = ent.Children[i]; + if (child.Ymap == ent.Ymap) + { + RenderWorldRecurseAddEntities(ent.Children[i], res); + } + } + } + } + + private void RenderWorldWaterQuads() + { + renderwaterquadlist.Clear(); + + water.GetVisibleQuads(camera, renderwaterquadlist); + + if (ProjectForm != null) + { + ProjectForm.GetVisibleWaterQuads(camera, renderwaterquadlist); + } + + foreach (var quad in renderwaterquadlist) + { + RenderableWaterQuad rquad = renderableCache.GetRenderableWaterQuad(quad); + if ((rquad != null) && (rquad.IsLoaded)) + { + rquad.CamRel = -camera.Position; + shaders.Enqueue(rquad); + } + } + + UpdateMouseHits(renderwaterquadlist); + + } + + private void RenderWorldPaths() + { + + renderpathynds.Clear(); + space.GetVisibleYnds(camera, renderpathynds); + + if (ProjectForm != null) + { + ProjectForm.GetVisibleYnds(camera, renderpathynds); + } + + foreach (var ynd in renderpathynds) + { + RenderablePathBatch rnd = renderableCache.GetRenderablePathBatch(ynd); + if ((rnd != null) && (rnd.IsLoaded)) + { + shaders.Enqueue(rnd); + } + } + + UpdateMouseHits(renderpathynds); + } + + private void RenderWorldTrainTracks() + { + if (!trains.Inited) return; + + rendertraintracklist.Clear(); + rendertraintracklist.AddRange(trains.TrainTracks); + + if (ProjectForm != null) + { + ProjectForm.GetVisibleTrainTracks(camera, rendertraintracklist); + } + + foreach (var track in rendertraintracklist) + { + RenderablePathBatch rnd = renderableCache.GetRenderablePathBatch(track); + if ((rnd != null) && (rnd.IsLoaded)) + { + shaders.Enqueue(rnd); + } + } + + UpdateMouseHits(rendertraintracklist); + } + + private void RenderWorldNavMeshes() + { + + rendernavmeshynvs.Clear(); + space.GetVisibleYnvs(camera, rendernavmeshynvs); + + if (ProjectForm != null) + { + //ProjectForm.GetVisibleYnvs(camera, rendernavmeshynvs); + } + + + foreach (var ynv in rendernavmeshynvs) + { + RenderablePathBatch rnd = renderableCache.GetRenderablePathBatch(ynv); + if ((rnd != null) && (rnd.IsLoaded)) + { + shaders.Enqueue(rnd); + } + } + + UpdateMouseHits(rendernavmeshynvs); + + + } + + private void RenderWorldScenarios() + { + if (!scenarios.Inited) return; + + renderscenariolist.Clear(); + renderscenariolist.AddRange(scenarios.ScenarioRegions); + + if (ProjectForm != null) + { + ProjectForm.GetVisibleScenarios(camera, renderscenariolist); + } + + foreach (var scenario in renderscenariolist) + { + RenderablePathBatch rnd = renderableCache.GetRenderablePathBatch(scenario.ScenarioRegion); + if ((rnd != null) && (rnd.IsLoaded)) + { + shaders.Enqueue(rnd); + } + } + + UpdateMouseHits(renderscenariolist); + } + + private void RenderWorldPopZones() + { + if (!popzones.Inited) return; + + renderpopzonelist.Clear(); + renderpopzonelist.AddRange(popzones.Groups.Values); + + if (ProjectForm != null) + { + //ProjectForm.GetVisiblePopZones(camera, renderpopzonelist); + } + + + + } + + + + + private void RenderSingleItem() + { + //start point for model view mode rendering + + uint hash = 0;// JenkHash.GenHash(modelname); + if (!uint.TryParse(modelname, out hash)) //try use a hash directly + { + hash = JenkHash.GenHash(modelname); + } + Archetype arche = gameFileCache.GetArchetype(hash); + + Archetype selarch = null; + DrawableBase seldrwbl = null; + YmapEntityDef selent = null; + + if (arche != null) + { + RenderArchetype(arche, null); + + selarch = arche; + } + else + { + YmapFile ymap = gameFileCache.GetYmap(hash); + if (ymap != null) + { + RenderYmap(ymap); + } + else + { + //not a ymap... see if it's a ydr or yft + YdrFile ydr = gameFileCache.GetYdr(hash); + if (ydr != null) + { + if (ydr.Loaded) + { + RenderDrawable(ydr.Drawable, null, null, -camera.Position, hash); + + seldrwbl = ydr.Drawable; + } + } + else + { + YftFile yft = gameFileCache.GetYft(hash); + if (yft != null) + { + if (yft.Loaded) + { + if (yft.Fragment != null) + { + var f = yft.Fragment; + + RenderDrawable(f.Drawable, null, null, -camera.Position, hash); + + if (f.Unknown_F8h_Data != null) //cloth + { + RenderDrawable(f.Unknown_F8h_Data, null, null, -camera.Position, hash); + } + + //vehicle wheels... + if ((f.PhysicsLODGroup != null) && (f.PhysicsLODGroup.PhysicsLOD1 != null)) + { + var pl1 = f.PhysicsLODGroup.PhysicsLOD1; + if ((pl1.Children != null) && (pl1.Children.data_items != null)) + { + for (int i = 0; i < pl1.Children.data_items.Length; i++) + { + var pch = pl1.Children.data_items[i]; + if ((pch.Drawable1 != null) && (pch.Drawable1.AllModels.Length != 0)) + { + //RenderDrawable(pch.Drawable1, null, null, -camera.Position, hash); + } + } + } + } + + seldrwbl = f.Drawable; + } + } + } + else + { + //TODO: collision bounds single model... + //YbnFile ybn = gameFileCache.GetYbn(hash); + } + } + + } + } + + if ((selarch != null) && (seldrwbl == null)) + { + seldrwbl = TryGetDrawable(selarch); + } + + //select this item for viewing by the UI... + if ((SelectedItem.Archetype != selarch) || (SelectedItem.Drawable != seldrwbl) || (SelectedItem.EntityDef != selent)) + { + SelectedItem.Clear(); + SelectedItem.Archetype = selarch; + SelectedItem.Drawable = seldrwbl; + SelectedItem.EntityDef = selent; + UpdateSelectionUI(false); + } + + } + + + private void RenderYmaps() + { + //start point for ymap view mode rendering + + foreach (string lod in ymaplist) + { + uint hash = JenkHash.GenHash(lod); + YmapFile ymap = gameFileCache.GetYmap(hash); + RenderYmap(ymap); + } + } + private void RenderYmap(YmapFile ymap) + { + if (ymap == null) return; + if (!ymap.Loaded) return; + + UpdateMouseHits(ymap); + + if ((ymap.AllEntities != null) && (ymap.RootEntities != null)) + { + if (usedynamiclod) + { + for (int i = 0; i < ymap.RootEntities.Length; i++) + { + RenderYmapLOD(ymap.RootEntities[i].Ymap, ymap.RootEntities[i]); + } + } + else + { + var ents = renderchildents ? ymap.AllEntities : ymap.RootEntities; + for (int i = 0; i < ents.Length; i++) + { + var ent = ents[i]; + if (renderchildents && ent.Children != null) continue; + //if (rootent.CEntityDef.parentIndex == -1) continue; + Archetype arch = ent.Archetype; + if (arch != null) + { + if (!arch.IsTimeArchetype || (rendertimedents && (rendertimedentsalways || arch.IsActive(timeofday)))) + { + ent.CamRel = ent.Position - camera.Position; + RenderArchetype(arch, ent); + } + } + else + { + //couldn't find archetype... + } + } + } + } + + if (rendergrass && (ymap.GrassInstanceBatches != null)) + { + RenderYmapGrass(ymap); + } + if (renderdistlodlights && timecycle.IsNightTime && (ymap.DistantLODLights != null)) + { + RenderYmapDistantLODLights(ymap); + } + + } + private bool RenderYmapLOD(YmapFile ymap, YmapEntityDef entity) + { + if (!ymap.Loaded) return false; + + ymap.EnsureChildYmaps(gameFileCache); + + Archetype arch = entity.Archetype; + if (arch != null) + { + if (!arch.IsTimeArchetype || (rendertimedents && (rendertimedentsalways || arch.IsActive(timeofday)))) + { + bool usechild = false; + entity.CamRel = entity.Position - camera.Position; + float dist = (entity.CamRel + entity.BSCenter).Length(); + float rad = arch.BSRadius; + float loddist = entity.CEntityDef.lodDist; + if (loddist < 1.0f) + { + loddist = 200.0f; + } + float mindist = Math.Max(dist - rad, 1.0f) * lodthreshold; + if (mindist < loddist) + { + //recurse... + var children = entity.ChildrenMerged; + if ((children != null)) + { + usechild = true; + for (int i = 0; i < children.Length; i++) + { + var childe = children[i]; + if (!RenderYmapLOD(childe.Ymap, childe)) + { + if (waitforchildrentoload) + { + usechild = false; //might cause some overlapping, but should reduce things disappearing + } + } + } + } + if (!entity.ChildrenRendered) + { + entity.ChildrenRendered = usechild; + } + } + else + { + entity.ChildrenRendered = false; + } + if (!usechild && !entity.ChildrenRendered) + { + + + + if (renderinteriors && entity.IsMlo) //render Mlo child entities... + { + if ((entity.MloData != null) && (entity.MloData.AllEntities != null)) + { + for (int j = 0; j < entity.MloData.AllEntities.Length; j++) + { + var intent = entity.MloData.AllEntities[j]; + var intarch = intent.Archetype; + if (intarch == null) continue; //missing archetype... + + if (!RenderIsEntityFinalRender(intent)) continue; //proxy or something.. + + intent.CamRel = intent.Position - camera.Position; + intent.Distance = intent.CamRel.Length(); + intent.IsVisible = true; + + RenderArchetype(intarch, intent); + } + } + if (rendercollisionmeshes) + { + RenderInteriorCollisionMesh(entity); + } + } + + + + + return RenderArchetype(arch, entity); + } + return true; + } + + } + return false; + } + + + private void RenderYmapGrass(YmapFile ymap) + { + //enqueue ymap grass instance batches for rendering + + if (ymap.GrassInstanceBatches == null) return; + + foreach (var batch in ymap.GrassInstanceBatches) + { + batch.CamRel = batch.Position - camera.Position; + //batch.Distance = batch.CamRel.Length(); + + float lodDist = batch.Batch.lodDist * renderworldDetailDistMult;//maybe add grass dist mult + //if (batch.Distance > lodDist) continue; //too far away.. + + lodDist *= 0.75f; //reduce it just a bit to improve performance... remove this later + + float cx = camera.Position.X; + float cy = camera.Position.Y; + float cz = camera.Position.Z; + if (cx < (batch.AABBMin.X - lodDist)) continue; + if (cx > (batch.AABBMax.X + lodDist)) continue; + if (cy < (batch.AABBMin.Y - lodDist)) continue; + if (cy > (batch.AABBMax.Y + lodDist)) continue; + if (cz < (batch.AABBMin.Z - lodDist)) continue; + if (cz > (batch.AABBMax.Z + lodDist)) continue; + + + var bscent = batch.CamRel; + float bsrad = batch.Radius; + if (!camera.ViewFrustum.ContainsSphereNoClipNoOpt(ref bscent, bsrad)) + { + continue; //frustum cull grass batches... + } + + var arch = batch.Archetype; + var drbl = TryGetDrawable(arch); + var rndbl = TryGetRenderable(arch, drbl); + var instb = renderableCache.GetRenderableInstanceBatch(batch); + if (rndbl == null) continue; //no renderable + if (!(rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload))) continue; //not loaded yet + if ((instb == null) || !instb.IsLoaded) continue; + + RenderableInstanceBatchInst binst = new RenderableInstanceBatchInst(); + binst.Batch = instb; + binst.Renderable = rndbl; + + shaders.Enqueue(binst); + + } + + } + + private void RenderYmapDistantLODLights(YmapFile ymap) + { + //enqueue ymap DistantLODLights instance batch for rendering + + if (ymap.DistantLODLights == null) return; + + switch (ymap.DistantLODLights.CDistantLODLight.category) + { + case 0: //distlodlights_small009.ymap + case 1: //distlodlights_medium000.ymap + case 2: //distlodlights_large000.ymap + break; + default: + break; + } + + RenderableDistantLODLights lights = renderableCache.GetRenderableDistantLODLights(ymap.DistantLODLights); + if (!lights.IsLoaded) return; + + + uint ytdhash = 3154743001; //"graphics" + uint texhash = 2236244673; //"distant_light" + YtdFile graphicsytd = gameFileCache.GetYtd(ytdhash); + Texture lighttex = null; + if ((graphicsytd != null) && (graphicsytd.Loaded) && (graphicsytd.TextureDict != null) && (graphicsytd.TextureDict.Dict != null)) + { + graphicsytd.TextureDict.Dict.TryGetValue(texhash, out lighttex); //starfield hash + } + + if (lighttex == null) return; + RenderableTexture lightrtex = null; + if (lighttex != null) + { + lightrtex = renderableCache.GetRenderableTexture(lighttex); + } + if (lightrtex == null) return; + if (!lightrtex.IsLoaded) return; + + lights.Texture = lightrtex; + + shaders.Enqueue(lights); + } + + + + + private bool RenderIsEntityFinalRender(YmapEntityDef ent) + { + var arch = ent.Archetype; + bool isshadowproxy = false; + bool isreflproxy = false; + uint archflags = arch.BaseArchetype.flags; + if (arch.IsTimeArchetype) + { + if (!(rendertimedents && (rendertimedentsalways || arch.IsActive(timeofday)))) return false; + archflags = arch.TimeArchetype.CBaseArchetypeDef.flags; + } + else if (arch.IsMloArchetype) + { + archflags = arch.MloArchetype.CBaseArchetypeDef.flags; + } + //switch (archflags) + //{ + // //case 8192: //8192: is YTYP no shadow rendering - CP + // case 2048: //000000000000000000100000000000 shadow proxies... + // case 536872960: //100000000000000000100000000000 tunnel refl/shadow prox? + // isshadowproxy = true; break; + //} + if ((archflags & 2048) > 0) + { + isshadowproxy = true; + } + + //if ((ent.CEntityDef.flags & 1572864) == 1572864) + //{ + // isreflproxy = true; + //} + + switch (ent.CEntityDef.flags) + { + case 135790592: //001000000110000000000000000000 prewater proxy (golf course) + case 135790593: //001000000110000000000000000001 water refl proxy? (mike house) + case 672661504: //101000000110000000000000000000 vb_ca_prop_tree_reflprox_2 + case 536870912: //100000000000000000000000000000 vb_05_emissive_mirroronly + case 35127296: //000010000110000000000000000000 tunnel refl proxy? + case 39321602: //000010010110000000000000000010 mlo reflection? + isreflproxy = true; break; + //nonproxy is: //000000000110000000000000001000 (1572872) + // //000000000110000000000000000000 + } + if (isshadowproxy || isreflproxy) + { + return renderproxies; //filter out proxy entities... + } + return true; + } + private bool RenderIsModelFinalRender(RenderableModel model) + { + + if ((model.Unk2Ch & 1) == 0) //smallest bit is proxy/"final render" bit? seems to work... + { + return renderproxies; + } + return true; + + //switch (model.Unk2Ch) + //{ + // case 65784: //0000010000000011111000 //reflection proxy? + // case 65788: //0000010000000011111100 + // case 131312: //0000100000000011110000 //reflection proxy? + // case 131320: //0000100000000011111000 //reflection proxy? + // case 131324: //0000100000000011111100 //shadow/reflection proxy? + // case 196834: //0000110000000011100010 //shadow proxy? (tree branches) + // case 196848: //0000110000000011110000 //reflection proxy? + // case 196856: //0000110000000011111000 //reflection proxy? hotel nr golf course + // case 262392: //0001000000000011111000 //reflection proxy? + // case 327932: //0001010000000011111100 //reflection proxy? (alamo/sandy shores) + // case 983268: //0011110000000011100100 //big reflection proxy? + // case 2293988://1000110000000011100100 //big reflection proxy? + // //case 1442047://golf course water proxy, but other things also + // //case 1114367://mike house water proxy, but other things also + // return renderproxies; + //} + //return true; + } + + + + private bool RenderArchetype(Archetype arche, YmapEntityDef entity, Renderable rndbl = null, bool cull = true) + { + //enqueue a single archetype for rendering. + + if (arche == null) return false; + + Vector3 camrel = (entity != null) ? entity.CamRel : -camera.Position; + + if (arche.IsMloArchetype) + { } + + Quaternion orientation = Quaternion.Identity; + Vector3 scale = Vector3.One; + Vector3 bscent = camrel; + if (entity != null) + { + orientation = entity.Orientation; + scale = entity.Scale; + bscent += entity.BSCenter; + } + else + { + bscent += arche.BSCenter; + } + + float bsrad = arche.BSRadius;// * scale; + if (cull) + { + if (!camera.ViewFrustum.ContainsSphereNoClipNoOpt(ref bscent, bsrad)) + { + return true; //culled - not visible; don't render, but pretend we did for LOD purposes.. + } + } + + float dist = bscent.Length(); + + if (boundsmode == BoundsShaderMode.Sphere) + { + if ((bsrad < renderboundsmaxrad) && (dist < renderboundsmaxdist)) + { + MapSphere ms = new MapSphere(); + ms.CamRelPos = bscent; + ms.Radius = bsrad; + BoundingSpheres.Add(ms); + } + } + if (boundsmode == BoundsShaderMode.Box) + { + if ((dist < renderboundsmaxdist)) + { + MapBox mb = new MapBox(); + mb.CamRelPos = camrel; + mb.BBMin = arche.BBMin; + mb.BBMax = arche.BBMax; + mb.Orientation = orientation; + mb.Scale = scale; + BoundingBoxes.Add(mb); + } + } + + + + bool res = false; + if (rndbl == null) + { + var drawable = TryGetDrawable(arche); + rndbl = TryGetRenderable(arche, drawable); + } + + if (rndbl != null) + { + res = RenderRenderable(rndbl, arche, entity, camrel); + + + //fragments have extra drawables! need to render those too... TODO: handle fragments properly... + FragDrawable fd = rndbl.Key as FragDrawable; + if (fd != null) + { + var frag = fd.OwnerFragment; + if ((frag != null) && (frag.Unknown_F8h_Data != null)) //cloth... + { + rndbl = TryGetRenderable(arche, frag.Unknown_F8h_Data); + if (rndbl != null) + { + bool res2 = RenderRenderable(rndbl, arche, entity, camrel); + res = res || res2; + } + } + } + } + + + return res; + } + + private bool RenderDrawable(DrawableBase drawable, Archetype arche, YmapEntityDef entity, Vector3 camrel, uint txdHash = 0) + { + //enqueue a single drawable for rendering. + + if (drawable == null) + return false; + + Renderable rndbl = TryGetRenderable(arche, drawable, txdHash); + if (rndbl == null) + return false; + + return RenderRenderable(rndbl, arche, entity, camrel); + } + + private bool RenderRenderable(Renderable rndbl, Archetype arche, YmapEntityDef entity, Vector3 camrel) + { + //enqueue a single renderable for rendering. + + if (!rndbl.IsLoaded) return false; + + + if (((SelectionMode == MapSelectionMode.Entity) || (SelectionMode == MapSelectionMode.EntityExtension) || (SelectionMode == MapSelectionMode.ArchetypeExtension))) + { + UpdateMouseHit(rndbl, arche, entity, camrel); + } + + bool isselected = (rndbl.Key == SelectedItem.Drawable); + + Vector3 position = Vector3.Zero; + Vector3 scale = Vector3.One; + Quaternion orientation = Quaternion.Identity; + uint tintPaletteIndex = 0; + Vector3 bbmin = (arche != null) ? arche.BBMin : rndbl.Key.BoundingBoxMin.XYZ(); + Vector3 bbmax = (arche != null) ? arche.BBMax : rndbl.Key.BoundingBoxMax.XYZ(); + Vector3 bscen = (arche != null) ? arche.BSCenter : rndbl.Key.BoundingCenter; + float radius = (arche != null) ? arche.BSRadius : rndbl.Key.BoundingSphereRadius; + float distance = (camrel + bscen).Length(); + if (entity != null) + { + position = entity.Position; + scale = entity.Scale; + orientation = entity.Orientation; + tintPaletteIndex = entity.CEntityDef.tintValue; + bbmin = entity.BBMin; + bbmax = entity.BBMax; + bscen = entity.BSCenter; + } + + + if (rendercollisionmeshes && collisionmeshlayerdrawable) + { + Drawable sdrawable = rndbl.Key as Drawable; + if ((sdrawable != null) && (sdrawable.Bound != null)) + { + RenderCollisionMesh(sdrawable.Bound, entity); + } + } + + + bool retval = true;// false; + if (rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload)) + { + RenderableGeometryInst rginst = new RenderableGeometryInst(); + rginst.Inst.Renderable = rndbl; + rginst.Inst.CamRel = camrel; + rginst.Inst.Position = position; + rginst.Inst.Scale = scale; + rginst.Inst.Orientation = orientation; + rginst.Inst.TintPaletteIndex = tintPaletteIndex; + rginst.Inst.BBMin = bbmin; + rginst.Inst.BBMax = bbmax; + rginst.Inst.BSCenter = bscen; + rginst.Inst.Radius = radius; + rginst.Inst.Distance = distance; + + + RenderableModel[] models = isselected ? rndbl.AllModels : rndbl.HDModels; + + for (int mi = 0; mi < models.Length; mi++) + { + var model = models[mi]; + + if (isselected) + { + if (SelectionModelDrawFlags.ContainsKey(model.DrawableModel)) + { continue; } //filter out models in selected item that aren't flagged for drawing. + } + + if (!RenderIsModelFinalRender(model) && !renderproxies) + { continue; } //filter out reflection proxy models... + + for (int gi = 0; gi < model.Geometries.Length; gi++) + { + var geom = model.Geometries[gi]; + + if (isselected) + { + if (SelectionGeometryDrawFlags.ContainsKey(geom.DrawableGeom)) + { continue; } //filter out geometries in selected item that aren't flagged for drawing. + } + + rginst.Geom = geom; + + shaders.Enqueue(rginst); + } + } + } + else + { + retval = false; + } + return retval; + } + + + + + private void RenderWorldCollisionMeshes() + { + //enqueue collision meshes for rendering - from the world grid + + collisionitems.Clear(); + space.GetVisibleBounds(camera, collisionmeshrange, collisionmeshlayers, collisionitems); + + foreach (var item in collisionitems) + { + YbnFile ybn = gameFileCache.GetYbn(item.Name); + if ((ybn != null) && (ybn.Loaded)) + { + RenderCollisionMesh(ybn.Bounds, null); + } + } + + } + + private void RenderInteriorCollisionMesh(YmapEntityDef mlo) + { + //enqueue interior collison meshes for rendering. + + if (mlo.Archetype == null) return; + var hash = mlo.Archetype.Hash; + YbnFile ybn = gameFileCache.GetYbn(hash); + if ((ybn != null) && (ybn.Loaded)) + { + RenderCollisionMesh(ybn.Bounds, mlo); + } + if (ybn == null) + { } + } + + private void RenderCollisionMesh(Bounds bounds, YmapEntityDef entity) + { + //enqueue a single collision mesh for rendering. + + Vector3 position; + Vector3 scale; + Quaternion orientation; + if (entity != null) + { + position = entity.Position; + scale = entity.Scale; + orientation = entity.Orientation; + } + else + { + position = Vector3.Zero; + scale = Vector3.One; + orientation = Quaternion.Identity; + } + + switch (bounds.Type) + { + case 10: //BoundComposite + BoundComposite boundcomp = bounds as BoundComposite; + if (boundcomp != null) + { + RenderableBoundComposite rndbc = renderableCache.GetRenderableBoundComp(boundcomp); + if (rndbc.IsLoaded) + { + RenderableBoundGeometryInst rbginst = new RenderableBoundGeometryInst(); + rbginst.Inst.Renderable = rndbc; + rbginst.Inst.Orientation = orientation; + rbginst.Inst.Scale = scale; + foreach (var geom in rndbc.Geometries) + { + if (geom == null) continue; + rbginst.Geom = geom; + rbginst.Inst.Position = position + orientation.Multiply(geom.BoundGeom.CenterGeom * scale); + rbginst.Inst.CamRel = rbginst.Inst.Position - camera.Position; + shaders.Enqueue(rbginst); + } + + UpdateMouseHits(rndbc, entity); + } + } + else + { } + break; + case 3: //BoundBox - found in drawables - TODO + BoundBox boundbox = bounds as BoundBox; + if (boundbox == null) + { } + break; + case 0: //BoundSphere - found in drawables - TODO + BoundSphere boundsphere = bounds as BoundSphere; + if (boundsphere == null) + { } + break; + default: + break; + } + } + + + + private void RenderBounds(DeviceContext context) + { + //immediately render the entity bounding boxes/spheres - depending on boundsmode + + + //////rendering grass instance batch bounding boxes... + ////shaders.SetDepthStencilMode(context, renderboundsclip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); + ////var shader = shaders.Bounds; + ////shader.SetMode(BoundsShaderMode.Box); + ////shader.SetShader(context); + ////shader.SetInputLayout(context, VertexType.Default); + ////shader.SetSceneVars(context, camera); + ////shader.SetColourVars(context, new Vector4(0, 0, 1, 1)); + ////for (int i = 0; i < shaders.RenderInstBatches.Count; i++) + ////{ + //// var b = shaders.RenderInstBatches[i]; + //// var bpos = b.Batch.GrassInstanceBatch.Position; + //// var camrel = bpos - camera.Position; + //// var bbmin = b.Batch.GrassInstanceBatch.Batch.BatchAABB.min.XYZ() - bpos; + //// var bbmax = b.Batch.GrassInstanceBatch.Batch.BatchAABB.max.XYZ() - bpos; + //// shader.SetBoxVars(context, camrel, bbmin, bbmax, Quaternion.Identity, Vector3.One); + //// shader.DrawBox(context); + ////} + ////shader.UnbindResources(context); + + + + + var mode = boundsmode; //try avoid multithreading issues + bool clip = renderboundsclip; + + switch (SelectionMode) + { + case MapSelectionMode.EntityExtension: + case MapSelectionMode.ArchetypeExtension: + case MapSelectionMode.TimeCycleModifier: + case MapSelectionMode.CarGenerator: + case MapSelectionMode.DistantLodLights: + case MapSelectionMode.Grass: + case MapSelectionMode.Collision: + case MapSelectionMode.NavMesh: + case MapSelectionMode.Path: + case MapSelectionMode.TrainTrack: + case MapSelectionMode.Scenario: + mode = BoundsShaderMode.Box; + break; + case MapSelectionMode.WaterQuad: + case MapSelectionMode.MloInstance: + mode = BoundsShaderMode.Box; + clip = false; + break; + } + + + if (mode == BoundsShaderMode.None) + { return; } + + Vector3 colour = new Vector3(0, 0, 1); + Vector3 colourhi = new Vector3(0, 1, 1); + colour *= globalLights.HdrIntensity; + colourhi *= globalLights.HdrIntensity; + + shaders.SetDepthStencilMode(context, clip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); + var shader = shaders.Bounds; + shader.SetMode(mode); + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.Default); + shader.SetSceneVars(context, camera, null, globalLights); + shader.SetColourVars(context, new Vector4(colour, 1)); + + + if (mode == BoundsShaderMode.Box) + { + for (int i = 0; i < BoundingBoxes.Count; i++) + { + MapBox mb = BoundingBoxes[i]; + shader.SetBoxVars(context, mb.CamRelPos, mb.BBMin, mb.BBMax, mb.Orientation, mb.Scale); + shader.DrawBox(context); + } + shader.SetColourVars(context, new Vector4(colourhi, 1)); + for (int i = 0; i < HilightBoxes.Count; i++) + { + MapBox mb = HilightBoxes[i]; + shader.SetBoxVars(context, mb.CamRelPos, mb.BBMin, mb.BBMax, mb.Orientation, mb.Scale); + shader.DrawBox(context); + } + } + else if (mode == BoundsShaderMode.Sphere) + { + for (int i = 0; i < BoundingSpheres.Count; i++) + { + MapSphere ms = BoundingSpheres[i]; + shader.SetSphereVars(context, ms.CamRelPos, ms.Radius); + shader.DrawSphere(context); + } + } + + shader.UnbindResources(context); + } + + private void RenderMoused(DeviceContext context) + { + //immediately render the bounding box of the currently moused entity. + + if (!MouseSelectEnabled) + { return; } + + PrevMouseHit = LastMouseHit; + LastMouseHit = CurMouseHit; + + bool change = (LastMouseHit.EntityDef != PrevMouseHit.EntityDef); + if (SelectByGeometry) + { + change = change || (LastMouseHit.Geometry != PrevMouseHit.Geometry); + } + switch (SelectionMode) + { + case MapSelectionMode.EntityExtension: + change = change || (LastMouseHit.EntityExtension != PrevMouseHit.EntityExtension); + break; + case MapSelectionMode.ArchetypeExtension: + change = change || (LastMouseHit.ArchetypeExtension != PrevMouseHit.ArchetypeExtension); + break; + case MapSelectionMode.TimeCycleModifier: + change = change || (LastMouseHit.TimeCycleModifier != PrevMouseHit.TimeCycleModifier); + break; + case MapSelectionMode.CarGenerator: + change = change || (LastMouseHit.CarGenerator != PrevMouseHit.CarGenerator); + break; + case MapSelectionMode.MloInstance: + change = change || (LastMouseHit.MloEntityDef != PrevMouseHit.MloEntityDef); + break; + case MapSelectionMode.DistantLodLights: + change = change || (LastMouseHit.DistantLodLights != PrevMouseHit.DistantLodLights); + break; + case MapSelectionMode.Grass: + change = change || (LastMouseHit.GrassBatch != PrevMouseHit.GrassBatch); + break; + case MapSelectionMode.WaterQuad: + change = change || (LastMouseHit.WaterQuad != PrevMouseHit.WaterQuad); + break; + case MapSelectionMode.Collision: + change = change || (LastMouseHit.CollisionBounds != PrevMouseHit.CollisionBounds); + break; + case MapSelectionMode.NavMesh: + change = change || (LastMouseHit.NavPoly != PrevMouseHit.NavPoly); + break; + case MapSelectionMode.Path: + change = change || (LastMouseHit.PathNode != PrevMouseHit.PathNode); + break; + case MapSelectionMode.TrainTrack: + change = change || (LastMouseHit.TrainTrackNode != PrevMouseHit.TrainTrackNode); + break; + case MapSelectionMode.Scenario: + change = change || (LastMouseHit.ScenarioNode != PrevMouseHit.ScenarioNode); + break; + } + + + if (change) + { + string text = LastMouseHit.GetFullNameString(string.Empty); + UpdateMousedLabel(text); + } + + if(!CurMouseHit.HasHit) + { return; } + + + if (SelectionMode == MapSelectionMode.NavMesh) + { + return;//navmesh mode isn't needing a selection box.. + } + + + Vector3 colour = new Vector3(1, 1, 1); + colour *= globalLights.HdrIntensity * 5.0f; + + bool clip = renderboundsclip; + + Vector3 bbmin = CurMouseHit.AABB.Minimum; + Vector3 bbmax = CurMouseHit.AABB.Maximum; + Vector3 camrel = CurMouseHit.CamRel; + Vector3 scale = Vector3.One; + Quaternion ori = Quaternion.Identity; + bool ext = (CurMouseHit.ArchetypeExtension != null) || (CurMouseHit.EntityExtension != null) || (CurMouseHit.CollisionBounds != null); + if (CurMouseHit.EntityDef != null) + { + scale = ext ? Vector3.One : CurMouseHit.EntityDef.Scale; + ori = CurMouseHit.EntityDef.Orientation; + } + if (CurMouseHit.Archetype != null) + { + bbmin = CurMouseHit.Archetype.BBMin; + bbmax = CurMouseHit.Archetype.BBMax; + } + if ((CurMouseHit.Geometry != null) || ext) + { + bbmin = CurMouseHit.AABB.Minimum; //override archetype AABB.. + bbmax = CurMouseHit.AABB.Maximum; + } + if (CurMouseHit.CarGenerator != null) + { + ori = CurMouseHit.CarGenerator.Orientation; + } + if (CurMouseHit.MloEntityDef != null) + { + scale = Vector3.One; + clip = false; + } + if (CurMouseHit.WaterQuad != null) + { + clip = false; + } + if (CurMouseHit.ScenarioNode != null) + { + var sp = CurMouseHit.ScenarioNode.MyPoint; + if (sp == null) sp = CurMouseHit.ScenarioNode.ClusterMyPoint; + if (sp != null) //orientate the moused box for the correct scenario point direction... + { + ori = sp.Orientation; + } + } + + + shaders.SetDepthStencilMode(context, clip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); + + //render moused object box. + var shader = shaders.Bounds; + shader.SetMode(BoundsShaderMode.Box); + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.Default); + shader.SetSceneVars(context, camera, null, globalLights); + shader.SetColourVars(context, new Vector4(colour, 1)); //white box + + shader.SetBoxVars(context, camrel, bbmin, bbmax, ori, scale); + shader.DrawBox(context); + + shader.UnbindResources(context); + + } + + private void RenderSelection(DeviceContext context) + { + //immediately render the bounding box of the currently selection. also, arrows. + + const uint cgrn = 4278255360;// (uint)new Color4(0.0f, 1.0f, 0.0f, 1.0f).ToRgba(); + const uint cblu = 4294901760;// (uint)new Color4(0.0f, 0.0f, 1.0f, 1.0f).ToRgba(); + + if (MouseRayCollisionEnabled && MouseRayCollisionVisible) + { + if (MouseRayCollision.Hit) + { + var arup = GetPerpVec(MouseRayCollision.Normal); + RenderSelectionArrowOutline(MouseRayCollision.Position, MouseRayCollision.Normal, arup, Quaternion.Identity, 2.0f, 0.15f, cgrn); + } + } + + if (!ShowSelectionBounds) + { return; } + + if (!SelectedItem.HasValue) + { return; } + + + Vector3 colour = new Vector3(0, 1, 0); + colour *= globalLights.HdrIntensity * 5.0f; + + + bool clip = renderboundsclip; + + + Vector3 bbmin = SelectedItem.AABB.Minimum; + Vector3 bbmax = SelectedItem.AABB.Maximum; + Vector3 camrel = -camera.Position; + Vector3 scale = Vector3.One; + Quaternion ori = Quaternion.Identity; + + + var arch = SelectedItem.Archetype; + var ent = SelectedItem.EntityDef; + if (SelectedItem.Archetype != null) + { + bbmin = SelectedItem.Archetype.BBMin; + bbmax = SelectedItem.Archetype.BBMax; + } + if (SelectedItem.EntityDef != null) + { + camrel = ent.Position - camera.Position; + scale = ent.Scale; + ori = ent.Orientation; + + if (EditEntityPivot) + { + RenderSelectionEntityPivot(ent); + } + } + if (SelectedItem.CarGenerator != null) + { + var cg = SelectedItem.CarGenerator; + camrel = cg.Position - camera.Position; + ori = cg.Orientation; + bbmin = cg.BBMin; + bbmax = cg.BBMax; + float arrowlen = cg._CCarGen.perpendicularLength; + float arrowrad = arrowlen * 0.066f; + RenderSelectionArrowOutline(cg.Position, Vector3.UnitX, Vector3.UnitY, ori, arrowlen, arrowrad, cgrn); + } + if (SelectedItem.PathNode != null) + { + camrel = SelectedItem.PathNode.Position - camera.Position; + } + if (SelectedItem.TrainTrackNode != null) + { + camrel = SelectedItem.TrainTrackNode.Position - camera.Position; + } + if (SelectedItem.ScenarioNode != null) + { + camrel = SelectedItem.ScenarioNode.Position - camera.Position; + + var sn = SelectedItem.ScenarioNode; + + //render direction arrow for ScenarioPoint + ori = sn.Orientation; + float arrowlen = 2.0f; + float arrowrad = 0.25f; + RenderSelectionArrowOutline(sn.Position, Vector3.UnitY, Vector3.UnitZ, ori, arrowlen, arrowrad, cgrn); + + } + if (SelectedItem.ScenarioEdge != null) + { + //render scenario edge arrow + var se = SelectedItem.ScenarioEdge; + var sn1 = se.NodeFrom; + var sn2 = se.NodeTo; + if ((sn1 != null) && (sn2 != null)) + { + var dirp = sn2.Position - sn1.Position; + float dl = dirp.Length(); + Vector3 dir = dirp * (1.0f / dl); + Vector3 dup = Vector3.UnitZ; + var aori = Quaternion.Invert(Quaternion.RotationLookAtRH(dir, dup)); + float arrowrad = 0.25f; + float arrowlen = Math.Max(dl - arrowrad*5.0f, 0); + RenderSelectionArrowOutline(sn1.Position, -Vector3.UnitZ, Vector3.UnitY, aori, arrowlen, arrowrad, cblu); + } + } + if (SelectedItem.MloEntityDef != null) + { + bbmin = SelectedItem.AABB.Minimum; + bbmax = SelectedItem.AABB.Maximum; + clip = false; + } + if ((SelectedItem.GrassBatch != null) || (SelectedItem.ArchetypeExtension != null) || (SelectedItem.EntityExtension != null) || (SelectedItem.CollisionBounds != null)) + { + bbmin = SelectedItem.AABB.Minimum; + bbmax = SelectedItem.AABB.Maximum; + scale = Vector3.One; + } + if (SelectedItem.WaterQuad != null) + { + clip = false; + } + if (SelectedItem.NavPoly != null) + { + RenderSelectionNavPoly(SelectedItem.NavPoly); + + //return;//don't render a selection box for nav mesh + //clip = false; + } + + + + + shaders.SetDepthStencilMode(context, clip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); + + //render selected object box... + var shader = shaders.Bounds; + shader.SetMode(BoundsShaderMode.Box); + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.Default); + shader.SetSceneVars(context, camera, null, globalLights); + shader.SetColourVars(context, new Vector4(colour, 1)); + + shader.SetBoxVars(context, camrel, bbmin, bbmax, ori, scale); + shader.DrawBox(context); + + shader.UnbindResources(context); + + } + + private void RenderSelectionEntityPivot(YmapEntityDef ent) + { + uint cred = (uint)new Color4(1.0f, 0.0f, 0.0f, 1.0f).ToRgba(); + uint cgrn = (uint)new Color4(0.0f, 1.0f, 0.0f, 1.0f).ToRgba(); + uint cblu = (uint)new Color4(0.0f, 0.0f, 1.0f, 1.0f).ToRgba(); + + var pos = ent.WidgetPosition; + var ori = ent.WidgetOrientation; + + float pxsize = 120.0f; + float sssize = pxsize / camera.Height; + float dist = (pos - camera.Position).Length(); + float size = sssize * dist; + if (camera.IsMapView || camera.IsOrthographic) + { + size = sssize * camera.OrthographicSize; + } + float rad = size * 0.066f; + + RenderSelectionArrowOutline(pos, Vector3.UnitX, Vector3.UnitY, ori, size, rad, cred); + RenderSelectionArrowOutline(pos, Vector3.UnitY, Vector3.UnitX, ori, size, rad, cgrn); + RenderSelectionArrowOutline(pos, Vector3.UnitZ, Vector3.UnitY, ori, size, rad, cblu); + + } + + private void RenderSelectionArrowOutline(Vector3 pos, Vector3 dir, Vector3 up, Quaternion ori, float len, float rad, uint colour) + { + Vector3 ax = Vector3.Cross(dir, up); + Vector3 sx = ax * rad; + Vector3 sy = up * rad; + Vector3 sz = dir * len; + VertexTypePC[] c = new VertexTypePC[8]; + Vector3 d0 = - sx - sy; + Vector3 d1 = - sx + sy; + Vector3 d2 = + sx - sy; + Vector3 d3 = + sx + sy; + c[0].Position = d0; + c[1].Position = d1; + c[2].Position = d2; + c[3].Position = d3; + c[4].Position = d0 + sz; + c[5].Position = d1 + sz; + c[6].Position = d2 + sz; + c[7].Position = d3 + sz; + for (int i = 0; i < 8; i++) + { + c[i].Colour = colour; + c[i].Position = pos + ori.Multiply(c[i].Position); + } + + SelectionLineVerts.Add(c[0]); + SelectionLineVerts.Add(c[1]); + SelectionLineVerts.Add(c[1]); + SelectionLineVerts.Add(c[3]); + SelectionLineVerts.Add(c[3]); + SelectionLineVerts.Add(c[2]); + SelectionLineVerts.Add(c[2]); + SelectionLineVerts.Add(c[0]); + SelectionLineVerts.Add(c[4]); + SelectionLineVerts.Add(c[5]); + SelectionLineVerts.Add(c[5]); + SelectionLineVerts.Add(c[7]); + SelectionLineVerts.Add(c[7]); + SelectionLineVerts.Add(c[6]); + SelectionLineVerts.Add(c[6]); + SelectionLineVerts.Add(c[4]); + SelectionLineVerts.Add(c[0]); + SelectionLineVerts.Add(c[4]); + SelectionLineVerts.Add(c[1]); + SelectionLineVerts.Add(c[5]); + SelectionLineVerts.Add(c[2]); + SelectionLineVerts.Add(c[6]); + SelectionLineVerts.Add(c[3]); + SelectionLineVerts.Add(c[7]); + + c[0].Position = pos + ori.Multiply(dir * (len + rad * 5.0f)); + c[4].Position += ori.Multiply(d0); + c[5].Position += ori.Multiply(d1); + c[6].Position += ori.Multiply(d2); + c[7].Position += ori.Multiply(d3); + SelectionLineVerts.Add(c[4]); + SelectionLineVerts.Add(c[5]); + SelectionLineVerts.Add(c[5]); + SelectionLineVerts.Add(c[7]); + SelectionLineVerts.Add(c[7]); + SelectionLineVerts.Add(c[6]); + SelectionLineVerts.Add(c[6]); + SelectionLineVerts.Add(c[4]); + SelectionLineVerts.Add(c[0]); + SelectionLineVerts.Add(c[4]); + SelectionLineVerts.Add(c[0]); + SelectionLineVerts.Add(c[5]); + SelectionLineVerts.Add(c[0]); + SelectionLineVerts.Add(c[6]); + SelectionLineVerts.Add(c[0]); + SelectionLineVerts.Add(c[7]); + + + } + + private void RenderSelectionNavPoly(YnvPoly poly) + { + ////draw poly triangles + var pcolour = new Color4(0.6f, 0.95f, 0.6f, 1.0f); + var colourval = (uint)pcolour.ToRgba(); + var ynv = poly.Ynv; + var ic = poly._RawData.IndexCount; + var startid = poly._RawData.IndexID; + var endid = startid + ic; + var lastid = endid - 1; + var vc = ynv.Vertices.Count; + var startind = ynv.Indices[startid]; + VertexTypePC v0 = new VertexTypePC(); + VertexTypePC v1 = new VertexTypePC(); + VertexTypePC v2 = new VertexTypePC(); + v0.Position = ynv.Vertices[startind]; + v0.Colour = colourval; + v1.Colour = colourval; + v2.Colour = colourval; + int tricount = ic - 2; + for (int t = 0; t < tricount; t++) + { + int tid = startid + t; + int ind1 = ynv.Indices[tid + 1]; + int ind2 = ynv.Indices[tid + 2]; + if ((ind1 >= vc) || (ind2 >= vc)) + { continue; } + v1.Position = ynv.Vertices[ind1]; + v2.Position = ynv.Vertices[ind2]; + SelectionTriVerts.Add(v0); + SelectionTriVerts.Add(v1); + SelectionTriVerts.Add(v2); + SelectionTriVerts.Add(v0); + SelectionTriVerts.Add(v2); + SelectionTriVerts.Add(v1); + } + } + + private void RenderSelectionGeometry(DeviceContext context) + { + + bool clip = true; + if (SelectionMode == MapSelectionMode.NavMesh) + { + clip = false; + } + + + shaders.SetDepthStencilMode(context, clip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); + + var pshader = shaders.Paths; + if (SelectionTriVerts.Count > 0) + { + pshader.RenderTriangles(context, SelectionTriVerts, camera, shaders.GlobalLights); + } + if (SelectionLineVerts.Count > 0) + { + pshader.RenderLines(context, SelectionLineVerts, camera, shaders.GlobalLights); + } + + } + + + private void RenderMarkers(DeviceContext context) + { + //immediately render all the current markers. + + lock (markersyncroot) //should only cause delays if markers moved/updated + { + foreach (var marker in Markers) + { + marker.CamRelPos = marker.WorldPos - camera.Position; + marker.Distance = marker.CamRelPos.Length(); + marker.ScreenPos = camera.ViewProjMatrix.MultiplyW(marker.CamRelPos); + } + + lock (markersortedsyncroot) //stop collisions with mouse testing + { + SortedMarkers.Clear(); + SortedMarkers.AddRange(Markers); + if (RenderLocator) + { + LocatorMarker.CamRelPos = LocatorMarker.WorldPos - camera.Position; + LocatorMarker.Distance = LocatorMarker.CamRelPos.Length(); + LocatorMarker.ScreenPos = camera.ViewProjMatrix.MultiplyW(LocatorMarker.CamRelPos); + SortedMarkers.Add(LocatorMarker); + } + SortedMarkers.Sort((m1, m2) => m2.Distance.CompareTo(m1.Distance)); + } + + MarkerBatch.Clear(); + MarkerBatch.AddRange(SortedMarkers); + } + + shaders.SetRasterizerMode(context, RasterizerMode.SolidDblSided); //hmm they are backwards + shaders.SetDepthStencilMode(context, markerdepthclip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); + shaders.SetDefaultBlendState(context); + + var shader = shaders.Marker; + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.Default); + shader.SetSceneVars(context, camera, null, globalLights); + + MapIcon icon = null; + foreach (var marker in MarkerBatch) + { + icon = marker.Icon; + Vector2 texs = new Vector2(icon.TexWidth, icon.TexHeight); + Vector2 size = texs * marker.Distance; + Vector2 offset = (new Vector2(texs.X, -texs.Y) - new Vector2(icon.Center.X, -icon.Center.Y) * 2.0f) * marker.Distance; + shader.SetMarkerVars(context, marker.CamRelPos, size, offset); + shader.SetTexture(context, icon.TexView); + markerquad.Draw(context); + } + + shader.UnbindResources(context); + } + + + private void RenderWidgets(DeviceContext context) + { + if (!ShowWidget) return; + + + var dsmode = DepthStencilMode.Enabled; + if (Widget.Mode == WidgetMode.Rotation) + { + dsmode = DepthStencilMode.DisableAll; + } + + shaders.SetRasterizerMode(context, RasterizerMode.SolidDblSided); + shaders.SetDepthStencilMode(context, dsmode); + shaders.SetDefaultBlendState(context); + shaders.ClearDepth(context, false); + + var shader = shaders.Widgets; + + Widget.Render(context, camera, shader); + + } + private void UpdateWidgets() + { + if (!ShowWidget) return; + + Widget.Update(camera); + } + + private void Widget_OnPositionChange(Vector3 newpos, Vector3 oldpos) + { + //called during UpdateWidgets() + if (newpos == oldpos) return; + + if (SelectedItem.EntityDef != null) + { + if (EditEntityPivot) + { + SelectedItem.EntityDef.SetPivotPositionFromWidget(newpos); + } + else + { + SelectedItem.EntityDef.SetPositionFromWidget(newpos); + } + + if (ProjectForm != null) + { + ProjectForm.OnWorldEntityModified(SelectedItem.EntityDef); + } + } + else if (SelectedItem.CarGenerator != null) + { + SelectedItem.CarGenerator.SetPosition(newpos); + + if (ProjectForm != null) + { + ProjectForm.OnWorldCarGenModified(SelectedItem.CarGenerator); + } + } + else if (SelectedItem.PathNode != null) + { + SelectedItem.PathNode.SetPosition(newpos); + + if (ProjectForm != null) + { + ProjectForm.OnWorldPathNodeModified(SelectedItem.PathNode, SelectedItem.PathLink); + } + } + else if (SelectedItem.NavPoly != null) + { + //SelectedItem.NavPoly.SetPosition(newpos); + + //if (ProjectForm != null) + //{ + // ProjectForm.OnWorldNavPolyModified(SelectedItem.NavPoly); + //} + } + else if (SelectedItem.TrainTrackNode != null) + { + SelectedItem.TrainTrackNode.SetPosition(newpos); + + if (ProjectForm != null) + { + ProjectForm.OnWorldTrainNodeModified(SelectedItem.TrainTrackNode); + } + } + else if (SelectedItem.ScenarioNode != null) + { + SelectedItem.ScenarioNode.SetPosition(newpos); + + if (ProjectForm != null) + { + ProjectForm.OnWorldScenarioNodeModified(SelectedItem.ScenarioNode); + } + } + + } + private void Widget_OnRotationChange(Quaternion newrot, Quaternion oldrot) + { + if (newrot == oldrot) return; + + if (SelectedItem.EntityDef != null) + { + if (EditEntityPivot) + { + SelectedItem.EntityDef.SetPivotOrientationFromWidget(newrot); + } + else + { + SelectedItem.EntityDef.SetOrientationFromWidget(newrot); + } + + if (ProjectForm != null) + { + ProjectForm.OnWorldEntityModified(SelectedItem.EntityDef); + } + } + else if (SelectedItem.CarGenerator != null) + { + SelectedItem.CarGenerator.SetOrientation(newrot); + + if (ProjectForm != null) + { + ProjectForm.OnWorldCarGenModified(SelectedItem.CarGenerator); + } + } + else if (SelectedItem.ScenarioNode != null) + { + SelectedItem.ScenarioNode.SetOrientation(newrot); + + if (ProjectForm != null) + { + ProjectForm.OnWorldScenarioNodeModified(SelectedItem.ScenarioNode); + } + } + } + private void Widget_OnScaleChange(Vector3 newscale, Vector3 oldscale) + { + if (newscale == oldscale) return; + + if (SelectedItem.EntityDef != null) + { + SelectedItem.EntityDef.SetScale(newscale); + + if (ProjectForm != null) + { + ProjectForm.OnWorldEntityModified(SelectedItem.EntityDef); + } + } + else if (SelectedItem.CarGenerator != null) + { + SelectedItem.CarGenerator.SetScale(newscale); + SelectedItem.AABB = new BoundingBox(SelectedItem.CarGenerator.BBMin, SelectedItem.CarGenerator.BBMax); + + if (ProjectForm != null) + { + ProjectForm.OnWorldCarGenModified(SelectedItem.CarGenerator); + } + } + } + + public void SetWidgetPosition(Vector3 pos, bool enableUndo = false) + { + if (enableUndo) + { + SetWidgetMode("Position"); + MarkUndoStart(Widget); + } + + Widget.Position = pos; + + if (enableUndo) + { + MarkUndoEnd(Widget); + } + } + public void SetWidgetRotation(Quaternion q, bool enableUndo = false) + { + if (enableUndo) + { + SetWidgetMode("Rotation"); + MarkUndoStart(Widget); + } + + Widget.Rotation = q; + + if (enableUndo) + { + MarkUndoEnd(Widget); + } + } + public void SetWidgetScale(Vector3 s, bool enableUndo = false) + { + if (enableUndo) + { + SetWidgetMode("Scale"); + MarkUndoStart(Widget); + } + + Widget.Scale = s; + + if (enableUndo) + { + MarkUndoEnd(Widget); + } + } + + + public void UpdatePathYndGraphics(YndFile ynd, bool fullupdate) + { + if (fullupdate) + { + space.BuildYndData(ynd); + } + else + { + space.BuildYndVerts(ynd); + } + lock (rendersyncroot) + { + renderableCache.Invalidate(ynd); + } + } + public void UpdatePathNodeGraphics(YndNode pathnode, bool fullupdate) + { + if (pathnode == null) return; + pathnode.Ynd.UpdateBvhForNode(pathnode); + UpdatePathYndGraphics(pathnode.Ynd, fullupdate); + } + public YndNode GetPathNodeFromSpace(ushort areaid, ushort nodeid) + { + return space.NodeGrid.GetYndNode(areaid, nodeid); + } + + public void UpdateNavYnvGraphics(YnvFile ynv, bool fullupdate)//TODO! + { + } + public void UpdateNavPolyGraphics(YnvPoly poly, bool fullupdate)//TODO! + { + } + + public void UpdateTrainTrackGraphics(TrainTrack tt, bool fullupdate) + { + tt.BuildVertices(); + //if (fullupdate) + //{ + // //space.BuildYndData(ynd); + //} + //else + //{ + // //space.BuildYndVerts(ynd); + //} + lock (rendersyncroot) + { + renderableCache.Invalidate(tt); + } + } + public void UpdateTrainTrackNodeGraphics(TrainTrackNode node, bool fullupdate) + { + if (node == null) return; + node.Track.UpdateBvhForNode(node); + UpdateTrainTrackGraphics(node.Track, fullupdate); + } + + public void UpdateScenarioGraphics(YmtFile ymt, bool fullupdate) + { + var scenario = ymt.ScenarioRegion; + if (scenario == null) return; + + scenario.BuildBVH(); + + scenario.BuildVertices(); + + lock (rendersyncroot) + { + renderableCache.Invalidate(scenario); + } + } + + + public Vector3 GetCameraPosition() + { + //currently used by ProjectForm when creating entities + lock (rendersyncroot) + { + return camera.Position; + } + } + public Vector3 GetCameraViewDir() + { + //currently used by ProjectForm when creating entities + lock (rendersyncroot) + { + return camera.ViewDirection; + } + } + + public void SetCameraSensitivity(float sensitivity, float smoothing) + { + camera.Sensitivity = sensitivity; + camera.Smoothness = smoothing; + } + + public void SetKeyBindings(KeyBindings kb) + { + keyBindings = kb.Copy(); + UpdateToolbarShortcutsText(); + } + private void UpdateToolbarShortcutsText() + { + ToolbarSelectButton.ToolTipText = string.Format("Select objects / Exit edit mode ({0}, {1})", keyBindings.ToggleMouseSelect, keyBindings.ExitEditMode); + ToolbarMoveButton.ToolTipText = string.Format("Move ({0})", keyBindings.EditPosition); + ToolbarRotateButton.ToolTipText = string.Format("Rotate ({0})", keyBindings.EditRotation); + ToolbarScaleButton.ToolTipText = string.Format("Scale ({0})", keyBindings.EditScale); + ShowToolbarCheckBox.Text = string.Format("Show Toolbar ({0})", keyBindings.ToggleToolbar); + } + + + private MapBox GetExtensionBox(Vector3 camrel, MetaWrapper ext) + { + MapBox b = new MapBox(); + Vector3 pos = Vector3.Zero; + float size = 0.5f; + if (ext is MCExtensionDefLightEffect) + { + var le = ext as MCExtensionDefLightEffect; + pos = le.Data.offsetPosition; + } + else if (ext is MCExtensionDefSpawnPointOverride) + { + var spo = ext as MCExtensionDefSpawnPointOverride; + pos = spo.Data.offsetPosition; + size = spo.Data.Radius; + } + else if (ext is MCExtensionDefDoor) + { + var door = ext as MCExtensionDefDoor; + pos = door.Data.offsetPosition; + } + else if (ext is Mrage__phVerletClothCustomBounds) + { + var cb = ext as Mrage__phVerletClothCustomBounds; + if ((cb.CollisionData != null) && (cb.CollisionData.Length > 0)) + { + pos = cb.CollisionData[0].Data.Position; + } + } + else if (ext is MCExtensionDefParticleEffect) + { + var pe = ext as MCExtensionDefParticleEffect; + pos = pe.Data.offsetPosition; + } + else if (ext is MCExtensionDefAudioCollisionSettings) + { + var acs = ext as MCExtensionDefAudioCollisionSettings; + pos = acs.Data.offsetPosition; + } + else if (ext is MCExtensionDefAudioEmitter) + { + var ae = ext as MCExtensionDefAudioEmitter; + pos = ae.Data.offsetPosition; + } + else if (ext is MCExtensionDefSpawnPoint) + { + var sp = ext as MCExtensionDefSpawnPoint; + pos = sp.Data.offsetPosition; + } + else if (ext is MCExtensionDefExplosionEffect) + { + var ee = ext as MCExtensionDefExplosionEffect; + pos = ee.Data.offsetPosition; + } + else if (ext is MCExtensionDefLadder) + { + var ld = ext as MCExtensionDefLadder; + pos = ld.Data.offsetPosition; + } + else if (ext is MCExtensionDefBuoyancy) + { + var bu = ext as MCExtensionDefBuoyancy; + pos = bu.Data.offsetPosition; + } + else if (ext is MCExtensionDefExpression) + { + var exp = ext as MCExtensionDefExpression; + pos = exp.Data.offsetPosition; + } + else if (ext is MCExtensionDefLightShaft) + { + var ls = ext as MCExtensionDefLightShaft; + pos = ls.Data.offsetPosition; + } + else if (ext is MCExtensionDefWindDisturbance) + { + var wd = ext as MCExtensionDefWindDisturbance; + pos = wd.Data.offsetPosition; + } + else if (ext is MCExtensionDefProcObject) + { + var po = ext as MCExtensionDefProcObject; + pos = po.Data.offsetPosition; + } + + + b.BBMin = pos - size; + b.BBMax = pos + size; + b.CamRelPos = camrel; + + return b; + } + + + public static Vector3 GetPerpVec(Vector3 n) + { + //make a vector perpendicular to the given one + float nx = Math.Abs(n.X); + float ny = Math.Abs(n.Y); + float nz = Math.Abs(n.Z); + if ((nx < ny) && (nx < nz)) + { + return Vector3.Cross(n, Vector3.Right); + } + else if (ny < nz) + { + return Vector3.Cross(n, Vector3.Up); + } + else + { + return Vector3.Cross(n, Vector3.ForwardLH); + } + } + + + private void SpawnTestEntity(bool cameraCenter = false) + { + if (!space.Inited) return; + + Vector3 dir = (cameraCenter ? camera.ViewDirection : camera.MouseRay.Direction); + Vector3 ofs = (cameraCenter ? Vector3.Zero : camera.MouseRay.Position); + Vector3 pos = ofs + camera.Position + (dir * 1.5f); + Vector3 vel = dir * 50.0f; //m/s + + var hash = JenkHash.GenHash("prop_alien_egg_01"); + var arch = GameFileCache.GetArchetype(hash); + + if (arch == null) return; + + CEntityDef cent = new CEntityDef(); + cent.archetypeName = hash; + cent.rotation = new Vector4(0, 0, 0, 1); + cent.scaleXY = 1.0f; + cent.scaleZ = 1.0f; + cent.flags = 1572872; + cent.parentIndex = -1; + cent.lodDist = 200.0f; + cent.lodLevel = Unk_1264241711.LODTYPES_DEPTH_ORPHANHD; + cent.priorityLevel = Unk_648413703.PRI_REQUIRED; + cent.ambientOcclusionMultiplier = 255; + cent.artificialAmbientOcclusion = 255; + cent.position = pos; + + YmapEntityDef ent = new YmapEntityDef(null, 0, ref cent); + + ent.SetArchetype(arch); + + + Entity e = new Entity(); + e.Position = pos; + e.Velocity = vel; + e.Mass = 10.0f; + e.Momentum = vel * e.Mass; + e.EntityDef = ent; + e.Radius = arch.BSRadius * 0.7f; + e.EnableCollisions = true; + e.Enabled = true; + + lock (rendersyncroot) + { + space.AddTemporaryEntity(e); + } + } + + + + public void SetControlMode(WorldControlMode mode) + { + if (InvokeRequired) + { + try + { + Invoke(new Action(() => { SetControlMode(mode); })); + } + catch + { } + return; + } + + if (mode == ControlMode) return; + + bool wasfree = (ControlMode == WorldControlMode.Free); + bool isfree = (mode == WorldControlMode.Free); + + if (isfree && !wasfree) + { + camEntity.Position = pedEntity.Position; + + pedEntity.Enabled = false; + + timerunning = false; + + camera.SetFollowEntity(camEntity); + camera.TargetDistance = 1.0f; //default? + camera.Smoothness = Settings.Default.CameraSmoothing; + + Cursor.Show(); + } + else if (!isfree && wasfree) + { + pedEntity.Position = camEntity.Position; + pedEntity.Velocity = Vector3.Zero; + pedEntity.Enabled = true; + + timerunning = true; + + camera.SetFollowEntity(pedEntity.CameraEntity); + camera.TargetDistance = 0.01f; //1cm + camera.Smoothness = 20.0f; + + //center the mouse in the window + System.Drawing.Point centerp = new System.Drawing.Point(ClientSize.Width / 2, ClientSize.Height / 2); + MouseLastPoint = centerp; + MouseX = centerp.X; + MouseY = centerp.Y; + Cursor.Position = PointToScreen(centerp); + Cursor.Hide(); + } + + + + + ControlMode = mode; + + } + + + + + + + private void BeginMouseHitTest() + { + //reset variables for beginning the mouse hit test + CurMouseHit.Clear(); + + SelectionLineVerts.Clear(); + SelectionTriVerts.Clear(); + + + MouseRayCollisionEnabled = CtrlPressed; //temporary...! + if (MouseRayCollisionEnabled) + { + if (space.Inited && space.Grid != null) + { + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + MouseRayCollision = space.RayIntersect(mray); + } + } + + } + private void UpdateMouseHit(Renderable rndbl, Archetype arche, YmapEntityDef entity, Vector3 camrel) + { + if ((SelectionMode == MapSelectionMode.Entity) && !MouseSelectEnabled) return; //performance improvement when not selecting entities... + + //test the selected entity/archetype for mouse hit. + + //first test the bounding sphere for mouse hit.. + Quaternion orinv; + Ray mraytrn; + float hitdist = 0.0f; + var drawable = rndbl.Key; + int geometryIndex = 0; + DrawableGeometry geometry = null; + BoundingBox geometryAABB = new BoundingBox(); + BoundingSphere bsph = new BoundingSphere(); + BoundingBox bbox = new BoundingBox(); + BoundingBox gbbox = new BoundingBox(); + Quaternion orientation = Quaternion.Identity; + Vector3 scale = Vector3.One; + if (entity != null) + { + orientation = entity.Orientation; + scale = entity.Scale; + } + if (arche != null) + { + bsph.Center = camrel + orientation.Multiply(arche.BSCenter);//could use entity.BSCenter + bsph.Radius = arche.BSRadius; + bbox.Minimum = arche.BBMin * scale; + bbox.Maximum = arche.BBMax * scale; + } + else + { + bsph.Center = camrel + drawable.BoundingCenter; + bsph.Radius = drawable.BoundingSphereRadius; + bbox.Minimum = drawable.BoundingBoxMin.XYZ() * scale; + bbox.Maximum = drawable.BoundingBoxMax.XYZ() * scale; + } + bool mousespherehit = camera.MouseRay.Intersects(ref bsph); + + + + if ((SelectionMode == MapSelectionMode.EntityExtension) || (SelectionMode == MapSelectionMode.ArchetypeExtension)) + { + //transform the mouse ray into the entity space. + orinv = Quaternion.Invert(orientation); + mraytrn = new Ray(); + mraytrn.Position = orinv.Multiply(camera.MouseRay.Position-camrel); + mraytrn.Direction = orinv.Multiply(camera.MouseRay.Direction); + + if (SelectionMode == MapSelectionMode.EntityExtension) + { + if ((entity != null) && (entity.Extensions != null)) + { + for (int i = 0; i < entity.Extensions.Length; i++) + { + var extension = entity.Extensions[i]; + MapBox mb = GetExtensionBox(camrel, extension); + mb.Orientation = orientation; + mb.Scale = Vector3.One;// scale; + mb.BBMin *= scale; + mb.BBMax *= scale; + BoundingBoxes.Add(mb); + + bbox.Minimum = mb.BBMin; //TODO: refactor this! + bbox.Maximum = mb.BBMax; + if (mraytrn.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.EntityDef = entity; + CurMouseHit.Archetype = arche; + CurMouseHit.EntityExtension = extension; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = bbox; + } + } + } + return; //only test extensions when in select extension mode... + } + if (SelectionMode == MapSelectionMode.ArchetypeExtension) + { + if ((arche != null) && (arche.Extensions != null)) + { + for (int i = 0; i < arche.Extensions.Length; i++) + { + var extension = arche.Extensions[i]; + MapBox mb = GetExtensionBox(camrel, extension); + mb.Orientation = orientation; + mb.Scale = Vector3.One;// scale; + mb.BBMin *= scale; + mb.BBMax *= scale; + BoundingBoxes.Add(mb); + + bbox.Minimum = mb.BBMin; //TODO: refactor this! + bbox.Maximum = mb.BBMax; + if (mraytrn.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.EntityDef = entity; + CurMouseHit.Archetype = arche; + CurMouseHit.ArchetypeExtension = extension; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = bbox; + } + } + } + return; //only test extensions when in select extension mode... + } + + } + + + + + if (!mousespherehit) + { return; } //no sphere hit, so no entity hit. + + + + bool usegeomboxes = SelectByGeometry; + var dmodels = drawable.DrawableModelsHigh; + if((dmodels==null)||(dmodels.data_items==null)) + { usegeomboxes = false; } + if (usegeomboxes) + { + for (int i = 0; i < dmodels.data_items.Length; i++) + { + var m = dmodels.data_items[i]; + if (m.Unknown_18h_Data == null) + { usegeomboxes = false; break; } + } + } + + + + //transform the mouse ray into the entity space. + orinv = Quaternion.Invert(orientation); + mraytrn = new Ray(); + mraytrn.Position = orinv.Multiply(camera.MouseRay.Position-camrel); + mraytrn.Direction = orinv.Multiply(camera.MouseRay.Direction); + hitdist = 0.0f; + + + if (usegeomboxes) + { + //geometry bounding boxes version + float ghitdist = float.MaxValue; + for (int i = 0; i < dmodels.data_items.Length; i++) + { + var m = dmodels.data_items[i]; + int gbbcount = m.Unknown_18h_Data.Length; + for (int j = 0; j < gbbcount; j++) //first box seems to be whole model + { + var gbox = m.Unknown_18h_Data[j]; + gbbox.Minimum = gbox.Min.XYZ(); + gbbox.Maximum = gbox.Max.XYZ(); + bbox.Minimum = gbbox.Minimum * scale; + bbox.Maximum = gbbox.Maximum * scale; + bool usehit = false; + if (mraytrn.Intersects(ref bbox, out hitdist)) + { + if ((j == 0) && (gbbcount > 1)) continue;//ignore a model hit + //bool firsthit = (mousehit.EntityDef == null); + if (hitdist > 0.0f) //firsthit || //ignore when inside the box + { + bool nearer = ((hitdist < CurMouseHit.HitDist) && (hitdist < ghitdist)); + bool radsm = true; + if (CurMouseHit.Geometry != null) + { + var b1 = (gbbox.Maximum - gbbox.Minimum) * scale; + var b2 = (CurMouseHit.AABB.Maximum - CurMouseHit.AABB.Minimum) * scale; + float r1 = b1.Length() * 0.5f; + float r2 = b2.Length() * 0.5f; + radsm = (r1 < (r2));// * 0.5f)); + } + if ((nearer&&radsm) || radsm) usehit = true; + } + } + else if (j == 0) //no hit on model box + { + break; //don't try this model's geometries + } + if (usehit) + { + int gind = (j > 0) ? j - 1 : 0; + ghitdist = hitdist; + geometry = m.Geometries[gind]; + geometryAABB = gbbox; + geometryIndex = gind; + } + } + } + if (geometry == null) + { + return; //no geometry hit. + } + hitdist = ghitdist; + } + else + { + //archetype/drawable bounding boxes version + bool outerhit = false; + if (mraytrn.Intersects(ref bbox, out hitdist)) //test primary box + { + bool firsthit = (CurMouseHit.EntityDef == null); + if (firsthit || (hitdist > 0.0f)) //ignore when inside the box.. + { + bool nearer = (hitdist < CurMouseHit.HitDist); //closer than the last.. + bool radsm = true; + if ((CurMouseHit.Archetype != null)) //compare hit archetype sizes... + { + //var b1 = (arche.BBMax - arche.BBMin) * scale; + //var b2 = (mousehit.Archetype.BBMax - mousehit.Archetype.BBMin) * scale; + float r1 = arche.BSRadius; + float r2 = CurMouseHit.Archetype.BSRadius; + radsm = (r1 <= (r2));// * 0.5f)); //prefer selecting smaller things + } + if ((nearer&&radsm) || radsm) + { + outerhit = true; + } + } + } + if (!outerhit) + { return; } //no hit. + } + + + + + CurMouseHit.HitDist = (hitdist > 0.0f) ? hitdist : CurMouseHit.HitDist; + CurMouseHit.EntityDef = entity; + CurMouseHit.Archetype = arche; + CurMouseHit.Drawable = drawable; + CurMouseHit.Geometry = geometry; + CurMouseHit.AABB = geometryAABB; + CurMouseHit.GeometryIndex = geometryIndex; + CurMouseHit.CamRel = camrel; + + + + + //go through geometries...? need to use skeleton? + //if (drawable.DrawableModelsHigh == null) + //{ return; } + //if (drawable.DrawableModelsHigh.data_items == null) + //{ return; } + //for (int i = 0; i < drawable.DrawableModelsHigh.data_items.Length; i++) + //{ + // var model = drawable.DrawableModelsHigh.data_items[i]; + // if ((model.Geometries == null) || (model.Geometries.data_items == null)) + // { continue; } + // if ((model.Unknown_18h_Data == null)) + // { continue; } + // int boffset = 0; + // if ((model.Unknown_18h_Data.Length > model.Geometries.data_items.Length)) + // { boffset = 1; } + // for (int j = 0; j < model.Geometries.data_items.Length; j++) + // { + // var geom = model.Geometries.data_items[j]; + // var gbox = model.Unknown_18h_Data[j + boffset]; + // bbox.Minimum = gbox.AABB_Max.XYZ(); + // bbox.Maximum = gbox.AABB_Min.XYZ(); + // if (mraytrn.Intersects(ref bbox, out hitdist)) //test geom box + // { + // bool firsthit = (mousehit.EntityDef == null); + // if (firsthit || (hitdist > 0.0f)) //ignore when inside the box.. + // { + // bool nearer = (hitdist < mousehit.HitDist); //closer than the last.. + // if (nearer) + // { + // mousehit.HitDist = (hitdist > 0.0f) ? hitdist : mousehit.HitDist; + // mousehit.EntityDef = entity; + // mousehit.Archetype = arche; + // mousehit.Drawable = drawable; + // mousehit.CamRel = camrel; + // } + // } + // } + // } + //} + + + //Bounds b = null; + //var dd = drawable as Drawable; + //if (dd != null) + //{ + // b = dd.Bound; + //} + //else + //{ + // var fd = drawable as FragDrawable; + // if (fd != null) + // { + // b = fd.Bound; + // } + //} + //if (b == null) + //{ return; } + //else + //{ } + + + } + private void UpdateMouseHits(YmapFile ymap) + { + //find mouse hits for things like time cycle mods and car generators in ymaps. + + BoundingBox bbox = new BoundingBox(); + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + float hitdist = float.MaxValue; + + if ((SelectionMode == MapSelectionMode.TimeCycleModifier) && (ymap.TimeCycleModifiers != null)) + { + for (int i = 0; i < ymap.TimeCycleModifiers.Length; i++) + { + var tcm = ymap.TimeCycleModifiers[i]; + if ((((tcm.BBMin + tcm.BBMax) * 0.5f) - camera.Position).Length() > renderboundsmaxdist) continue; + //if (!LodDistTest(camera.Position, tcm.BBMin, tcm.BBMax, renderboundsmaxdist)) continue; + + MapBox mb = new MapBox(); + mb.CamRelPos = -camera.Position; + mb.BBMin = tcm.BBMin; + mb.BBMax = tcm.BBMax; + mb.Orientation = Quaternion.Identity; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + + bbox.Minimum = mb.BBMin; + bbox.Maximum = mb.BBMax; + if (mray.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.TimeCycleModifier = tcm; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = bbox; + } + } + } + if ((SelectionMode == MapSelectionMode.CarGenerator) && (ymap.CarGenerators != null)) + { + for (int i = 0; i < ymap.CarGenerators.Length; i++) + { + var cg = ymap.CarGenerators[i]; + MapBox mb = new MapBox(); + mb.CamRelPos = cg.Position - camera.Position; + mb.BBMin = cg.BBMin; + mb.BBMax = cg.BBMax; + mb.Orientation = cg.Orientation; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + + Quaternion orinv = Quaternion.Invert(cg.Orientation); + Ray mraytrn = new Ray(); + mraytrn.Position = orinv.Multiply(camera.MouseRay.Position - mb.CamRelPos); + mraytrn.Direction = orinv.Multiply(mray.Direction); + bbox.Minimum = mb.BBMin; + bbox.Maximum = mb.BBMax; + if (mraytrn.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.CarGenerator = cg; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = bbox; + } + } + } + if ((SelectionMode == MapSelectionMode.MloInstance) && (ymap.CMloInstanceDefs != null)) + { + for (int i = 0; i < ymap.CMloInstanceDefs.Length; i++) + { + var ent = (i < ymap.AllEntities.Length) ? ymap.AllEntities[i] : null; + var mlo = ymap.CMloInstanceDefs[i]; + MapBox mb = new MapBox(); + mb.CamRelPos = mlo.CEntityDef.position - camera.Position; + mb.BBMin = /*ent?.BBMin ??*/ new Vector3(-1.5f); + mb.BBMax = /*ent?.BBMax ??*/ new Vector3(1.5f); + mb.Orientation = ent?.Orientation ?? Quaternion.Identity; + mb.Scale = /*ent?.Scale ??*/ Vector3.One; + BoundingBoxes.Add(mb); + + Quaternion orinv = Quaternion.Invert(mb.Orientation); + Ray mraytrn = new Ray(); + mraytrn.Position = orinv.Multiply(camera.MouseRay.Position - mb.CamRelPos); + mraytrn.Direction = orinv.Multiply(mray.Direction); + bbox.Minimum = mb.BBMin; + bbox.Maximum = mb.BBMax; + if (mraytrn.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.MloEntityDef = ent; + CurMouseHit.EntityDef = ent; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = new BoundingBox(mb.BBMin, mb.BBMax); + } + } + } + if ((SelectionMode == MapSelectionMode.Grass) && (ymap.GrassInstanceBatches != null)) + { + for (int i = 0; i < ymap.GrassInstanceBatches.Length; i++) + { + var gb = ymap.GrassInstanceBatches[i]; + if ((gb.Position - camera.Position).Length() > renderboundsmaxdist) continue; + //if (!LodDistTest(camera.Position, gb.AABBMin, gb.AABBMax, renderboundsmaxdist)) continue; + + MapBox mb = new MapBox(); + mb.CamRelPos = -camera.Position; + mb.BBMin = gb.AABBMin; + mb.BBMax = gb.AABBMax; + mb.Orientation = Quaternion.Identity; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + + bbox.Minimum = mb.BBMin; + bbox.Maximum = mb.BBMax; + if (mray.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.GrassBatch = gb; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = bbox; + } + } + } + if ((SelectionMode == MapSelectionMode.DistantLodLights) && (ymap.DistantLODLights != null)) + { + var dll = ymap.DistantLODLights; + if ((((dll.BBMin + dll.BBMax) * 0.5f) - camera.Position).Length() <= renderboundsmaxdist) + //if (LodDistTest(camera.Position, dll.BBMin, dll.BBMax, renderboundsmaxdist)) + { + MapBox mb = new MapBox(); + mb.CamRelPos = -camera.Position; + mb.BBMin = dll.BBMin; + mb.BBMax = dll.BBMax; + mb.Orientation = Quaternion.Identity; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + + bbox.Minimum = mb.BBMin; + bbox.Maximum = mb.BBMax; + if (mray.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.DistantLodLights = dll; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = bbox; + } + } + } + + + } + private void UpdateMouseHits(List waterquads) + { + if (SelectionMode != MapSelectionMode.WaterQuad) return; + + BoundingBox bbox = new BoundingBox(); + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + float hitdist = float.MaxValue; + + + foreach (var quad in waterquads) + { + MapBox mb = new MapBox(); + mb.CamRelPos = -camera.Position; + mb.BBMin = new Vector3(quad.minX, quad.minY, quad.z); + mb.BBMax = new Vector3(quad.maxX, quad.maxY, quad.z); + mb.Orientation = Quaternion.Identity; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + + bbox.Minimum = mb.BBMin; + bbox.Maximum = mb.BBMax; + if (mray.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.WaterQuad = quad; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = bbox; + } + } + } + private void UpdateMouseHits(RenderableBoundComposite rndbc, YmapEntityDef entity) + { + if (SelectionMode != MapSelectionMode.Collision) return; + + var position = entity?.Position ?? Vector3.Zero; + var orientation = entity?.Orientation ?? Quaternion.Identity; + var scale = entity?.Scale ?? Vector3.One; + + var camrel = position - camera.Position; + + + + BoundingBox bbox = new BoundingBox(); + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + float hitdist = float.MaxValue; + Quaternion orinv = Quaternion.Invert(orientation); + Ray mraytrn = new Ray(); + mraytrn.Position = orinv.Multiply(camera.MouseRay.Position - camrel); + mraytrn.Direction = orinv.Multiply(mray.Direction); + + MapBox mb = new MapBox(); + mb.CamRelPos = camrel;// rbginst.Inst.CamRel; + mb.Orientation = orientation; + mb.Scale = scale; + + foreach (var geom in rndbc.Geometries) + { + if (geom == null) continue; + + mb.BBMin = geom.BoundGeom.BoundingBoxMin; + mb.BBMax = geom.BoundGeom.BoundingBoxMax; + + var cent = camrel + (mb.BBMin + mb.BBMax) * 0.5f; + if (cent.Length() > renderboundsmaxdist) continue; + + BoundingBoxes.Add(mb); + + bbox.Minimum = mb.BBMin * scale; + bbox.Maximum = mb.BBMax * scale; + if (mraytrn.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.CollisionBounds = geom.BoundGeom; + CurMouseHit.EntityDef = entity; + CurMouseHit.Archetype = entity?.Archetype; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = camrel; + CurMouseHit.AABB = bbox; + } + } + + } + private void UpdateMouseHits(List ynvs) + { + if (SelectionMode != MapSelectionMode.NavMesh) return; + + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + + foreach (var ynv in ynvs) + { + if (renderpathbounds) + { + if (ynv.Nav == null) continue; + if (ynv.Nav.SectorTree == null) continue; + + MapBox mb = new MapBox(); + mb.CamRelPos = -camera.Position; + mb.BBMin = ynv.Nav.SectorTree.AABBMin.XYZ(); + mb.BBMax = ynv.Nav.SectorTree.AABBMax.XYZ(); + mb.Orientation = Quaternion.Identity; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + } + + if ((ynv.Nav != null) && (ynv.Vertices != null) && (ynv.Indices != null) && (ynv.Polys != null)) + { + UpdateMouseHits(ynv, ynv.Nav.SectorTree, ynv.Nav.SectorTree, ref mray); + } + } + + if ((CurMouseHit.NavPoly != null) && MouseSelectEnabled) + { + var colour = Color4.White; + var colourval = (uint)colour.ToRgba(); + var poly = CurMouseHit.NavPoly; + var ynv = poly.Ynv; + var ic = poly._RawData.IndexCount; + var startid = poly._RawData.IndexID; + var endid = startid + ic; + var lastid = endid - 1; + var vc = ynv.Vertices.Count; + var startind = ynv.Indices[startid]; + + ////draw poly outline + VertexTypePC v = new VertexTypePC(); + v.Colour = colourval; + VertexTypePC v0 = new VertexTypePC(); + for (int id = startid; id < endid; id++) + { + var ind = ynv.Indices[id]; + if (ind >= vc) + { continue; } + + v.Position = ynv.Vertices[ind]; + SelectionLineVerts.Add(v); + if (id == startid) + { + v0 = v; + } + else + { + SelectionLineVerts.Add(v); + } + if (id == lastid) + { + SelectionLineVerts.Add(v0); + } + } + + + ////draw poly triangles + //VertexTypePC v0 = new VertexTypePC(); + //VertexTypePC v1 = new VertexTypePC(); + //VertexTypePC v2 = new VertexTypePC(); + //v0.Position = ynv.Vertices[startind]; + //v0.Colour = colourval; + //v1.Colour = colourval; + //v2.Colour = colourval; + //int tricount = ic - 2; + //for (int t = 0; t < tricount; t++) + //{ + // int tid = startid + t; + // int ind1 = ynv.Indices[tid + 1]; + // int ind2 = ynv.Indices[tid + 2]; + // if ((ind1 >= vc) || (ind2 >= vc)) + // { continue; } + // v1.Position = ynv.Vertices[ind1]; + // v2.Position = ynv.Vertices[ind2]; + // SelectionTriVerts.Add(v0); + // SelectionTriVerts.Add(v1); + // SelectionTriVerts.Add(v2); + // SelectionTriVerts.Add(v0); + // SelectionTriVerts.Add(v2); + // SelectionTriVerts.Add(v1); + //} + + } + + } + private void UpdateMouseHits(YnvFile ynv, NavMeshSector navsector, NavMeshSector rootsec, ref Ray mray) + { + if (navsector == null) return; + + float hitdist = float.MaxValue; + + BoundingBox bbox = new BoundingBox(); + bbox.Minimum = navsector.AABBMin.XYZ(); + bbox.Maximum = navsector.AABBMax.XYZ(); + + if (rootsec != null) //apparently the Z values are incorrect :( + { + bbox.Minimum.Z = rootsec.AABBMin.Z; + bbox.Maximum.Z = rootsec.AABBMax.Z; + } + + float fhd; + if (mray.Intersects(ref bbox, out fhd)) //ray intersects this node... check children for hits! + { + ////test vis + //MapBox mb = new MapBox(); + //mb.CamRelPos = -camera.Position; + //mb.BBMin = bbox.Minimum; + //mb.BBMax = bbox.Maximum; + //mb.Orientation = Quaternion.Identity; + //mb.Scale = Vector3.One; + //BoundingBoxes.Add(mb); + + + if (navsector.SubTree1 != null) + { + UpdateMouseHits(ynv, navsector.SubTree1, rootsec, ref mray); + } + if (navsector.SubTree2 != null) + { + UpdateMouseHits(ynv, navsector.SubTree2, rootsec, ref mray); + } + if (navsector.SubTree3 != null) + { + UpdateMouseHits(ynv, navsector.SubTree3, rootsec, ref mray); + } + if (navsector.SubTree4 != null) + { + UpdateMouseHits(ynv, navsector.SubTree4, rootsec, ref mray); + } + if ((navsector.Data != null) && (navsector.Data.PolyIDs != null)) + { + BoundingBox cbox = new BoundingBox(); + cbox.Minimum = bbox.Minimum - camera.Position; + cbox.Maximum = bbox.Maximum - camera.Position; + + var polys = ynv.Polys; + var polyids = navsector.Data.PolyIDs; + for (int i = 0; i < polyids.Length; i++) + { + var polyid = polyids[i]; + if (polyid >= polys.Count) + { continue; } + + var poly = polys[polyid]; + var ic = poly._RawData.IndexCount; + var startid = poly._RawData.IndexID; + var endid = startid + ic; + if (startid >= ynv.Indices.Count) + { continue; } + if (endid > ynv.Indices.Count) + { continue; } + + var vc = ynv.Vertices.Count; + var startind = ynv.Indices[startid]; + if (startind >= vc) + { continue; } + + Vector3 p0 = ynv.Vertices[startind]; + + //test triangles for the poly. + int tricount = ic - 2; + for (int t = 0; t < tricount; t++) + { + int tid = startid + t; + int ind1 = ynv.Indices[tid + 1]; + int ind2 = ynv.Indices[tid + 2]; + if ((ind1 >= vc) || (ind2 >= vc)) + { continue; } + + Vector3 p1 = ynv.Vertices[ind1]; + Vector3 p2 = ynv.Vertices[ind2]; + + if (mray.Intersects(ref p0, ref p1, ref p2, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + var cellaabb = poly._RawData.CellAABB; + CurMouseHit.NavPoly = poly; + CurMouseHit.HitDist = hitdist; + CurMouseHit.AABB = new BoundingBox(cellaabb.Min, cellaabb.Max); + break;//no need to test further tris in this poly + } + } + } + } + } + } + private void UpdateMouseHits(List ynds) + { + if (SelectionMode != MapSelectionMode.Path) return; + + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + + foreach (var ynd in ynds) + { + if (renderpathbounds) + { + float minz = (ynd.BVH != null) ? ynd.BVH.Box.Minimum.Z : 0.0f; + float maxz = (ynd.BVH != null) ? ynd.BVH.Box.Maximum.Z : 0.0f; + MapBox mb = new MapBox(); + mb.CamRelPos = -camera.Position; + mb.BBMin = new Vector3(ynd.BBMin.X, ynd.BBMin.Y, minz); + mb.BBMax = new Vector3(ynd.BBMax.X, ynd.BBMax.Y, maxz); + mb.Orientation = Quaternion.Identity; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + } + + if (ynd.BVH != null) + { + UpdateMouseHits(ynd.BVH, ref mray); + } + } + + + if (SelectedItem.PathNode != null) + { + float linkrad = 0.25f; + + var n = SelectedItem.PathNode; + if (n.Links != null) + { + foreach (var ln in n.Links) + { + if (ln.Node2 == null) continue;//invalid links can hit here... + Vector3 dv = n.Position - ln.Node2.Position; + float dl = dv.Length(); + Vector3 dir = dv * (1.0f / dl); + Vector3 dup = Vector3.UnitZ; + MapBox mb = new MapBox(); + + int lanestot = ln.LaneCountForward + ln.LaneCountBackward; + float lanewidth = n.IsPedNode ? 0.5f : 5.5f; + float inner = ln.LaneOffset * lanewidth;// 0.0f; + float outer = inner + Math.Max(lanewidth * ln.LaneCountForward, 0.5f); + float totwidth = lanestot * lanewidth; + float halfwidth = totwidth * 0.5f; + if (ln.LaneCountBackward == 0) + { + inner -= halfwidth; + outer -= halfwidth; + } + if (ln.LaneCountForward == 0) + { + inner += halfwidth; + outer += halfwidth; + } + + + mb.CamRelPos = n.Position - camera.Position; + mb.BBMin = new Vector3(-linkrad - outer, -linkrad, 0.0f); + mb.BBMax = new Vector3(linkrad - inner, linkrad, dl); + mb.Orientation = Quaternion.Invert(Quaternion.RotationLookAtRH(dir, dup)); + mb.Scale = Vector3.One; + if (ln == SelectedItem.PathLink) + { + HilightBoxes.Add(mb); + } + else + { + BoundingBoxes.Add(mb); + } + } + } + } + + } + private void UpdateMouseHits(List tracks) + { + if (SelectionMode != MapSelectionMode.TrainTrack) return; + + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + + foreach (var track in tracks) + { + if (renderpathbounds) + { + //MapBox mb = new MapBox(); + //mb.CamRelPos = -camera.Position; + //mb.BBMin = track.BVH?.Box.Minimum ?? Vector3.Zero; + //mb.BBMax = track.BVH?.Box.Maximum ?? Vector3.Zero; + //mb.Orientation = Quaternion.Identity; + //mb.Scale = Vector3.One; + //BoundingBoxes.Add(mb); + } + + if (track.BVH != null) + { + UpdateMouseHits(track.BVH, ref mray); + } + } + + + if (SelectedItem.TrainTrackNode != null) + { + float linkrad = 0.25f; + var n = SelectedItem.TrainTrackNode; + if (n.Links != null) + { + foreach (var ln in n.Links) + { + if (ln == null) continue; + Vector3 dv = n.Position - ln.Position; + float dl = dv.Length(); + Vector3 dir = dv * (1.0f / dl); + Vector3 dup = Vector3.UnitZ; + MapBox mb = new MapBox(); + mb.CamRelPos = n.Position - camera.Position; + mb.BBMin = new Vector3(-linkrad, -linkrad, 0.0f); + mb.BBMax = new Vector3(linkrad, linkrad, dl); + mb.Orientation = Quaternion.Invert(Quaternion.RotationLookAtRH(dir, dup)); + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + } + } + } + + } + private void UpdateMouseHits(List scenarios) + { + if (SelectionMode != MapSelectionMode.Scenario) return; + + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + + foreach (var scenario in scenarios) + { + var sr = scenario.ScenarioRegion; + if (sr == null) continue; + + if (renderscenariobounds) + { + MapBox mb = new MapBox(); + mb.CamRelPos = -camera.Position; + mb.BBMin = sr?.BVH?.Box.Minimum ?? Vector3.Zero; + mb.BBMax = sr?.BVH?.Box.Maximum ?? Vector3.Zero; + mb.Orientation = Quaternion.Identity; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + } + + if (sr.BVH != null) + { + UpdateMouseHits(sr.BVH, ref mray); + } + } + + + if (SelectedItem.ScenarioNode != null) //move this stuff to renderselection..? + { + var n = SelectedItem.ScenarioNode; + var nc = n.ChainingNode?.Chain; + var ncl = n.Cluster; + + + //float linkrad = 0.25f; + //if (n.Links != null) + //{ + // foreach (var ln in n.Links) + // { + // if (ln == null) continue; + // Vector3 dv = n.Position - ln.Position; + // float dl = dv.Length(); + // Vector3 dir = dv * (1.0f / dl); + // Vector3 dup = Vector3.UnitZ; + // MapBox mb = new MapBox(); + // mb.CamRelPos = n.Position - camera.Position; + // mb.BBMin = new Vector3(-linkrad, -linkrad, 0.0f); + // mb.BBMax = new Vector3(linkrad, linkrad, dl); + // mb.Orientation = Quaternion.Invert(Quaternion.RotationLookAtRH(dir, dup)); + // mb.Scale = Vector3.One; + // BoundingBoxes.Add(mb); + // } + //} + + var sr = SelectedItem.ScenarioNode.Ymt.ScenarioRegion; + //if (renderscenariobounds) + { + MapBox mb = new MapBox(); + mb.CamRelPos = -camera.Position; + mb.BBMin = sr?.BVH?.Box.Minimum ?? Vector3.Zero; + mb.BBMax = sr?.BVH?.Box.Maximum ?? Vector3.Zero; + mb.Orientation = Quaternion.Identity; + mb.Scale = Vector3.One; + if (renderscenariobounds) + { + HilightBoxes.Add(mb); + } + else + { + BoundingBoxes.Add(mb); + } + } + + + if (ncl != null) + { + + //hilight the cluster itself + MapBox mb = new MapBox(); + mb.Scale = Vector3.One; + mb.BBMin = new Vector3(-0.5f); + mb.BBMax = new Vector3(0.5f); + mb.CamRelPos = ncl.Position - camera.Position; + mb.Orientation = Quaternion.Identity; + HilightBoxes.Add(mb); + + + //show boxes for points in the cluster + if ((ncl.Points != null) && (ncl.Points.MyPoints != null)) + { + foreach (var clpoint in ncl.Points.MyPoints) + { + if (clpoint == n.ClusterMyPoint) continue; //don't highlight the selected node... + mb = new MapBox(); + mb.Scale = Vector3.One; + mb.BBMin = new Vector3(-0.5f); + mb.BBMax = new Vector3(0.5f); + mb.CamRelPos = clpoint.Position - camera.Position; + mb.Orientation = clpoint.Orientation; + BoundingBoxes.Add(mb); + } + } + } + + + + } + + + + + } + private void UpdateMouseHits(PathBVHNode pathbvhnode, ref Ray mray) + { + float nrad = 0.5f; + float hitdist = float.MaxValue; + + BoundingSphere bsph = new BoundingSphere(); + bsph.Radius = nrad; + + BoundingBox bbox = new BoundingBox(); + bbox.Minimum = pathbvhnode.Box.Minimum - nrad; + bbox.Maximum = pathbvhnode.Box.Maximum + nrad; + + BoundingBox nbox = new BoundingBox(); + nbox.Minimum = new Vector3(-nrad); + nbox.Maximum = new Vector3(nrad); + + float fhd; + if (mray.Intersects(ref bbox, out fhd)) //ray intersects this node... check children for hits! + { + if ((pathbvhnode.Node1 != null) && (pathbvhnode.Node2 != null)) //node is split. recurse + { + UpdateMouseHits(pathbvhnode.Node1, ref mray); + UpdateMouseHits(pathbvhnode.Node2, ref mray); + } + else if (pathbvhnode.Nodes != null) //leaf node. test contaned pathnodes + { + foreach (var n in pathbvhnode.Nodes) + { + bsph.Center = n.Position; + if (mray.Intersects(ref bsph, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.PathNode = n as YndNode; + CurMouseHit.TrainTrackNode = n as TrainTrackNode; + CurMouseHit.ScenarioNode = n as ScenarioNode; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = (n.Position - camera.Position); + CurMouseHit.AABB = nbox; + } + } + } + } + } + + public void SelectItem(YmapEntityDef entity, Archetype arch, DrawableBase drawable, DrawableGeometry geom = null, MapSelection? mhit = null) + { + if ((arch == null) && (entity != null)) + { + arch = entity.Archetype; //use the entity archetype if no archetype given + } + + bool change = (SelectedItem.EntityDef != entity) || (SelectedItem.Archetype != arch);// || (SelectedItem.Drawable != drawable); + if (mhit != null) + { + change = change || (SelectedItem.Drawable != drawable) + || (SelectedItem.TimeCycleModifier != mhit.Value.TimeCycleModifier) + || (SelectedItem.ArchetypeExtension != mhit.Value.ArchetypeExtension) + || (SelectedItem.EntityExtension != mhit.Value.EntityExtension) + || (SelectedItem.CarGenerator != mhit.Value.CarGenerator) + || (SelectedItem.MloEntityDef != mhit.Value.MloEntityDef) + || (SelectedItem.DistantLodLights != mhit.Value.DistantLodLights) + || (SelectedItem.GrassBatch != mhit.Value.GrassBatch) + || (SelectedItem.WaterQuad != mhit.Value.WaterQuad) + || (SelectedItem.CollisionBounds != mhit.Value.CollisionBounds) + || (SelectedItem.NavPoly != mhit.Value.NavPoly) + || (SelectedItem.PathNode != mhit.Value.PathNode) + || (SelectedItem.TrainTrackNode != mhit.Value.TrainTrackNode) + || (SelectedItem.ScenarioNode != mhit.Value.ScenarioNode); + } + else + { + change = change // || (SelectedItem.Drawable != null) + || (SelectedItem.TimeCycleModifier != null) + || (SelectedItem.ArchetypeExtension != null) + || (SelectedItem.EntityExtension != null) + || (SelectedItem.CarGenerator != null) + || (SelectedItem.MloEntityDef != null) + || (SelectedItem.DistantLodLights != null) + || (SelectedItem.GrassBatch != null) + || (SelectedItem.WaterQuad != null) + || (SelectedItem.CollisionBounds != null) + || (SelectedItem.NavPoly != null) + || (SelectedItem.PathNode != null) + || (SelectedItem.PathLink != null) + || (SelectedItem.TrainTrackNode != null) + || (SelectedItem.ScenarioNode != null); + } + + if (!change) + { + if (mhit.HasValue) + { + //make sure the path link gets changed (sub-selection!) + lock (rendersyncroot) + { + SelectedItem.PathLink = mhit.Value.PathLink; + SelectedItem.ScenarioEdge = mhit.Value.ScenarioEdge; + } + } + return; + } + + lock (rendersyncroot) //drawflags is used when rendering.. need that lock + { + if (mhit.HasValue && mhit.Value.GrassBatch != null) + { + arch = mhit.Value.GrassBatch.Archetype; + } + + if ((arch != null) && (drawable == null)) + { + drawable = TryGetDrawable(arch); //no drawable given.. try to get it from the cache.. if it's not there, drawable info won't display... + } + + + if (mhit.HasValue) + { + SelectedItem = mhit.Value; + } + else + { + SelectedItem.Clear(); + } + SelectedItem.EntityDef = entity; + SelectedItem.Archetype = arch; + SelectedItem.Drawable = drawable; + SelectedItem.Geometry = geom; + + if (change) + { + UpdateSelectionUI(true); + + var cargen = SelectedItem.CarGenerator; + var navpoly = SelectedItem.NavPoly; + var pathnode = SelectedItem.PathNode; + var trainnode = SelectedItem.TrainTrackNode; + var scenariond = SelectedItem.ScenarioNode; + + if (entity != null) + { + Widget.Position = entity.WidgetPosition; + Widget.Rotation = entity.WidgetOrientation; + Widget.Scale = entity.Scale; + Widget.Visible = true; + Widget.RotationWidget.EnableAxes = WidgetAxis.XYZ; + } + else if (cargen != null) + { + Widget.Position = cargen.Position; + Widget.Rotation = cargen.Orientation; + Widget.Scale = new Vector3(cargen.CCarGen.perpendicularLength); + Widget.Visible = true; + Widget.RotationWidget.EnableAxes = WidgetAxis.Z; + } + else if (navpoly != null) + { + Widget.Position = navpoly.Position; + Widget.Rotation = Quaternion.Identity; + Widget.Scale = Vector3.One; + Widget.Visible = true; + Widget.RotationWidget.EnableAxes = WidgetAxis.XYZ; + } + else if (pathnode != null) + { + Widget.Position = pathnode.Position; + Widget.Rotation = Quaternion.Identity; + Widget.Scale = Vector3.One; + Widget.Visible = true; + Widget.RotationWidget.EnableAxes = WidgetAxis.None; + } + else if (trainnode != null) + { + Widget.Position = trainnode.Position; + Widget.Rotation = Quaternion.Identity; + Widget.Scale = Vector3.One; + Widget.Visible = true; + Widget.RotationWidget.EnableAxes = WidgetAxis.None; + } + else if (scenariond != null) + { + Widget.Position = scenariond.Position; + Widget.Rotation = scenariond.Orientation; + Widget.Scale = Vector3.One; + Widget.Visible = true; + Widget.RotationWidget.EnableAxes = WidgetAxis.Z; + } + else + { + Widget.Visible = false; + } + } + } + if (change && (ProjectForm != null)) + { + ProjectForm.OnWorldSelectionChanged(SelectedItem); + } + } + public void SelectEntity(YmapEntityDef entity) + { + SelectItem(entity, null, null); + } + public void SelectCarGen(YmapCarGen cargen) + { + if (cargen == null) + { + SelectItem(null, null, null); + } + else + { + MapSelection ms = new MapSelection(); + ms.CarGenerator = cargen; + ms.AABB = new BoundingBox(cargen.BBMin, cargen.BBMax); + SelectItem(null, null, null, null, ms); + } + } + public void SelectNavPoly(YnvPoly poly) + { + if (poly == null) + { + SelectItem(null, null, null); + } + else + { + var sect = poly.Ynv?.Nav?.SectorTree; + + MapSelection ms = new MapSelection(); + ms.NavPoly = poly; + + var cellaabb = poly._RawData.CellAABB; + ms.AABB = new BoundingBox(cellaabb.Min, cellaabb.Max); + //if (sect != null) + //{ + // ms.AABB = new BoundingBox(sect.AABBMin.XYZ(), sect.AABBMax.XYZ()); + //} + SelectItem(null, null, null, null, ms); + } + } + public void SelectPathNode(YndNode node) + { + if (node == null) + { + SelectItem(null, null, null); + } + else + { + float nrad = 0.5f; + + MapSelection ms = new MapSelection(); + ms.PathNode = node; + ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad)); + SelectItem(null, null, null, null, ms); + } + } + public void SelectPathLink(YndLink link) + { + var node = link?.Node1; + if (node == null) + { + SelectItem(null, null, null); + } + else + { + float nrad = 0.5f; + + MapSelection ms = new MapSelection(); + ms.PathNode = node; + ms.PathLink = link; + ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad)); + SelectItem(null, null, null, null, ms); + } + } + public void SelectTrainTrackNode(TrainTrackNode node) + { + if (node == null) + { + SelectItem(null, null, null); + } + else + { + float nrad = 0.5f; + + MapSelection ms = new MapSelection(); + ms.TrainTrackNode = node; + ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad)); + SelectItem(null, null, null, null, ms); + } + } + public void SelectScenarioNode(ScenarioNode node) + { + if (node == null) + { + SelectItem(null, null, null); + } + else + { + float nrad = 0.5f; + + MapSelection ms = new MapSelection(); + ms.ScenarioNode = node; + ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad)); + SelectItem(null, null, null, null, ms); + } + } + public void SelectScenarioEdge(ScenarioNode node, MCScenarioChainingEdge edge) + { + if (node == null) + { + SelectItem(null, null, null); + } + else + { + float nrad = 0.5f; + + MapSelection ms = new MapSelection(); + ms.ScenarioNode = node; + ms.ScenarioEdge = edge; + ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad)); + SelectItem(null, null, null, null, ms); + } + } + private void SelectMousedItem() + { + //when clicked, select the currently moused item and update the selection info UI + + if (!MouseSelectEnabled) + { return; } + + var h = LastMouseHit; + + SelectItem(h.EntityDef, h.Archetype, h.Drawable, h.Geometry, h); + } + private void UpdateSelectionUI(bool wait) + { + try + { + if (InvokeRequired) + { + if (wait) + { + Invoke(new Action(() => { UpdateSelectionUI(wait); })); + } + else + { + BeginInvoke(new Action(() => { UpdateSelectionUI(wait); })); + } + } + else + { + SetSelectionUI(SelectedItem); + + if (InfoForm != null) + { + InfoForm.SetSelection(SelectedItem); + } + } + } + catch { } + } + private void SetSelectionUI(MapSelection item) + { + SelectionNameTextBox.Text = item.GetNameString("Nothing selected"); + //SelEntityPropertyGrid.SelectedObject = item.EntityDef; + SelArchetypePropertyGrid.SelectedObject = item.Archetype; + SelDrawablePropertyGrid.SelectedObject = item.Drawable; + + SelectionModelDrawFlags.Clear(); + SelectionGeometryDrawFlags.Clear(); + SelDrawableModelsTreeView.Nodes.Clear(); + SelDrawableTexturesTreeView.Nodes.Clear(); + if (item.Drawable != null) + { + AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsHigh, "High Detail", true); + AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsMedium, "Medium Detail", false); + AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsLow, "Low Detail", false); + AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsVeryLow, "Very Low Detail", false); + //AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsX, "X Detail", false); + } + + + YmapFile ymap = null; + YnvFile ynv = null; + YndFile ynd = null; + TrainTrack traintr = null; + YmtFile scenario = null; + ToolbarCopyButton.Enabled = false; + ToolbarDeleteItemButton.Enabled = false; + ToolbarDeleteItemButton.Text = "Delete"; + + if (item.TimeCycleModifier != null) + { + SelectionEntityTabPage.Text = "TCMod"; + SelEntityPropertyGrid.SelectedObject = item.TimeCycleModifier; + } + else if (item.CarGenerator != null) + { + SelectionEntityTabPage.Text = "CarGen"; + SelEntityPropertyGrid.SelectedObject = item.CarGenerator; + ymap = item.CarGenerator.Ymap; + ToolbarCopyButton.Enabled = true; + ToolbarDeleteItemButton.Enabled = true; + ToolbarDeleteItemButton.Text = "Delete car generator"; + } + else if (item.DistantLodLights != null) + { + SelectionEntityTabPage.Text = "DistLodLight"; + SelEntityPropertyGrid.SelectedObject = item.DistantLodLights; + } + else if (item.GrassBatch != null) + { + SelectionEntityTabPage.Text = "Grass"; + SelEntityPropertyGrid.SelectedObject = item.GrassBatch; + } + else if (item.WaterQuad != null) + { + SelectionEntityTabPage.Text = "WaterQuad"; + SelEntityPropertyGrid.SelectedObject = item.WaterQuad; + } + else if (item.PathNode != null) + { + SelectionEntityTabPage.Text = "PathNode"; + SelEntityPropertyGrid.SelectedObject = item.PathNode; + ynd = item.PathNode.Ynd; + ToolbarCopyButton.Enabled = true; + ToolbarDeleteItemButton.Enabled = true; + ToolbarDeleteItemButton.Text = "Delete path node"; + } + else if (item.NavPoly != null) + { + SelectionEntityTabPage.Text = "NavPoly"; + SelEntityPropertyGrid.SelectedObject = item.NavPoly; + ynv = item.NavPoly.Ynv; + //ToolbarCopyButton.Enabled = true; + //ToolbarDeleteItemButton.Enabled = true; + //ToolbarDeleteItemButton.Text = "Delete nav poly"; + } + else if (item.TrainTrackNode != null) + { + SelectionEntityTabPage.Text = "TrainNode"; + SelEntityPropertyGrid.SelectedObject = item.TrainTrackNode; + traintr = item.TrainTrackNode.Track; + ToolbarCopyButton.Enabled = true; + ToolbarDeleteItemButton.Enabled = true; + ToolbarDeleteItemButton.Text = "Delete train track node"; + } + else if (item.ScenarioNode != null) + { + SelectionEntityTabPage.Text = item.ScenarioNode.ShortTypeName; + SelEntityPropertyGrid.SelectedObject = item.ScenarioNode; + scenario = item.ScenarioNode.Ymt; + ToolbarCopyButton.Enabled = true; + ToolbarDeleteItemButton.Enabled = true; + ToolbarDeleteItemButton.Text = "Delete scenario point"; + } + else + { + SelectionEntityTabPage.Text = "Entity"; + SelEntityPropertyGrid.SelectedObject = item.EntityDef; + if (item.EntityDef != null) + { + ymap = item.EntityDef?.Ymap; + ToolbarCopyButton.Enabled = true; + ToolbarDeleteItemButton.Enabled = true; + ToolbarDeleteItemButton.Text = "Delete entity"; + } + } + + + if (item.EntityExtension != null) + { + SelExtensionPropertyGrid.SelectedObject = item.EntityExtension; + ShowSelectedExtensionTab(true); + } + else if (item.ArchetypeExtension != null) + { + SelExtensionPropertyGrid.SelectedObject = item.ArchetypeExtension; + ShowSelectedExtensionTab(true); + } + else if (item.CollisionBounds != null) + { + SelExtensionPropertyGrid.SelectedObject = item.CollisionBounds; + ShowSelectedExtensionTab(true, "Coll"); + } + else + { + SelExtensionPropertyGrid.SelectedObject = null; + ShowSelectedExtensionTab(false); + } + + + //var ent = SelectedItem.EntityDef; + //ToolbarDeleteEntityButton.Enabled = false; + ////ToolbarAddEntityButton.Enabled = false; + //ToolbarCopyButton.Enabled = (ent != null); + //if (ent != null) + //{ + // ToolbarDeleteEntityButton.Enabled = true; + // //ToolbarAddEntityButton.Enabled = true; + // //if (ProjectForm != null) + // //{ + // // ToolbarDeleteEntityButton.Enabled = ProjectForm.IsCurrentEntity(ent); + // //} + //} + //bool enableymapui = (ent != null) && (ent.Ymap != null); + //var ymap = ent?.Ymap; + + bool enableymapui = (ymap != null); + + EnableYmapUI(enableymapui, (ymap != null) ? ymap.Name : ""); + + if (ynd != null) + { + EnableYndUI(true, ynd.Name); + } + if (ynv != null) + { + EnableYnvUI(true, ynv.Name); + } + if (traintr != null) + { + EnableTrainsUI(true, traintr.Name); + } + if (scenario != null) + { + EnableScenarioUI(true, scenario.Name); + } + + } + private void ShowSelectedExtensionTab(bool show, string text = "Ext") + { + SelectionExtensionTabPage.Text = text; + if (show) + { + if (!SelectionTabControl.TabPages.Contains(SelectionExtensionTabPage)) + { + SelectionTabControl.TabPages.Add(SelectionExtensionTabPage); + SelectionTabControl.SelectedTab = SelectionExtensionTabPage; + } + } + else + { + if (SelectionTabControl.TabPages.Contains(SelectionExtensionTabPage)) + { + SelectionTabControl.TabPages.Remove(SelectionExtensionTabPage); + } + } + } + private void AddSelectionDrawableModelsTreeNodes(ResourcePointerList64 models, string prefix, bool check) + { + if (models == null) return; + if (models.data_items == null) return; + + for (int mi = 0; mi < models.data_items.Length; mi++) + { + var model = models.data_items[mi]; + string mprefix = prefix + " " + (mi + 1).ToString(); + var mnode = SelDrawableModelsTreeView.Nodes.Add(mprefix + " " + model.ToString()); + mnode.Tag = model; + mnode.Checked = check; + + var tmnode = SelDrawableTexturesTreeView.Nodes.Add(mprefix + " " + model.ToString()); + tmnode.Tag = model; + + if (!check) + { + SelectionModelDrawFlags[model] = false; + } + + if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + + foreach (var geom in model.Geometries.data_items) + { + var gname = geom.ToString(); + var gnode = mnode.Nodes.Add(gname); + gnode.Tag = geom; + gnode.Checked = true;// check; + + var tgnode = tmnode.Nodes.Add(gname); + tgnode.Tag = geom; + + if ((geom.Shader != null) && (geom.Shader.ParametersList != null) && (geom.Shader.ParametersList.Hashes != null)) + { + var pl = geom.Shader.ParametersList; + var h = pl.Hashes; + var p = pl.Parameters; + for (int ip = 0; ip < h.Length; ip++) + { + var hash = pl.Hashes[ip]; + var parm = pl.Parameters[ip]; + var tex = parm.Data as TextureBase; + if (tex != null) + { + var t = tex as Texture; + var tstr = tex.Name.Trim(); + if (t != null) + { + tstr = string.Format("{0} ({1}x{2}, embedded)", tex.Name, t.Width, t.Height); + } + var tnode = tgnode.Nodes.Add(hash.ToString().Trim() + ": " + tstr); + tnode.Tag = tex; + } + } + tgnode.Expand(); + } + + } + + mnode.Expand(); + tmnode.Expand(); + } + } + private void UpdateSelectionDrawFlags(TreeNode node) + { + //update the selection draw flags depending on tag and checked/unchecked + var model = node.Tag as DrawableModel; + var geom = node.Tag as DrawableGeometry; + bool rem = node.Checked; + lock (rendersyncroot) + { + if (model != null) + { + if (rem) + { + if (SelectionModelDrawFlags.ContainsKey(model)) + { + SelectionModelDrawFlags.Remove(model); + } + } + else + { + SelectionModelDrawFlags[model] = false; + } + } + if (geom != null) + { + if (rem) + { + if (SelectionGeometryDrawFlags.ContainsKey(geom)) + { + SelectionGeometryDrawFlags.Remove(geom); + } + } + else + { + SelectionGeometryDrawFlags[geom] = false; + } + } + } + } + public void SyncSelDrawableModelsTreeNode(TreeNode node) + { + //called by the info form when a selection treeview node is checked/unchecked. + foreach (TreeNode mnode in SelDrawableModelsTreeView.Nodes) + { + if (mnode.Tag == node.Tag) + { + if (mnode.Checked != node.Checked) + { + mnode.Checked = node.Checked; + } + } + foreach (TreeNode gnode in mnode.Nodes) + { + if (gnode.Tag == node.Tag) + { + if (gnode.Checked != node.Checked) + { + gnode.Checked = node.Checked; + } + } + } + } + } + + + private void ShowInfoForm() + { + if (InfoForm == null) + { + InfoForm = new WorldInfoForm(this); + InfoForm.SetSelection(SelectedItem); + InfoForm.SetSelectionMode(SelectionModeStr, MouseSelectEnabled); + InfoForm.Show(this); + } + else + { + if (InfoForm.WindowState == FormWindowState.Minimized) + { + InfoForm.WindowState = FormWindowState.Normal; + } + InfoForm.Focus(); + } + ToolbarInfoWindowButton.Checked = true; + } + public void OnInfoFormSelectionModeChanged(string mode, bool enableSelect) + { + //called by the WorldInfoForm + SetSelectionMode(mode); + SetMouseSelect(enableSelect); + } + public void OnInfoFormClosed() + { + //called by the WorldInfoForm when it's closed. + InfoForm = null; + ToolbarInfoWindowButton.Checked = false; + } + + private void ShowProjectForm() + { + if (ProjectForm == null) + { + ProjectForm = new ProjectForm(this); + ProjectForm.Show(this); + } + else + { + if (ProjectForm.WindowState == FormWindowState.Minimized) + { + ProjectForm.WindowState = FormWindowState.Normal; + } + ProjectForm.Focus(); + } + ToolbarProjectWindowButton.Checked = true; + } + public void OnProjectFormClosed() + { + ProjectForm = null; + ToolbarProjectWindowButton.Checked = false; + } + + private void ShowSearchForm() + { + if (SearchForm == null) + { + SearchForm = new WorldSearchForm(this); + SearchForm.Show(this); + } + else + { + if (SearchForm.WindowState == FormWindowState.Minimized) + { + SearchForm.WindowState = FormWindowState.Normal; + } + SearchForm.Focus(); + } + //ToolbarSearchWindowButton.Checked = true; + } + public void OnSearchFormClosed() + { + SearchForm = null; + //ToolbarSearchWindowButton.Checked = false; + } + + public void ShowModel(string name) + { + ViewModeComboBox.Text = "Model view"; + ModelComboBox.Text = name; + modelname = name; + } + public void GoToEntity(YmapEntityDef entity) + { + if (entity == null) return; + ViewModeComboBox.Text = "World view"; + GoToPosition(entity.Position); + SelectEntity(entity); + } + + + private void LoadWorld() + { + + UpdateStatus("Loading timecycles..."); + timecycle.Init(gameFileCache, UpdateStatus); + timecycle.SetTime(timeofday); + + UpdateStatus("Loading materials..."); + BoundsMaterialTypes.Init(gameFileCache); + + UpdateStatus("Loading weather..."); + weather.Init(gameFileCache, UpdateStatus, timecycle); + UpdateWeatherTypesComboBox(weather); + + UpdateStatus("Loading clouds..."); + clouds.Init(gameFileCache, UpdateStatus, weather); + UpdateCloudTypesComboBox(clouds); + + UpdateStatus("Loading water..."); + water.Init(gameFileCache, UpdateStatus); + + UpdateStatus("Loading trains..."); + trains.Init(gameFileCache, UpdateStatus); + + UpdateStatus("Loading scenarios..."); + scenarios.Init(gameFileCache, UpdateStatus, timecycle); + + UpdateStatus("Loading popzones..."); + popzones.Init(gameFileCache, UpdateStatus); + + UpdateStatus("Loading world..."); + space.Init(gameFileCache, UpdateStatus); + + UpdateStatus("World loaded"); + + } + + + + private void SetDlcLevel(string dlc, bool enable) + { + if (!initialised) return; + Cursor = Cursors.WaitCursor; + Task.Run(() => + { + lock (rendersyncroot) + { + if (gameFileCache.SetDlcLevel(dlc, enable)) + { + LoadWorld(); + } + } + Invoke(new Action(()=> { + Cursor = Cursors.Default; + })); + }); + } + + private void SetModsEnabled(bool enable) + { + if (!initialised) return; + Cursor = Cursors.WaitCursor; + Task.Run(() => + { + lock (rendersyncroot) + { + if (gameFileCache.SetModsEnabled(enable)) + { + UpdateDlcListComboBox(gameFileCache.DlcNameList); + + LoadWorld(); + } + } + Invoke(new Action(() => { + Cursor = Cursors.Default; + })); + }); + } + + + private void ContentThread() + { + //main content loading thread. + running = true; + + UpdateStatus("Scanning..."); + + try + { + GTA5Keys.LoadFromPath(Settings.Default.GTAFolder); //now loads from magic + } + catch + { + MessageBox.Show("Keys not found! This shouldn't happen."); + Close(); + return; + } + + gameFileCache.Init(UpdateStatus, LogError); + + UpdateDlcListComboBox(gameFileCache.DlcNameList); + + EnableCacheDependentUI(); + + + + LoadWorld(); + + + + initialised = true; + + EnableDLCModsUI(); + + + while (formopen && !IsDisposed) //main asset loop + { + gameFileCache.ContentThreadProc(); + + renderableCache.ContentThreadProc(); + + if (!(gameFileCache.ItemsStillPending || renderableCache.ItemsStillPending)) + { + Thread.Sleep(1); //sleep if there's nothing to do + } + } + + gameFileCache.Clear(); + + running = false; + } + + + + private void UpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateStatus(text); })); + } + else + { + StatusLabel.Text = text; + } + } + catch { } + } + private void UpdateMousedLabel(string text) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateMousedLabel(text); })); + } + else + { + MousedLabel.Text = text; + } + } + catch { } + } + private void UpdateWeatherTypesComboBox(Weather weather) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateWeatherTypesComboBox(weather); })); + } + else + { + + //MessageBox.Show("sky_hdr: " + weather.GetDynamicValue("sky_hdr").ToString() + "\n" + + // "Timecycle index: " + weather.Timecycle.CurrentSampleIndex + "\n" + + // "Timecycle blend: " + weather.Timecycle.CurrentSampleBlend + "\n"); + + WeatherComboBox.Items.Clear(); + foreach (string wt in weather.WeatherTypes.Keys) + { + WeatherComboBox.Items.Add(wt); + } + WeatherComboBox.SelectedIndex = 0; + WeatherRegionComboBox.SelectedIndex = 0; + } + } + catch { } + } + private void UpdateCloudTypesComboBox(Clouds clouds) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateCloudTypesComboBox(clouds); })); + } + else + { + CloudsComboBox.Items.Clear(); + foreach (var frag in clouds.HatManager.CloudHatFrags) + { + CloudsComboBox.Items.Add(frag.Name); + } + CloudsComboBox.SelectedIndex = Math.Max(CloudsComboBox.FindString(individualcloudfrag), 0); + + + CloudParamComboBox.Items.Clear(); + foreach (var setting in clouds.AnimSettings.Values) + { + CloudParamComboBox.Items.Add(setting); + } + CloudParamComboBox.SelectedIndex = 0; + } + } + catch { } + } + private void UpdateDlcListComboBox(List dlcnames) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateDlcListComboBox(dlcnames); })); + } + else + { + DlcLevelComboBox.Items.Clear(); + foreach (var dlcname in dlcnames) + { + DlcLevelComboBox.Items.Add(dlcname); + } + if (string.IsNullOrEmpty(gameFileCache.SelectedDlc)) + { + DlcLevelComboBox.SelectedIndex = dlcnames.Count - 1; + } + else + { + int idx = DlcLevelComboBox.FindString(gameFileCache.SelectedDlc); + DlcLevelComboBox.SelectedIndex = (idx > 0) ? idx : (dlcnames.Count - 1); + } + } + } + catch { } + } + + private void LogError(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { LogError(text); })); + } + else + { + ConsoleTextBox.AppendText(text + "\r\n"); + //MessageBox.Show(text); + } + } + catch { } + } + + + + + private void UpdateMarkerSelectionPanelInvoke() + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { UpdateMarkerSelectionPanel(); })); + } + else + { + UpdateMarkerSelectionPanel(); + } + } + catch { } + } + private void UpdateMarkerSelectionPanel() + { + if (!SelectedMarkerPanel.Visible) return; + if (SelectedMarker == null) + { + SelectedMarkerPanel.Visible = false; + return; + } + + int ox = -90; //screen offset from actual marker world pos + int oy = -76; + + float spx = ((SelectedMarker.ScreenPos.X * 0.5f) + 0.5f) * camera.Width; + float spy = ((SelectedMarker.ScreenPos.Y * -0.5f) + 0.5f) * camera.Height; + + int px = (int)Math.Round(spx, MidpointRounding.AwayFromZero) + ox; + int py = (int)Math.Round(spy, MidpointRounding.AwayFromZero) + oy; + + int sx = SelectedMarkerPanel.Width; + int sy = SelectedMarkerPanel.Height; + + SelectedMarkerPanel.SetBounds(px, py, sx, sy); + } + private void ShowMarkerSelectionInfo(MapMarker marker) + { + SelectedMarkerNameTextBox.Text = SelectedMarker.Name; + SelectedMarkerPositionTextBox.Text = SelectedMarker.Get3DWorldPosString(); + UpdateMarkerSelectionPanel(); + SelectedMarkerPanel.Visible = true; + } + private void HideMarkerSelectionInfo() + { + SelectedMarkerPanel.Visible = false; + } + + private MapMarker FindMousedMarker() + { + lock (markersortedsyncroot) + { + float mx = MouseLastPoint.X; + float my = MouseLastPoint.Y; + + if (ShowLocatorCheckBox.Checked) + { + if (IsMarkerUnderPoint(LocatorMarker, mx, my)) + { + return LocatorMarker; + } + } + + //search backwards through the render markers (front to back) + for (int i = SortedMarkers.Count - 1; i >= 0; i--) + { + MapMarker m = SortedMarkers[i]; + if (IsMarkerUnderPoint(m, mx, my)) + { + return m; + } + } + } + return null; + } + private bool IsMarkerUnderPoint(MapMarker marker, float x, float y) + { + if (marker.ScreenPos.Z <= 0.0f) return false; //behind the camera... + float dx = x - ((marker.ScreenPos.X * 0.5f) + 0.5f) * camera.Width; + float dy = y - ((marker.ScreenPos.Y * -0.5f) + 0.5f) * camera.Height; + float mcx = marker.Icon.Center.X; + float mcy = marker.Icon.Center.Y; + bool bx = ((dx >= -mcx) && (dx <= mcx)); + bool by = ((dy <= 0.0f) && (dy >= -mcy)); + return (bx && by); + } + + private void GoToMarker(MapMarker m) + { + //////adjust the target to account for the main panel... + ////Vector3 view = m.TexturePos; + ////view.X += ((float)(MainPanel.Width + 4) * 0.5f) / CurrentZoom; + ////TargetViewCenter = view; + + camera.FollowEntity.Position = m.WorldPos; + + } + public void GoToPosition(Vector3 p) + { + camera.FollowEntity.Position = p; + } + + private MapMarker AddMarker(Vector3 pos, string name, bool addtotxtbox = false) + { + string str = pos.X.ToString() + ", " + pos.Y.ToString() + ", " + pos.Z.ToString(); + if (!string.IsNullOrEmpty(name)) + { + str += ", " + name; + } + if (addtotxtbox) + { + StringBuilder sb = new StringBuilder(); + sb.Append(MultiFindTextBox.Text); + if ((sb.Length > 0) && (!MultiFindTextBox.Text.EndsWith("\n"))) + { + sb.AppendLine(); + } + sb.AppendLine(str); + MultiFindTextBox.Text = sb.ToString(); + } + + return AddMarker(str); + } + private MapMarker AddMarker(string markerstr) + { + lock (markersyncroot) + { + MapMarker m = new MapMarker(); + m.Parse(markerstr.Trim()); + m.Icon = MarkerIcon; + + Markers.Add(m); + + //ListViewItem lvi = new ListViewItem(new string[] { m.Name, m.WorldPos.X.ToString(), m.WorldPos.Y.ToString(), m.WorldPos.Z.ToString() }); + //lvi.Tag = m; + //MarkersListView.Items.Add(lvi); + + return m; + } + } + private void AddDefaultMarkers() + { + StringBuilder sb = new StringBuilder(); + //sb.AppendLine("1972.606, 3817.044, 0.0, Trevor Bed"); + //sb.AppendLine("94.5723, -1290.082, 0.0, Strip Club Bed"); + //sb.AppendLine("-1151.746, -1518.136, 0.0, Trevor City Bed"); + //sb.AppendLine("-1154.11, -2715.203, 0.0, Flight School"); + //sb.AppendLine("-1370.625, 56.1227, 52.82404, Golf"); + //sb.AppendLine("-1109.213, 4914.744, 0.0, Altruist Cult"); + //sb.AppendLine("-1633.087, 4736.784, 0.0, Deal Gone Wrong"); + sb.AppendLine("-2052, 3237, 1449.036, Zancudo UFO"); + sb.AppendLine("2490, 3777, 2400, Hippy UFO"); + sb.AppendLine("2577.396, 3301.573, 52.52076, Sand glyph"); + sb.AppendLine("-804.8452, 176.4936, 75.40561, bh1_48_michaels"); + sb.AppendLine("-5.757423, 529.674, 171.1747, ch2_05c_b1"); + sb.AppendLine("1971.208, 3818.237, 33.46632, cs4_10_trailer003b"); + sb.AppendLine("760.4618, 7392.803, -126.0774, cs1_09_sea_ufo"); + sb.AppendLine("501.4398, 5603.96, 795.9738, cs1_10_redeye"); + sb.AppendLine("51.3909, 5957.7568, 209.614, cs1_10_clue_moon02"); + sb.AppendLine("400.7087, 5714.5645, 605.0978, cs1_10_clue_rain01"); + sb.AppendLine("703.442, 6329.8936, 76.4973, cs1_10_clue_rain02"); + sb.AppendLine("228.7844, 5370.585, 577.2613, cs1_10_clue_moon01"); + sb.AppendLine("366.4871, 5518.0742, 704.3185, cs1_10_clue_mountain01"); + sb.AppendLine("41.64376, -779.9391, 832.4024, hw1_22_shipint"); + sb.AppendLine("-1255.392, 6795.764, -181.9927, cs1_08_sea_base"); + sb.AppendLine("4285.036, 2967.639, -184.1908, cs5_1_sea_hatch"); + sb.AppendLine("3041.498, 5584.321, 196.4748, cs2_08_generic02"); + sb.AppendLine("3406.483, 5498.655, 23.50577, cs2_08_generic01a"); + sb.AppendLine("1507.081, 6565.075, 8.681923, cs1_09_props_elec_spider1"); + sb.AppendLine("455.7852, 5586.104, 779.4382, cs1_10_elec_spider_spline052b"); + sb.AppendLine("3861.661, -4959.252, 91.49448, plg_01_nico_new"); + sb.AppendLine("-1689.308, 2174.457, 107.2592, ch1_09b_vinesleaf_28"); + sb.AppendLine("440.8488, 5810.079, 563.4703, Cock face"); + sb.AppendLine("-3955.667, -4675.212, -1274.563, Interesting..."); + sb.AppendLine("4512.627, 2623.241, 2500, Interesting..."); + sb.AppendLine("228.6058, -992.0537, -100, v_garagel"); + + MultiFindTextBox.Text = sb.ToString(); + string[] lines = MultiFindTextBox.Text.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string line in lines) + { + AddMarker(line); + } + + } + + + + + + + private void LoadSettings() + { + var s = Settings.Default; + WindowState = s.WindowMaximized ? FormWindowState.Maximized : WindowState; + FullScreenCheckBox.Checked = s.FullScreen; + WireframeCheckBox.Checked = s.Wireframe; + HDRRenderingCheckBox.Checked = s.HDR; + ShadowsCheckBox.Checked = s.Shadows; + SkydomeCheckBox.Checked = s.Skydome; + TimedEntitiesCheckBox.Checked = s.ShowTimedEntities; + CollisionMeshesCheckBox.Checked = s.ShowCollisionMeshes; + CollisionMeshRangeTrackBar.Value = s.CollisionMeshRange; + DynamicLODCheckBox.Checked = s.DynamicLOD; + DetailTrackBar.Value = s.DetailDist; + WaitForChildrenCheckBox.Checked = s.WaitForChildren; + RenderModeComboBox.SelectedIndex = Math.Max(RenderModeComboBox.FindString(s.RenderMode), 0); + TextureSamplerComboBox.SelectedIndex = Math.Max(TextureSamplerComboBox.FindString(s.RenderTextureSampler), 0); + TextureCoordsComboBox.SelectedIndex = Math.Max(TextureCoordsComboBox.FindString(s.RenderTextureSamplerCoord), 0); + MarkerStyleComboBox.SelectedIndex = Math.Max(MarkerStyleComboBox.FindString(s.MarkerStyle), 0); + LocatorStyleComboBox.SelectedIndex = Math.Max(LocatorStyleComboBox.FindString(s.LocatorStyle), 0); + MarkerDepthClipCheckBox.Checked = s.MarkerDepthClip; + AnisotropicFilteringCheckBox.Checked = s.AnisotropicFiltering; + BoundsStyleComboBox.SelectedIndex = Math.Max(BoundsStyleComboBox.FindString(s.BoundsStyle), 0); + BoundsDepthClipCheckBox.Checked = s.BoundsDepthClip; + BoundsRangeTrackBar.Value = s.BoundsRange; + ErrorConsoleCheckBox.Checked = s.ShowErrorConsole; + StatusBarCheckBox.Checked = s.ShowStatusBar; + + EnableModsCheckBox.Checked = s.EnableMods; + DlcLevelComboBox.Text = s.DLC; + gameFileCache.SelectedDlc = s.DLC; + EnableDlcCheckBox.Checked = !string.IsNullOrEmpty(s.DLC); + } + private void SaveSettings() + { + var s = Settings.Default; + s.WindowMaximized = (WindowState == FormWindowState.Maximized); + s.FullScreen = FullScreenCheckBox.Checked; + s.Wireframe = WireframeCheckBox.Checked; + s.HDR = HDRRenderingCheckBox.Checked; + s.Shadows = ShadowsCheckBox.Checked; + s.Skydome = SkydomeCheckBox.Checked; + s.ShowTimedEntities = TimedEntitiesCheckBox.Checked; + s.ShowCollisionMeshes = CollisionMeshesCheckBox.Checked; + s.CollisionMeshRange = CollisionMeshRangeTrackBar.Value; + s.DynamicLOD = DynamicLODCheckBox.Checked; + s.DetailDist = DetailTrackBar.Value; + s.WaitForChildren = WaitForChildrenCheckBox.Checked; + s.RenderMode = RenderModeComboBox.Text; + s.RenderTextureSampler = TextureSamplerComboBox.Text; + s.RenderTextureSamplerCoord = TextureCoordsComboBox.Text; + s.MarkerStyle = MarkerStyleComboBox.Text; + s.LocatorStyle = LocatorStyleComboBox.Text; + s.MarkerDepthClip = MarkerDepthClipCheckBox.Checked; + s.AnisotropicFiltering = AnisotropicFilteringCheckBox.Checked; + s.BoundsStyle = BoundsStyleComboBox.Text; + s.BoundsDepthClip = BoundsDepthClipCheckBox.Checked; + s.BoundsRange = BoundsRangeTrackBar.Value; + s.ShowErrorConsole = ErrorConsoleCheckBox.Checked; + s.ShowStatusBar = StatusBarCheckBox.Checked; + + //additional settings from gamefilecache... + s.EnableMods = gameFileCache.EnableMods; + s.DLC = gameFileCache.EnableDlc ? gameFileCache.SelectedDlc : ""; + + s.Save(); + } + + private void ShowSettingsForm(string tab = "") + { + if (SettingsForm == null) + { + SettingsForm = new SettingsForm(this); + SettingsForm.Show(this); + } + else + { + if (SettingsForm.WindowState == FormWindowState.Minimized) + { + SettingsForm.WindowState = FormWindowState.Normal; + } + SettingsForm.Focus(); + } + if (!string.IsNullOrEmpty(tab)) + { + SettingsForm.SelectTab(tab); + } + } + public void OnSettingsFormClosed() + { + //called by the SettingsForm when it's closed. + SettingsForm = null; + } + + + + + + private void MarkUndoStart(Widget w) + { + bool hasval = false; + if (SelectedItem.EntityDef != null) hasval = true; + if (SelectedItem.CarGenerator != null) hasval = true; + if (SelectedItem.PathNode != null) hasval = true; + //if (SelectedItem.NavPoly != null) hasval = true; + if (SelectedItem.TrainTrackNode != null) hasval = true; + if (SelectedItem.ScenarioNode != null) hasval = true; + if (!hasval) return; + if (Widget is TransformWidget) + { + UndoStartPosition = Widget.Position; + UndoStartRotation = Widget.Rotation; + UndoStartScale = Widget.Scale; + } + } + private void MarkUndoEnd(Widget w) + { + bool hasval = false; + if (SelectedItem.EntityDef != null) hasval = true; + if (SelectedItem.CarGenerator != null) hasval = true; + if (SelectedItem.PathNode != null) hasval = true; + //if (SelectedItem.NavPoly != null) hasval = true; + if (SelectedItem.TrainTrackNode != null) hasval = true; + if (SelectedItem.ScenarioNode != null) hasval = true; + if (!hasval) return; + var ent = SelectedItem.EntityDef; + var cargen = SelectedItem.CarGenerator; + var pathnode = SelectedItem.PathNode; + var trainnode = SelectedItem.TrainTrackNode; + var scenarionode = SelectedItem.ScenarioNode; + TransformWidget tw = Widget as TransformWidget; + UndoStep s = null; + if (tw != null) + { + if (ent != null) + { + if (EditEntityPivot) + { + switch (tw.Mode) + { + case WidgetMode.Position: s = new EntityPivotPositionUndoStep(ent, UndoStartPosition); break; + case WidgetMode.Rotation: s = new EntityPivotRotationUndoStep(ent, UndoStartRotation); break; + } + } + else + { + switch (tw.Mode) + { + case WidgetMode.Position: s = new EntityPositionUndoStep(ent, UndoStartPosition); break; + case WidgetMode.Rotation: s = new EntityRotationUndoStep(ent, UndoStartRotation); break; + case WidgetMode.Scale: s = new EntityScaleUndoStep(ent, UndoStartScale); break; + } + } + } + else if (cargen != null) + { + switch (tw.Mode) + { + case WidgetMode.Position: s = new CarGenPositionUndoStep(cargen, UndoStartPosition); break; + case WidgetMode.Rotation: s = new CarGenRotationUndoStep(cargen, UndoStartRotation); break; + case WidgetMode.Scale: s = new CarGenScaleUndoStep(cargen, UndoStartScale); break; + } + } + else if (pathnode != null) + { + switch (tw.Mode) + { + case WidgetMode.Position: s = new PathNodePositionUndoStep(pathnode, UndoStartPosition, this, ProjectForm); break; + } + } + else if (trainnode != null) + { + switch (tw.Mode) + { + case WidgetMode.Position: s = new TrainTrackNodePositionUndoStep(trainnode, UndoStartPosition, this, ProjectForm); break; + } + } + else if (scenarionode != null) + { + switch (tw.Mode) + { + case WidgetMode.Position: s = new ScenarioNodePositionUndoStep(scenarionode, UndoStartPosition, this, ProjectForm); break; + case WidgetMode.Rotation: s = new ScenarioNodeRotationUndoStep(scenarionode, UndoStartRotation, this, ProjectForm); break; + } + } + } + if (s != null) + { + RedoSteps.Clear(); + UndoSteps.Push(s); + UpdateUndoUI(); + } + } + private void Undo() + { + if (UndoSteps.Count == 0) return; + var s = UndoSteps.Pop(); + RedoSteps.Push(s); + + s.Undo(this, ProjectForm, ref SelectedItem); + + UpdateUndoUI(); + } + private void Redo() + { + if (RedoSteps.Count == 0) return; + var s = RedoSteps.Pop(); + UndoSteps.Push(s); + + s.Redo(this, ProjectForm, ref SelectedItem); + + UpdateUndoUI(); + } + private void UpdateUndoUI() + { + ToolbarUndoButton.DropDownItems.Clear(); + ToolbarRedoButton.DropDownItems.Clear(); + int i = 0; + foreach (var step in UndoSteps) + { + var button = ToolbarUndoButton.DropDownItems.Add(step.ToString()); + button.Tag = step; + button.Click += ToolbarUndoListButton_Click; + i++; + if (i >= 10) break; + } + i = 0; + foreach (var step in RedoSteps) + { + var button = ToolbarRedoButton.DropDownItems.Add(step.ToString()); + button.Tag = step; + button.Click += ToolbarRedoListButton_Click; + i++; + if (i >= 10) break; + } + ToolbarUndoButton.Enabled = (UndoSteps.Count > 0); + ToolbarRedoButton.Enabled = (RedoSteps.Count > 0); + } + + + + private void EnableCacheDependentUI() + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { EnableCacheDependentUI(); })); + } + else + { + ToolbarNewButton.Enabled = true; + ToolbarOpenButton.Enabled = true; + ToolbarProjectWindowButton.Enabled = true; + ToolsMenuProjectWindow.Enabled = true; + ToolsMenuJenkInd.Enabled = true; + } + } + catch { } + } + private void EnableDLCModsUI() + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { EnableDLCModsUI(); })); + } + else + { + EnableDlcCheckBox.Enabled = true; + EnableModsCheckBox.Enabled = true; + DlcLevelComboBox.Enabled = true; + } + } + catch { } + } + + + public void SetCurrentSaveItem(string filename) + { + bool enable = !string.IsNullOrEmpty(filename); + ToolbarSaveButton.ToolTipText = enable ? ("Save " + filename) : "Save"; + ToolbarSaveButton.Enabled = enable; + ToolbarSaveAllButton.Enabled = enable; + } + public void EnableYmapUI(bool enable, string filename) + { + string type = "entity"; + switch (SelectionMode) + { + case MapSelectionMode.CarGenerator: type = "car generator"; break; + } + + ToolbarAddItemButton.ToolTipText = "Add " + type + (enable ? (" to " + filename) : ""); + ToolbarAddItemButton.Enabled = enable; + //ToolbarDeleteEntityButton.Enabled = enable; + ToolbarPasteButton.Enabled = (CopiedEntity != null) && enable; + } + public void EnableYndUI(bool enable, string filename) + { + string type = "node"; + switch (SelectionMode) + { + case MapSelectionMode.Path: type = "node"; break; + } + + if (enable) //only do something if a ynd is selected - EnableYmapUI will handle the no selection case.. + { + ToolbarAddItemButton.ToolTipText = "Add " + type + (enable ? (" to " + filename) : ""); + ToolbarAddItemButton.Enabled = enable; + //ToolbarDeleteEntityButton.Enabled = enable; + ToolbarPasteButton.Enabled = (CopiedPathNode != null) && enable; + } + } + public void EnableYnvUI(bool enable, string filename) + { + string type = "polygon"; + switch (SelectionMode) + { + case MapSelectionMode.NavMesh: type = "polygon"; break; + } + + if (enable) //only do something if a ynv is selected - EnableYmapUI will handle the no selection case.. + { + ToolbarAddItemButton.ToolTipText = "Add " + type + (enable ? (" to " + filename) : ""); + ToolbarAddItemButton.Enabled = enable; + //ToolbarDeleteEntityButton.Enabled = enable; + ToolbarPasteButton.Enabled = (CopiedNavPoly != null) && enable; + } + } + public void EnableTrainsUI(bool enable, string filename) + { + string type = "node"; + switch (SelectionMode) + { + case MapSelectionMode.TrainTrack: type = "node"; break; + } + + if (enable) //only do something if a track is selected - EnableYmapUI will handle the no selection case.. + { + ToolbarAddItemButton.ToolTipText = "Add " + type + (enable ? (" to " + filename) : ""); + ToolbarAddItemButton.Enabled = enable; + //ToolbarDeleteEntityButton.Enabled = enable; + ToolbarPasteButton.Enabled = false;// (CopiedTrainNode != null) && enable; + } + } + public void EnableScenarioUI(bool enable, string filename) + { + string type = "scenario point"; + switch (SelectionMode) + { + case MapSelectionMode.Scenario: type = "scenario point"; break; + } + + if (enable) //only do something if a scenario is selected - EnableYmapUI will handle the no selection case.. + { + ToolbarAddItemButton.ToolTipText = "Add " + type + (enable ? (" to " + filename) : ""); + ToolbarAddItemButton.Enabled = enable; + //ToolbarDeleteEntityButton.Enabled = enable; + ToolbarPasteButton.Enabled = (CopiedScenarioNode != null) && enable; + } + } + + + private void New() + { + ShowProjectForm(); + + if (ProjectForm.IsProjectLoaded) + { + ProjectForm.NewYmap(); + } + else + { + ProjectForm.NewProject(); + } + } + private void NewProject() + { + ShowProjectForm(); + ProjectForm.NewProject(); + } + private void NewYmap() + { + ShowProjectForm(); + ProjectForm.NewYmap(); + } + private void NewYnd() + { + ShowProjectForm(); + ProjectForm.NewYnd(); + } + private void NewYnv() + { + ShowProjectForm(); + ProjectForm.NewYnv(); + } + private void NewTrainTrack() + { + ShowProjectForm(); + ProjectForm.NewTrainTrack(); + } + private void NewScenario() + { + ShowProjectForm(); + ProjectForm.NewScenario(); + } + private void Open() + { + ShowProjectForm(); + + if (ProjectForm.IsProjectLoaded) + { + ProjectForm.OpenYmap(); + } + else + { + ProjectForm.OpenProject(); + } + } + private void OpenProject() + { + ShowProjectForm(); + ProjectForm.OpenProject(); + } + private void OpenYmap() + { + ShowProjectForm(); + ProjectForm.OpenYmap(); + } + private void OpenYnd() + { + ShowProjectForm(); + ProjectForm.OpenYnd(); + } + private void OpenYnv() + { + ShowProjectForm(); + ProjectForm.OpenYnv(); + } + private void OpenTrainTrack() + { + ShowProjectForm(); + ProjectForm.OpenTrainTrack(); + } + private void OpenScenario() + { + ShowProjectForm(); + ProjectForm.OpenScenario(); + } + private void Save() + { + if (ProjectForm == null) return; + ProjectForm.Save(); + } + private void SaveAll() + { + if (ProjectForm == null) return; + ProjectForm.SaveAll(); + } + + + private void AddItem() + { + switch (SelectionMode) + { + case MapSelectionMode.Entity: AddEntity(); break; + case MapSelectionMode.CarGenerator: AddCarGen(); break; + case MapSelectionMode.Path: AddPathNode(); break; + case MapSelectionMode.NavMesh: AddNavPoly(); break; + case MapSelectionMode.TrainTrack: AddTrainNode(); break; + case MapSelectionMode.Scenario: AddScenarioNode(); break; + } + } + private void DeleteItem() + { + if (SelectedItem.EntityDef != null) DeleteEntity(); + else if (SelectedItem.CarGenerator != null) DeleteCarGen(); + else if (SelectedItem.PathNode != null) DeletePathNode(); + else if (SelectedItem.NavPoly != null) DeleteNavPoly(); + else if (SelectedItem.TrainTrackNode != null) DeleteTrainNode(); + else if (SelectedItem.ScenarioNode != null) DeleteScenarioNode(); + } + private void CopyItem() + { + if (SelectedItem.EntityDef != null) CopyEntity(); + else if (SelectedItem.CarGenerator != null) CopyCarGen(); + else if (SelectedItem.PathNode != null) CopyPathNode(); + else if (SelectedItem.NavPoly != null) CopyNavPoly(); + else if (SelectedItem.TrainTrackNode != null) CopyTrainNode(); + else if (SelectedItem.ScenarioNode != null) CopyScenarioNode(); + } + private void PasteItem() + { + if (CopiedEntity != null) PasteEntity(); + else if (CopiedCarGen != null) PasteCarGen(); + else if (CopiedPathNode != null) PastePathNode(); + else if (CopiedNavPoly != null) PasteNavPoly(); + else if (CopiedTrainNode != null) PasteTrainNode(); + else if (CopiedScenarioNode != null) PasteScenarioNode(); + } + private void CloneItem() + { + if (SelectedItem.EntityDef != null) CloneEntity(); + else if (SelectedItem.CarGenerator != null) CloneCarGen(); + else if (SelectedItem.PathNode != null) ClonePathNode(); + else if (SelectedItem.NavPoly != null) CloneNavPoly(); + else if (SelectedItem.TrainTrackNode != null) CloneTrainNode(); + else if (SelectedItem.ScenarioNode != null) CloneScenarioNode(); + } + + private void AddEntity() + { + if (ProjectForm == null) return; + ProjectForm.NewEntity(); + } + private void DeleteEntity() + { + var ent = SelectedItem.EntityDef; + if (ent == null) return; + + if ((ProjectForm != null) && (ProjectForm.IsCurrentEntity(ent))) + { + if (!ProjectForm.DeleteEntity()) + { + //MessageBox.Show("Unable to delete this entity from the current project. Make sure the entity's ymap exists in the current project."); + } + else + { + SelectItem(null, null, null); + } + } + else + { + //project not open, or entity not selected there, just remove the entity from the ymap... + var ymap = ent.Ymap; + if (ymap == null) + { + MessageBox.Show("Sorry, deleting interior entities is not currently supported."); + } + else if (!ymap.RemoveEntity(ent)) + { + MessageBox.Show("Unable to remove entity."); + } + else + { + SelectItem(null, null, null); + } + } + } + private void CopyEntity() + { + CopiedEntity = SelectedItem.EntityDef; + ToolbarPasteButton.Enabled = (CopiedEntity != null) && ToolbarAddItemButton.Enabled; + } + private void PasteEntity() + { + if (CopiedEntity == null) return; + if (ProjectForm == null) return; + ProjectForm.NewEntity(CopiedEntity); + } + private void CloneEntity() + { + if (SelectedItem.EntityDef == null) return; + if (ProjectForm == null) return; + ProjectForm.NewEntity(SelectedItem.EntityDef, true); + } + + private void AddCarGen() + { + if (ProjectForm == null) return; + ProjectForm.NewCarGen(); + } + private void DeleteCarGen() + { + var cargen = SelectedItem.CarGenerator; + if (cargen == null) return; + + if ((ProjectForm != null) && (ProjectForm.IsCurrentCarGen(cargen))) + { + if (!ProjectForm.DeleteCarGen()) + { + //MessageBox.Show("Unable to delete this car generator from the current project. Make sure the car generator's ymap exists in the current project."); + } + else + { + SelectItem(null, null, null); + } + } + else + { + //project not open, or cargen not selected there, just remove the cargen from the ymap... + var ymap = cargen.Ymap; + if (!ymap.RemoveCarGen(cargen)) + { + MessageBox.Show("Unable to remove car generator."); + } + else + { + SelectItem(null, null, null); + } + } + } + private void CopyCarGen() + { + CopiedCarGen = SelectedItem.CarGenerator; + ToolbarPasteButton.Enabled = (CopiedCarGen != null) && ToolbarAddItemButton.Enabled; + } + private void PasteCarGen() + { + if (CopiedCarGen == null) return; + if (ProjectForm == null) return; + ProjectForm.NewCarGen(CopiedCarGen); + } + private void CloneCarGen() + { + if (SelectedItem.CarGenerator == null) return; + if (ProjectForm == null) return; + ProjectForm.NewCarGen(SelectedItem.CarGenerator, true); + } + + private void AddPathNode() + { + if (ProjectForm == null) return; + ProjectForm.NewPathNode(); + } + private void DeletePathNode() + { + var pathnode = SelectedItem.PathNode; + if (pathnode == null) return; + + if ((ProjectForm != null) && (ProjectForm.IsCurrentPathNode(pathnode))) + { + if (!ProjectForm.DeletePathNode()) + { + //MessageBox.Show("Unable to delete this path node from the current project. Make sure the path node's ynd exists in the current project."); + } + else + { + SelectItem(null, null, null); + } + } + else + { + //project not open, or cargen not selected there, just remove the cargen from the ymap... + var ynd = pathnode.Ynd; + if (!ynd.RemoveNode(pathnode)) + { + MessageBox.Show("Unable to remove path node."); + } + else + { + UpdatePathNodeGraphics(pathnode, false); + SelectItem(null, null, null); + } + } + } + private void CopyPathNode() + { + CopiedPathNode = SelectedItem.PathNode; + ToolbarPasteButton.Enabled = (CopiedPathNode != null) && ToolbarAddItemButton.Enabled; + } + private void PastePathNode() + { + if (CopiedPathNode == null) return; + if (ProjectForm == null) return; + ProjectForm.NewPathNode(CopiedPathNode); + } + private void ClonePathNode() + { + if (SelectedItem.PathNode == null) return; + if (ProjectForm == null) return; + ProjectForm.NewPathNode(SelectedItem.PathNode, true); + } + + private void AddNavPoly() + { + if (ProjectForm == null) return; + ProjectForm.NewNavPoly(); + } + private void DeleteNavPoly() + { + var navpoly = SelectedItem.NavPoly; + if (navpoly == null) return; + + if ((ProjectForm != null) && (ProjectForm.IsCurrentNavPoly(navpoly))) + { + if (!ProjectForm.DeleteNavPoly()) + { + //MessageBox.Show("Unable to delete this nav poly from the current project. Make sure the nav poly's ynv exists in the current project."); + } + else + { + SelectItem(null, null, null); + } + } + else + { + //project not open, or nav poly not selected there, just remove the poly from the ynv... + var ynv = navpoly.Ynv; + if (!ynv.RemovePoly(navpoly)) + { + MessageBox.Show("Unable to remove nav poly. NavMesh editing TODO!"); + } + else + { + UpdateNavPolyGraphics(navpoly, false); + SelectItem(null, null, null); + } + } + } + private void CopyNavPoly() + { + CopiedNavPoly = SelectedItem.NavPoly; + ToolbarPasteButton.Enabled = (CopiedNavPoly != null) && ToolbarAddItemButton.Enabled; + } + private void PasteNavPoly() + { + if (CopiedNavPoly == null) return; + if (ProjectForm == null) return; + ProjectForm.NewNavPoly(CopiedNavPoly); + } + private void CloneNavPoly() + { + if (SelectedItem.NavPoly == null) return; + if (ProjectForm == null) return; + ProjectForm.NewNavPoly(SelectedItem.NavPoly, true); + } + + private void AddTrainNode() + { + if (ProjectForm == null) return; + ProjectForm.NewTrainNode(); + } + private void DeleteTrainNode() + { + var trainnode = SelectedItem.TrainTrackNode; + if (trainnode == null) return; + + if ((ProjectForm != null) && (ProjectForm.IsCurrentTrainNode(trainnode))) + { + if (!ProjectForm.DeleteTrainNode()) + { + //MessageBox.Show("Unable to delete this train track node from the current project. Make sure the path train track file exists in the current project."); + } + else + { + SelectItem(null, null, null); + } + } + else + { + //project not open, or train node not selected there, just remove the node from the train track... + var track = trainnode.Track; + if (!track.RemoveNode(trainnode)) + { + MessageBox.Show("Unable to remove train track node."); + } + else + { + UpdateTrainTrackNodeGraphics(trainnode, false); + SelectItem(null, null, null); + } + } + } + private void CopyTrainNode() + { + CopiedTrainNode = SelectedItem.TrainTrackNode; + ToolbarPasteButton.Enabled = (CopiedTrainNode != null) && ToolbarAddItemButton.Enabled; + } + private void PasteTrainNode() + { + if (CopiedTrainNode == null) return; + if (ProjectForm == null) return; + ProjectForm.NewTrainNode(CopiedTrainNode); + } + private void CloneTrainNode() + { + if (SelectedItem.TrainTrackNode == null) return; + if (ProjectForm == null) return; + ProjectForm.NewTrainNode(SelectedItem.TrainTrackNode, true); + } + + private void AddScenarioNode() + { + if (ProjectForm == null) return; + ProjectForm.NewScenarioNode(); + } + private void DeleteScenarioNode() + { + var scenariopt = SelectedItem.ScenarioNode; + if (scenariopt == null) return; + + if ((ProjectForm != null) && (ProjectForm.IsCurrentScenarioNode(scenariopt))) + { + if (!ProjectForm.DeleteScenarioNode()) + { + //MessageBox.Show("Unable to delete this scenario point from the current project. Make sure the scenario file exists in the current project."); + } + else + { + SelectItem(null, null, null); + } + } + else + { + //project not open, or scenario point not selected there, just remove the point from the region... + var region = scenariopt.Region.Ymt.ScenarioRegion; + if (!region.RemoveNode(scenariopt)) + { + MessageBox.Show("Unable to remove scenario point."); + } + else + { + UpdateScenarioGraphics(scenariopt.Ymt, false); + SelectItem(null, null, null); + } + } + } + private void CopyScenarioNode() + { + CopiedScenarioNode = SelectedItem.ScenarioNode; + ToolbarPasteButton.Enabled = (CopiedScenarioNode != null) && ToolbarAddItemButton.Enabled; + } + private void PasteScenarioNode() + { + if (CopiedScenarioNode == null) return; + if (ProjectForm == null) return; + ProjectForm.NewScenarioNode(CopiedScenarioNode); + } + private void CloneScenarioNode() + { + if (SelectedItem.ScenarioNode == null) return; + if (ProjectForm == null) return; + ProjectForm.NewScenarioNode(SelectedItem.ScenarioNode, true); + } + + + private void SetMouseSelect(bool enable) + { + MouseSelectEnabled = enable; + MouseSelectCheckBox.Checked = enable; + ToolbarSelectButton.Checked = enable; + + if (InfoForm != null) + { + InfoForm.SetSelectionMode(SelectionModeStr, MouseSelectEnabled); + } + } + + private void SetWidgetMode(string mode) + { + ToolbarMoveButton.Checked = false; + ToolbarRotateButton.Checked = false; + ToolbarScaleButton.Checked = false; + + lock (rendersyncroot) + { + switch (mode) + { + case "Default": + Widget.Mode = WidgetMode.Default; + iseditmode = false; + break; + case "Position": + Widget.Mode = WidgetMode.Position; + iseditmode = true; + ToolbarMoveButton.Checked = true; + break; + case "Rotation": + Widget.Mode = WidgetMode.Rotation; + iseditmode = true; + ToolbarRotateButton.Checked = true; + break; + case "Scale": + Widget.Mode = WidgetMode.Scale; + iseditmode = true; + ToolbarScaleButton.Checked = true; + break; + } + } + } + + private void SetWidgetSpace(string space) + { + foreach (var child in ToolbarTransformSpaceButton.DropDownItems) + { + var childi = child as ToolStripMenuItem; + if (childi != null) + { + childi.Checked = false; + } + } + + lock (rendersyncroot) + { + switch (space) + { + case "World space": + Widget.ObjectSpace = false; + ToolbarTransformSpaceButton.Image = ToolbarWorldSpaceButton.Image; + ToolbarWorldSpaceButton.Checked = true; + break; + case "Object space": + Widget.ObjectSpace = true; + ToolbarTransformSpaceButton.Image = ToolbarObjectSpaceButton.Image; + ToolbarObjectSpaceButton.Checked = true; + break; + } + } + } + + private void ToggleWidgetSpace() + { + SetWidgetSpace(Widget.ObjectSpace ? "World space" : "Object space"); + } + + + + private void SetFullscreen(bool fullscreen) + { + if (fullscreen) + { + FormBorderStyle = FormBorderStyle.None; + WindowState = FormWindowState.Maximized; + } + else + { + WindowState = FormWindowState.Normal; + FormBorderStyle = FormBorderStyle.Sizable; + } + } + + private void SetBoundsMode(string modestr) + { + BoundsShaderMode mode = BoundsShaderMode.None; + switch (modestr) + { + case "Boxes": + mode = BoundsShaderMode.Box; + break; + case "Spheres": + mode = BoundsShaderMode.Sphere; + break; + } + boundsmode = mode; + } + + + + private void SetSelectionMode(string modestr) + { + + foreach (var child in ToolbarSelectButton.DropDownItems) + { + var childi = child as ToolStripMenuItem; + if (childi != null) + { + childi.Checked = false; + } + } + + MapSelectionMode mode = MapSelectionMode.Entity; + switch (modestr) + { + default: + case "Entity": + mode = MapSelectionMode.Entity; + ToolbarSelectEntityButton.Checked = true; + break; + case "Entity Extension": + mode = MapSelectionMode.EntityExtension; + ToolbarSelectEntityExtensionButton.Checked = true; + break; + case "Archetype Extension": + mode = MapSelectionMode.ArchetypeExtension; + ToolbarSelectArchetypeExtensionButton.Checked = true; + break; + case "Time Cycle Modifier": + mode = MapSelectionMode.TimeCycleModifier; + ToolbarSelectTimeCycleModifierButton.Checked = true; + break; + case "Car Generator": + mode = MapSelectionMode.CarGenerator; + ToolbarSelectCarGeneratorButton.Checked = true; + break; + case "Grass": + mode = MapSelectionMode.Grass; + ToolbarSelectGrassButton.Checked = true; + break; + case "Water Quad": + mode = MapSelectionMode.WaterQuad; + ToolbarSelectWaterQuadButton.Checked = true; + break; + case "Collision": + mode = MapSelectionMode.Collision; + ToolbarSelectCollisionButton.Checked = true; + break; + case "Nav Mesh": + mode = MapSelectionMode.NavMesh; + ToolbarSelectNavMeshButton.Checked = true; + break; + case "Path": + mode = MapSelectionMode.Path; + ToolbarSelectPathButton.Checked = true; + break; + case "Train Track": + mode = MapSelectionMode.TrainTrack; + ToolbarSelectTrainTrackButton.Checked = true; + break; + case "Distant Lod Lights": + mode = MapSelectionMode.DistantLodLights; + ToolbarSelectDistantLodLightsButton.Checked = true; + break; + case "Mlo Instance": + mode = MapSelectionMode.MloInstance; + ToolbarSelectMloInstanceButton.Checked = true; + break; + case "Scenario": + mode = MapSelectionMode.Scenario; + ToolbarSelectScenarioButton.Checked = true; + break; + + } + SelectionMode = mode; + SelectionModeStr = modestr; + + if (SelectionModeComboBox.Text != modestr) + { + SelectionModeComboBox.Text = modestr; + } + + if (InfoForm != null) + { + InfoForm.SetSelectionMode(modestr, MouseSelectEnabled); + } + } + + + + private void SetCameraMode(string modestr) + { + foreach (var child in ToolbarCameraModeButton.DropDownItems) + { + var childi = child as ToolStripMenuItem; + if (childi != null) + { + childi.Checked = false; + } + } + + lock (rendersyncroot) + { + switch (modestr) + { + case "Perspective": + camera.IsOrthographic = false; + MapViewEnabled = false; + camera.UpdateProj = true; + ToolbarCameraModeButton.Image = ToolbarCameraPerspectiveButton.Image; + ToolbarCameraPerspectiveButton.Checked = true; + break; + case "Orthographic": + camera.IsOrthographic = true; + MapViewEnabled = false; + ToolbarCameraModeButton.Image = ToolbarCameraOrthographicButton.Image; + ToolbarCameraOrthographicButton.Checked = true; + break; + case "2D Map": + camera.IsOrthographic = true; + MapViewEnabled = true; + ToolbarCameraModeButton.Image = ToolbarCameraMapViewButton.Image; + ToolbarCameraMapViewButton.Checked = true; + break; + } + camera.IsMapView = MapViewEnabled; + } + FieldOfViewTrackBar.Enabled = !MapViewEnabled; + MapViewDetailTrackBar.Enabled = MapViewEnabled; + + + if (CameraModeComboBox.Text != modestr) + { + CameraModeComboBox.Text = modestr; + } + + + } + + private void ToggleCameraMode() + { + SetCameraMode(MapViewEnabled ? "Perspective" : "2D Map"); + } + + + private void ToggleToolbar() + { + ToolbarPanel.Visible = !ToolbarPanel.Visible; + ShowToolbarCheckBox.Checked = ToolbarPanel.Visible; + } + + + private void StatsUpdateTimer_Tick(object sender, EventArgs e) + { + int rgc = (shaders != null) ? shaders.RenderedGeometries : 0; + int crc = renderableCache.LoadedRenderableCount; + int ctc = renderableCache.LoadedTextureCount; + int tcrc = renderableCache.MemCachedRenderableCount; + int tctc = renderableCache.MemCachedTextureCount; + long vr = renderableCache.TotalGraphicsMemoryUse + (shaders != null ? shaders.TotalGraphicsMemoryUse : 0); + string vram = TextUtil.GetBytesReadable(vr); + //StatsLabel.Text = string.Format("Drawn: {0} geom, Loaded: {1}/{5} dr, {2}/{6} tx, Vram: {3}, Fps: {4}", rgc, crc, ctc, vram, fps, tcrc, tctc); + StatsLabel.Text = string.Format("Drawn: {0} geom, Loaded: {1} dr, {2} tx, Vram: {3}, Fps: {4}", rgc, crc, ctc, vram, fps); + + if (timerunning) + { + float fv = timeofday * 60.0f; + TimeOfDayTrackBar.Value = (int)fv; + UpdateTimeOfDayLabel(); + } + + CameraPositionTextBox.Text = FloatUtil.GetVector3String(camera.Position, "0.##"); + } + + private void WorldForm_Load(object sender, EventArgs e) + { + Init(); + } + + private void WorldForm_FormClosing(object sender, FormClosingEventArgs e) + { + //if (ProjectForm != null) + //{ + // if (MessageBox.Show("Are you sure you want to quit CodeWalker?", "Confirm quit", MessageBoxButtons.YesNo) != DialogResult.Yes) + // { + // e.Cancel = true; //unfortunately this doesn't catch the event early enough! :( + // } + //} + } + + private void WorldForm_MouseDown(object sender, MouseEventArgs e) + { + switch (e.Button) + { + case MouseButtons.Left: MouseLButtonDown = true; break; + case MouseButtons.Right: MouseRButtonDown = true; break; + } + + MouseDownPoint = e.Location; + MouseLastPoint = MouseDownPoint; + + if (ControlMode == WorldControlMode.Free) + { + if (MouseLButtonDown) + { + if (MousedMarker != null) + { + if (MousedMarker.IsMovable) + { + GrabbedMarker = MousedMarker; + } + else + { + SelectedMarker = MousedMarker; + ShowMarkerSelectionInfo(SelectedMarker); + } + if (GrabbedWidget != null) + { + GrabbedWidget.IsDragging = false; + GrabbedWidget = null; + } + } + else + { + if (ShowWidget && Widget.IsUnderMouse) + { + GrabbedWidget = Widget; + GrabbedWidget.IsDragging = true; + if (ShiftPressed) + { + CloneItem(); + } + MarkUndoStart(GrabbedWidget); + } + else + { + if (GrabbedWidget != null) + { + GrabbedWidget.IsDragging = false; + GrabbedWidget = null; + } + + if (CtrlPressed) + { + SpawnTestEntity(); + } + + } + GrabbedMarker = null; + } + } + + if (MouseRButtonDown) + { + SelectMousedItem(); + } + } + else + { + lock (MouseControlSyncRoot) + { + MouseControlButtons |= e.Button; + } + } + + MouseX = e.X; //to stop jumps happening on mousedown, sometimes the last MouseMove event was somewhere else... (eg after clicked a menu) + MouseY = e.Y; + } + + private void WorldForm_MouseUp(object sender, MouseEventArgs e) + { + switch (e.Button) + { + case MouseButtons.Left: MouseLButtonDown = false; break; + case MouseButtons.Right: MouseRButtonDown = false; break; + } + + lock (MouseControlSyncRoot) + { + MouseControlButtons &= ~e.Button; + } + + + + if (e.Button == MouseButtons.Left) + { + GrabbedMarker = null; + if (GrabbedWidget != null) + { + MarkUndoEnd(GrabbedWidget); + GrabbedWidget.IsDragging = false; + GrabbedWidget = null; + } + if ((e.Location == MouseDownPoint) && (MousedMarker == null)) + { + //was clicked. but not on a marker... deselect and hide the panel + SelectedMarker = null; + HideMarkerSelectionInfo(); + } + } + + } + + private void WorldForm_MouseMove(object sender, MouseEventArgs e) + { + int dx = e.X - MouseX; + int dy = e.Y - MouseY; + + if (ControlMode == WorldControlMode.Free) + { + if (MouseLButtonDown) + { + if (GrabbedMarker == null) + { + if (GrabbedWidget == null) + { + if (MapViewEnabled == false) + { + camera.MouseRotate(dx, dy); + } + else + { + //need to move the camera entity XY with mouse in mapview mode... + MapViewDragX += dx; + MapViewDragY += dy; + } + } + else + { + //grabbed widget will move itself in Update() when IsDragging==true + } + } + else + { + //move the grabbed marker... + //float uptx = (CurrentMap != null) ? CurrentMap.UnitsPerTexelX : 1.0f; + //float upty = (CurrentMap != null) ? CurrentMap.UnitsPerTexelY : 1.0f; + //Vector3 wpos = GrabbedMarker.WorldPos; + //wpos.X += dx * uptx; + //wpos.Y += dy * upty; + //GrabbedMarker.WorldPos = wpos; + //UpdateMarkerTexturePos(GrabbedMarker); + //if (GrabbedMarker == LocatorMarker) + //{ + // LocateTextBox.Text = LocatorMarker.ToString(); + // WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString(); + // TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString(); + //} + } + } + if (MouseRButtonDown) + { + if (controllightdir) + { + lightdirx += (dx * camera.Sensitivity); + lightdiry += (dy * camera.Sensitivity); + } + else if (controltimeofday) + { + timeofday += (dx - dy) / 30.0f; + while (timeofday >= 24.0f) timeofday -= 24.0f; + while (timeofday < 0.0f) timeofday += 24.0f; + timecycle.SetTime(timeofday); + + float fv = timeofday * 60.0f; + TimeOfDayTrackBar.Value = (int)fv; + UpdateTimeOfDayLabel(); + } + } + + MouseX = e.X; + MouseY = e.Y; + MouseLastPoint = e.Location; + + } + else + { + lock (MouseControlSyncRoot) + { + MouseControlX += dx; + MouseControlY += dy; + //MouseControlButtons = e.Button; + } + var newpos = PointToScreen(MouseLastPoint); + if (Cursor.Position != newpos) + { + Cursor.Position = newpos; + return; + } + } + + + + MousedMarker = FindMousedMarker(); + + if (Cursor != Cursors.WaitCursor) + { + if (MousedMarker != null) + { + if (MousedMarker.IsMovable) + { + Cursor = Cursors.SizeAll; + } + else + { + Cursor = Cursors.Hand; + } + } + else + { + Cursor = Cursors.Default; + } + } + } + + private void WorldForm_MouseWheel(object sender, MouseEventArgs e) + { + if (e.Delta != 0) + { + if (ControlMode == WorldControlMode.Free) + { + camera.MouseZoom(e.Delta); + } + else + { + lock (MouseControlSyncRoot) + { + MouseControlWheel += e.Delta; + } + } + } + + } + + private void WorldForm_KeyDown(object sender, KeyEventArgs e) + { + if (ActiveControl is TextBox) + { + var tb = ActiveControl as TextBox; + if (!tb.ReadOnly) return; //don't move the camera when typing! + } + if (ActiveControl is ComboBox) + { + var cb = ActiveControl as ComboBox; + if (cb.DropDownStyle != ComboBoxStyle.DropDownList) return; //nontypable combobox + } + + var k = e.KeyCode; + + bool ctrl = (e.Modifiers & Keys.Control) > 0; + bool shift = (e.Modifiers & Keys.Shift) > 0; + CtrlPressed = ctrl; + ShiftPressed = shift; + + bool enablemove = (!iseditmode) || (MouseLButtonDown && (GrabbedMarker == null) && (GrabbedWidget == null)); + + enablemove = enablemove && (!ctrl); + + //WASD move the camera entity... + if (enablemove) + { + if (k == keyBindings.MoveForward) kbmovefwd = true; + if (k == keyBindings.MoveBackward) kbmovebck = true; + if (k == keyBindings.MoveLeft) kbmovelft = true; + if (k == keyBindings.MoveRight) kbmovergt = true; + if (k == keyBindings.MoveUp) kbmoveup = true; + if (k == keyBindings.MoveDown) kbmovedn = true; + if (k == keyBindings.Jump) kbjump = true; + } + + bool moving = kbmovefwd || kbmovebck || kbmovelft || kbmovergt || kbmoveup || kbmovedn || kbjump; + + + if (!ctrl) + { + if (k == keyBindings.MoveSlowerZoomIn) + { + camera.MouseZoom(1); + } + if (k == keyBindings.MoveFasterZoomOut) + { + camera.MouseZoom(-1); + } + } + + + + if (!moving) //don't trigger further actions if moving. + { + + if (!ctrl) + { + //switch widget modes and spaces. + if ((k == keyBindings.ExitEditMode)) + { + if (Widget.Mode == WidgetMode.Default) ToggleWidgetSpace(); + else SetWidgetMode("Default"); + } + if ((k == keyBindings.EditPosition))// && !enablemove) + { + if (Widget.Mode == WidgetMode.Position) ToggleWidgetSpace(); + else SetWidgetMode("Position"); + } + if ((k == keyBindings.EditRotation))// && !enablemove) + { + if (Widget.Mode == WidgetMode.Rotation) ToggleWidgetSpace(); + else SetWidgetMode("Rotation"); + } + if ((k == keyBindings.EditScale))// && !enablemove) + { + if (Widget.Mode == WidgetMode.Scale) ToggleWidgetSpace(); + else SetWidgetMode("Scale"); + } + if (k == keyBindings.ToggleMouseSelect) + { + SetMouseSelect(!MouseSelectEnabled); + } + if (k == keyBindings.ToggleToolbar) + { + ToggleToolbar(); + } + if (k == Keys.P) + { + //TEMPORARY! + SetControlMode((ControlMode == WorldControlMode.Free) ? WorldControlMode.Ped : WorldControlMode.Free); + } + } + else + { + switch (k) + { + case Keys.N: + New(); + break; + case Keys.O: + Open(); + break; + case Keys.S: + if (shift) SaveAll(); + else Save(); + break; + case Keys.Z: + Undo(); + break; + case Keys.Y: + Redo(); + break; + case Keys.C: + CopyItem(); + break; + case Keys.V: + PasteItem(); + break; + case Keys.U: + ToolsPanelShowButton.Visible = !ToolsPanelShowButton.Visible; + break; + } + } + if (k == Keys.Escape) //temporary? panic get cursor back + { + if (ControlMode != WorldControlMode.Free) SetControlMode(WorldControlMode.Free); + } + } + + if (ControlMode != WorldControlMode.Free) + { + e.Handled = true; + } + } + + private void WorldForm_KeyUp(object sender, KeyEventArgs e) + { + bool ctrl = (e.Modifiers & Keys.Control) > 0; + bool shift = (e.Modifiers & Keys.Shift) > 0; + CtrlPressed = ctrl; + ShiftPressed = shift; + + if (ActiveControl is TextBox) + { + var tb = ActiveControl as TextBox; + if (!tb.ReadOnly) return; //don't move the camera when typing! + } + if (ActiveControl is ComboBox) + { + var cb = ActiveControl as ComboBox; + if (cb.DropDownStyle != ComboBoxStyle.DropDownList) return; //non-typable combobox + } + + + var k = e.KeyCode; + if (k == keyBindings.MoveForward) kbmovefwd = false; + if (k == keyBindings.MoveBackward) kbmovebck = false; + if (k == keyBindings.MoveLeft) kbmovelft = false; + if (k == keyBindings.MoveRight) kbmovergt = false; + if (k == keyBindings.MoveUp) kbmoveup = false; + if (k == keyBindings.MoveDown) kbmovedn = false; + if (k == keyBindings.Jump) kbjump = false; + + + if (ControlMode != WorldControlMode.Free) + { + e.Handled = true; + } + } + + private void ViewModeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + bool prevmodel = !(rendermaps || renderworld); + string mode = (string)ViewModeComboBox.SelectedItem; + switch (mode) + { + case "World view": + rendermaps = false; + renderworld = true; + ViewTabControl.SelectedTab = ViewWorldTabPage; + break; + case "Ymap view": + rendermaps = true; + renderworld = false; + ViewTabControl.SelectedTab = ViewYmapsTabPage; + break; + case "Model view": + rendermaps = false; + renderworld = false; + ViewTabControl.SelectedTab = ViewModelTabPage; + break; + } + + if ((camera == null) || (camera.FollowEntity == null)) return; + if (rendermaps || renderworld) + { + if (prevmodel) //only change location if the last mode was model mode + { + camera.FollowEntity.Position = prevworldpos; + } + } + else + { + prevworldpos = camera.FollowEntity.Position; + camera.FollowEntity.Position = new Vector3(0.0f, 0.0f, 0.0f); + } + } + + private void ModelComboBox_TextUpdate(object sender, EventArgs e) + { + modelname = ModelComboBox.Text; + } + + private void ModelComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + modelname = ModelComboBox.Text; + } + + private void YmapsTextBox_TextChanged(object sender, EventArgs e) + { + ymaplist = YmapsTextBox.Text.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + } + + private void ToolsPanelHideButton_Click(object sender, EventArgs e) + { + ToolsPanel.Visible = false; + ToolsPanelShowButton.Focus(); + } + + private void ToolsPanelShowButton_Click(object sender, EventArgs e) + { + ToolsPanel.Visible = true; + ToolsPanelHideButton.Focus(); + } + + private void WireframeCheckBox_CheckedChanged(object sender, EventArgs e) + { + shaders.wireframe = WireframeCheckBox.Checked; + } + + private void GrassCheckBox_CheckedChanged(object sender, EventArgs e) + { + rendergrass = GrassCheckBox.Checked; + } + + private void TimedEntitiesCheckBox_CheckedChanged(object sender, EventArgs e) + { + lock (rendersyncroot) + { + rendertimedents = TimedEntitiesCheckBox.Checked; + } + } + + private void TimedEntitiesAlwaysOnCheckBox_CheckedChanged(object sender, EventArgs e) + { + rendertimedentsalways = TimedEntitiesAlwaysOnCheckBox.Checked; + } + + private void InteriorsCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderinteriors = InteriorsCheckBox.Checked; + } + + private void WaterQuadsCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderwaterquads = WaterQuadsCheckBox.Checked; + } + + private void ProxiesCheckBox_CheckedChanged(object sender, EventArgs e) + { + lock (rendersyncroot) + { + renderproxies = ProxiesCheckBox.Checked; + } + } + + private void PathsCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderpaths = PathsCheckBox.Checked; + } + + private void PathBoundsCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderpathbounds = PathBoundsCheckBox.Checked; + } + + private void TrainPathsCheckBox_CheckedChanged(object sender, EventArgs e) + { + rendertraintracks = TrainPathsCheckBox.Checked; + } + + private void NavMeshesCheckBox_CheckedChanged(object sender, EventArgs e) + { + rendernavmeshes = NavMeshesCheckBox.Checked; + } + + private void PathsDepthClipCheckBox_CheckedChanged(object sender, EventArgs e) + { + shaders.PathsDepthClip = PathsDepthClipCheckBox.Checked; + } + + private void ErrorConsoleCheckBox_CheckedChanged(object sender, EventArgs e) + { + ConsolePanel.Visible = ErrorConsoleCheckBox.Checked; + } + + private void DynamicLODCheckBox_CheckedChanged(object sender, EventArgs e) + { + usedynamiclod = DynamicLODCheckBox.Checked; + ShowYmapChildrenCheckBox.Enabled = !usedynamiclod; + } + + private void DetailTrackBar_Scroll(object sender, EventArgs e) + { + lodthreshold = 50.0f / (0.1f + (float)DetailTrackBar.Value); + } + + private void WaitForChildrenCheckBox_CheckedChanged(object sender, EventArgs e) + { + waitforchildrentoload = WaitForChildrenCheckBox.Checked; + } + + private void ReloadShadersButton_Click(object sender, EventArgs e) + { + if (currentdevice == null) return; //can't do this with no device + + Cursor = Cursors.WaitCursor; + pauserendering = true; + + lock (rendersyncroot) + { + try + { + if (shaders != null) + { + shaders.Dispose(); + } + shaders = new ShaderManager(currentdevice, dxman); + } + catch (Exception ex) + { + MessageBox.Show("Error loading shaders!\n" + ex.ToString()); + return; + } + } + + pauserendering = false; + Cursor = Cursors.Default; + } + + private void MarkerStyleComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + MapIcon icon = MarkerStyleComboBox.SelectedItem as MapIcon; + if (icon != MarkerIcon) + { + MarkerIcon = icon; + foreach (MapMarker m in Markers) + { + m.Icon = icon; + } + } + } + + private void LocatorStyleComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + MapIcon icon = LocatorStyleComboBox.SelectedItem as MapIcon; + if (icon != LocatorIcon) + { + LocatorIcon = icon; + LocatorMarker.Icon = icon; + } + } + + private void ShowLocatorCheckBox_CheckedChanged(object sender, EventArgs e) + { + RenderLocator = ShowLocatorCheckBox.Checked; + } + + private void LocateTextBox_TextChanged(object sender, EventArgs e) + { + if (GrabbedMarker == LocatorMarker) return; //don't try to update the marker if it's being dragged + if (LocatorMarker == null) return; //this shouldn't happen, but anyway + + LocatorMarker.Parse(LocateTextBox.Text); + + //UpdateMarkerTexturePos(LocatorMarker); + } + + private void GoToButton_Click(object sender, EventArgs e) + { + GoToMarker(LocatorMarker); + } + + private void AddMarkersButton_Click(object sender, EventArgs e) + { + string[] lines = MultiFindTextBox.Text.Split('\n'); + foreach (string line in lines) + { + AddMarker(line); + } + } + + private void ClearMarkersButton_Click(object sender, EventArgs e) + { + MultiFindTextBox.Text = string.Empty; + Markers.Clear(); + } + + private void ResetMarkersButton_Click(object sender, EventArgs e) + { + Markers.Clear(); + AddDefaultMarkers(); + } + + private void AddCurrentPositonMarkerButton_Click(object sender, EventArgs e) + { + AddMarker(camera.Position, "Marker", true); + } + + private void AddSelectionMarkerButton_Click(object sender, EventArgs e) + { + if (SelectedItem.EntityDef == null) + { return; } + + Vector3 pos = SelectedItem.EntityDef.Position; + string name = SelectedItem.EntityDef.CEntityDef.archetypeName.ToString(); + var marker = AddMarker(pos, name, true); + SelectedMarker = marker; + ShowMarkerSelectionInfo(SelectedMarker); + } + + private void MarkerDepthClipCheckBox_CheckedChanged(object sender, EventArgs e) + { + markerdepthclip = MarkerDepthClipCheckBox.Checked; + } + + private void ShadowsCheckBox_CheckedChanged(object sender, EventArgs e) + { + lock (rendersyncroot) + { + shaders.shadows = ShadowsCheckBox.Checked; + } + } + + private void SkydomeCheckbox_CheckedChanged(object sender, EventArgs e) + { + renderskydome = SkydomeCheckBox.Checked; + } + + private void BoundsStyleComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + var val = BoundsStyleComboBox.SelectedItem; + var strval = val as string; + SetBoundsMode(strval); + } + + private void BoundsDepthClipCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderboundsclip = BoundsDepthClipCheckBox.Checked; + } + + private void BoundsRangeTrackBar_Scroll(object sender, EventArgs e) + { + float fv = BoundsRangeTrackBar.Value; + renderboundsmaxdist = fv * fv; + } + + private void MouseSelectCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetMouseSelect(MouseSelectCheckBox.Checked); + } + + private void SelectionBoundsCheckBox_CheckedChanged(object sender, EventArgs e) + { + ShowSelectionBounds = SelectionBoundsCheckBox.Checked; + } + + private void ToolsPanelExpandButton_Click(object sender, EventArgs e) + { + toolspanelexpanded = !toolspanelexpanded; + + int oldwidth = ToolsPanel.Width; + if (toolspanelexpanded) + { + ToolsPanelExpandButton.Text = ">>"; + } + else + { + ToolsPanelExpandButton.Text = "<<"; + } + ToolsPanel.Width = toolspanellastwidth; //or extended width + ToolsPanel.Left -= (toolspanellastwidth - oldwidth); + toolspanellastwidth = oldwidth; + } + + private void ToolsDragPanel_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + toolsPanelResizing = true; + toolsPanelResizeStartX = e.X + ToolsPanel.Left; + toolsPanelResizeStartLeft = ToolsPanel.Left; + toolsPanelResizeStartRight = ToolsPanel.Right; + } + } + + private void ToolsDragPanel_MouseUp(object sender, MouseEventArgs e) + { + toolsPanelResizing = false; + } + + private void ToolsDragPanel_MouseMove(object sender, MouseEventArgs e) + { + if (toolsPanelResizing) + { + int rx = e.X + ToolsPanel.Left; + int dx = rx - toolsPanelResizeStartX; + ToolsPanel.Left = toolsPanelResizeStartLeft + dx; + ToolsPanel.Width = toolsPanelResizeStartRight - toolsPanelResizeStartLeft - dx; + } + } + + private void FullScreenCheckBox_CheckedChanged(object sender, EventArgs e) + { + SetFullscreen(FullScreenCheckBox.Checked); + } + + private void ControlSettingsButton_Click(object sender, EventArgs e) + { + ShowSettingsForm("Controls"); + } + + private void AdvancedSettingsButton_Click(object sender, EventArgs e) + { + ShowSettingsForm("Advanced"); + } + + private void ReloadSettingsButton_Click(object sender, EventArgs e) + { + LoadSettings(); + } + + private void SaveSettingsButton_Click(object sender, EventArgs e) + { + SaveSettings(); + } + + private void QuitButton_Click(object sender, EventArgs e) + { + if (MessageBox.Show("Really quit?", "", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + Close(); + } + } + + private void AboutButton_Click(object sender, EventArgs e) + { + AboutForm f = new AboutForm(); + f.Show(this); + } + + private void ToolsButton_Click(object sender, EventArgs e) + { + ToolsMenu.Show(ToolsButton, 0, ToolsButton.Height); + } + + private void ToolsMenuRPFBrowser_Click(object sender, EventArgs e) + { + BrowseForm f = new BrowseForm(); + f.Show(this); + } + + private void ToolsMenuRPFExplorer_Click(object sender, EventArgs e) + { + ExploreForm f = new ExploreForm(); + f.Show(this); + } + + private void ToolsMenuSelectionInfo_Click(object sender, EventArgs e) + { + ShowInfoForm(); + } + + private void ToolsMenuProjectWindow_Click(object sender, EventArgs e) + { + ShowProjectForm(); + } + + private void ToolsMenuWorldSearch_Click(object sender, EventArgs e) + { + ShowSearchForm(); + } + + private void ToolsMenuBinarySearch_Click(object sender, EventArgs e) + { + BinarySearchForm f = new BinarySearchForm(); + f.Show(this); + } + + private void ToolsMenuJenkGen_Click(object sender, EventArgs e) + { + JenkGenForm f = new JenkGenForm(); + f.Show(this); + } + + private void ToolsMenuJenkInd_Click(object sender, EventArgs e) + { + JenkIndForm f = new JenkIndForm(gameFileCache); + f.Show(this); + } + + private void ToolsMenuExtractScripts_Click(object sender, EventArgs e) + { + ExtractScriptsForm f = new ExtractScriptsForm(); + f.Show(this); + } + + private void ToolsMenuExtractTextures_Click(object sender, EventArgs e) + { + ExtractTexForm f = new ExtractTexForm(); + f.Show(this); + } + + private void ToolsMenuExtractRawFiles_Click(object sender, EventArgs e) + { + ExtractRawForm f = new ExtractRawForm(); + f.Show(this); + } + + private void ToolsMenuExtractShaders_Click(object sender, EventArgs e) + { + ExtractShadersForm f = new ExtractShadersForm(); + f.Show(this); + } + + private void ToolsMenuOptions_Click(object sender, EventArgs e) + { + ShowSettingsForm(); + } + + private void StatusBarCheckBox_CheckedChanged(object sender, EventArgs e) + { + StatusStrip.Visible = StatusBarCheckBox.Checked; + } + + private void RenderModeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + TextureSamplerComboBox.Enabled = false; + TextureCoordsComboBox.Enabled = false; + switch (RenderModeComboBox.Text) + { + default: + case "Default": + shaders.RenderMode = WorldRenderMode.Default; + break; + case "Single texture": + shaders.RenderMode = WorldRenderMode.SingleTexture; + TextureSamplerComboBox.Enabled = true; + TextureCoordsComboBox.Enabled = true; + break; + case "Vertex normals": + shaders.RenderMode = WorldRenderMode.VertexNormals; + break; + case "Vertex tangents": + shaders.RenderMode = WorldRenderMode.VertexTangents; + break; + case "Vertex colour 1": + shaders.RenderMode = WorldRenderMode.VertexColour; + shaders.RenderVertexColourIndex = 1; + break; + case "Vertex colour 2": + shaders.RenderMode = WorldRenderMode.VertexColour; + shaders.RenderVertexColourIndex = 2; + break; + case "Vertex colour 3": + shaders.RenderMode = WorldRenderMode.VertexColour; + shaders.RenderVertexColourIndex = 3; + break; + case "Texture coord 1": + shaders.RenderMode = WorldRenderMode.TextureCoord; + shaders.RenderTextureCoordIndex = 1; + break; + case "Texture coord 2": + shaders.RenderMode = WorldRenderMode.TextureCoord; + shaders.RenderTextureCoordIndex = 2; + break; + case "Texture coord 3": + shaders.RenderMode = WorldRenderMode.TextureCoord; + shaders.RenderTextureCoordIndex = 3; + break; + } + } + + private void TextureSamplerComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (TextureSamplerComboBox.SelectedItem is MetaName) + { + shaders.RenderTextureSampler = (MetaName)TextureSamplerComboBox.SelectedItem; + } + } + + private void TextureCoordsComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + switch (TextureCoordsComboBox.Text) + { + default: + case "Texture coord 1": + shaders.RenderTextureSamplerCoord = 1; + break; + case "Texture coord 2": + shaders.RenderTextureSamplerCoord = 2; + break; + case "Texture coord 3": + shaders.RenderTextureSamplerCoord = 3; + break; + } + + } + + private void CollisionMeshesCheckBox_CheckedChanged(object sender, EventArgs e) + { + rendercollisionmeshes = CollisionMeshesCheckBox.Checked; + } + + private void CollisionMeshRangeTrackBar_Scroll(object sender, EventArgs e) + { + collisionmeshrange = CollisionMeshRangeTrackBar.Value; + } + + private void CollisionMeshLayer0CheckBox_CheckedChanged(object sender, EventArgs e) + { + collisionmeshlayers[0] = CollisionMeshLayer0CheckBox.Checked; + } + + private void CollisionMeshLayer1CheckBox_CheckedChanged(object sender, EventArgs e) + { + collisionmeshlayers[1] = CollisionMeshLayer1CheckBox.Checked; + } + + private void CollisionMeshLayer2CheckBox_CheckedChanged(object sender, EventArgs e) + { + collisionmeshlayers[2] = CollisionMeshLayer2CheckBox.Checked; + } + + private void CollisionMeshLayerDrawableCheckBox_CheckedChanged(object sender, EventArgs e) + { + collisionmeshlayerdrawable = CollisionMeshLayerDrawableCheckBox.Checked; + } + + private void ControlLightDirectionCheckBox_CheckedChanged(object sender, EventArgs e) + { + controllightdir = ControlLightDirectionCheckBox.Checked; + if (controllightdir) + { + ControlTimeOfDayCheckBox.Checked = false; + } + } + + private void ControlTimeOfDayCheckBox_CheckedChanged(object sender, EventArgs e) + { + controltimeofday = ControlTimeOfDayCheckBox.Checked; + if (controltimeofday) + { + ControlLightDirectionCheckBox.Checked = false; + } + } + + private void ShowYmapChildrenCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderchildents = ShowYmapChildrenCheckBox.Checked; + } + + private void HDRRenderingCheckBox_CheckedChanged(object sender, EventArgs e) + { + lock (rendersyncroot) + { + shaders.hdr = HDRRenderingCheckBox.Checked; + } + } + + private void AnisotropicFilteringCheckBox_CheckedChanged(object sender, EventArgs e) + { + shaders.AnisotropicFiltering = AnisotropicFilteringCheckBox.Checked; + } + + private void WorldMaxLodComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + switch (WorldMaxLodComboBox.Text) + { + default: + case "ORPHANHD": + renderworldMaxLOD = Unk_1264241711.LODTYPES_DEPTH_ORPHANHD; + break; + case "HD": + renderworldMaxLOD = Unk_1264241711.LODTYPES_DEPTH_HD; + break; + case "LOD": + renderworldMaxLOD = Unk_1264241711.LODTYPES_DEPTH_LOD; + break; + case "SLOD1": + renderworldMaxLOD = Unk_1264241711.LODTYPES_DEPTH_SLOD1; + break; + case "SLOD2": + renderworldMaxLOD = Unk_1264241711.LODTYPES_DEPTH_SLOD2; + break; + case "SLOD3": + renderworldMaxLOD = Unk_1264241711.LODTYPES_DEPTH_SLOD3; + break; + case "SLOD4": + renderworldMaxLOD = Unk_1264241711.LODTYPES_DEPTH_SLOD4; + break; + } + } + + private void WorldLodDistTrackBar_Scroll(object sender, EventArgs e) + { + float loddist = ((float)WorldLodDistTrackBar.Value) * 0.1f; + renderworldLodDistMult = loddist; + WorldLodDistLabel.Text = loddist.ToString("0.0"); + } + + private void WorldDetailDistTrackBar_Scroll(object sender, EventArgs e) + { + float detdist = ((float)WorldDetailDistTrackBar.Value) * 0.1f; + renderworldDetailDistMult = detdist; + WorldDetailDistLabel.Text = detdist.ToString("0.0"); + } + + private void WorldScriptedYmapsCheckBox_CheckedChanged(object sender, EventArgs e) + { + ShowScriptedYmaps = WorldScriptedYmapsCheckBox.Checked; + } + + private void WorldYmapTimeFilterCheckBox_CheckedChanged(object sender, EventArgs e) + { + worldymaptimefilter = WorldYmapTimeFilterCheckBox.Checked; + } + + private void WorldYmapWeatherFilterCheckBox_CheckedChanged(object sender, EventArgs e) + { + worldymapweatherfilter = WorldYmapWeatherFilterCheckBox.Checked; + } + + private void EnableModsCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (!initialised) return; + if (ProjectForm != null) + { + MessageBox.Show("Please close the Project Window before enabling or disabling mods."); + return; + } + + SetModsEnabled(EnableModsCheckBox.Checked); + } + + private void EnableDlcCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (!initialised) return; + if (ProjectForm != null) + { + MessageBox.Show("Please close the Project Window before enabling or disabling DLC."); + return; + } + + SetDlcLevel(DlcLevelComboBox.Text, EnableDlcCheckBox.Checked); + } + + private void DlcLevelComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (!initialised) return; + if (ProjectForm != null) + { + MessageBox.Show("Please close the Project Window before changing the DLC level."); + return; + } + + SetDlcLevel(DlcLevelComboBox.Text, EnableDlcCheckBox.Checked); + } + + private void TimeOfDayTrackBar_Scroll(object sender, EventArgs e) + { + int v = TimeOfDayTrackBar.Value; + float fh = v / 60.0f; + UpdateTimeOfDayLabel(); + lock (rendersyncroot) + { + timeofday = fh; + timecycle.SetTime(timeofday); + } + } + + private void WeatherComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (!Monitor.TryEnter(rendersyncroot, 50)) + { return; } //couldn't get a lock... + weathertype = WeatherComboBox.Text; + weather.SetNextWeather(weathertype); + Monitor.Exit(rendersyncroot); + } + + private void WeatherRegionComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + weather.Region = WeatherRegionComboBox.Text; + } + + private void CloudsComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + //if (!Monitor.TryEnter(rendersyncroot, 50)) + //{ return; } //couldn't get a lock... + individualcloudfrag = CloudsComboBox.Text; + //Monitor.Exit(rendersyncroot); + } + + private void DistantLODLightsCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderdistlodlights = DistantLODLightsCheckBox.Checked; + } + + private void NaturalAmbientLightCheckBox_CheckedChanged(object sender, EventArgs e) + { + rendernaturalambientlight = NaturalAmbientLightCheckBox.Checked; + } + + private void ArtificialAmbientLightCheckBox_CheckedChanged(object sender, EventArgs e) + { + renderartificialambientlight = ArtificialAmbientLightCheckBox.Checked; + } + + private void TimeStartStopButton_Click(object sender, EventArgs e) + { + timerunning = !timerunning; + TimeStartStopButton.Text = timerunning ? "Stop" : "Start"; + } + + private void TimeSpeedTrackBar_Scroll(object sender, EventArgs e) + { + float tv = TimeSpeedTrackBar.Value * 0.01f; + //when tv=0, speed=0 min/sec + //when tv=0.5, speed=0.5 min/sec + //when tv=1, speed=128 min/sec + + timespeed = 128.0f * tv * tv * tv * tv * tv * tv * tv * tv; + + TimeSpeedLabel.Text = timespeed.ToString("0.###") + " min/sec"; + } + + private void CameraModeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + SetCameraMode(CameraModeComboBox.Text); + } + + private void MapViewDetailTrackBar_Scroll(object sender, EventArgs e) + { + float det = ((float)MapViewDetailTrackBar.Value) * 0.1f; + MapViewDetailLabel.Text = det.ToString("0.0#"); + lock (rendersyncroot) + { + MapViewDetail = det; + } + } + + private void FieldOfViewTrackBar_Scroll(object sender, EventArgs e) + { + float fov = FieldOfViewTrackBar.Value * 0.01f; + FieldOfViewLabel.Text = fov.ToString("0.0#"); + lock (rendersyncroot) + { + camera.FieldOfView = fov; + camera.UpdateProj = true; + } + } + + private void CloudParamComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + CloudAnimSetting setting = CloudParamComboBox.SelectedItem as CloudAnimSetting; + if (setting != null) + { + float rng = setting.MaxValue - setting.MinValue; + float cval = (setting.CurrentValue - setting.MinValue) / rng; + int ival = (int)(cval * 200.0f); + ival = Math.Min(Math.Max(ival, 0), 200); + CloudParamTrackBar.Value = ival; + } + } + + private void CloudParamTrackBar_Scroll(object sender, EventArgs e) + { + CloudAnimSetting setting = CloudParamComboBox.SelectedItem as CloudAnimSetting; + if (setting != null) + { + float rng = setting.MaxValue - setting.MinValue; + float fval = CloudParamTrackBar.Value / 200.0f; + float cval = (fval * rng) + setting.MinValue; + setting.CurrentValue = cval; + } + } + + private void SelDrawableModelsTreeView_AfterCheck(object sender, TreeViewEventArgs e) + { + if (e.Node != null) + { + UpdateSelectionDrawFlags(e.Node); + + if (InfoForm != null) + { + InfoForm.SyncSelDrawableModelsTreeNode(e.Node); + } + } + } + + private void SelDrawableModelsTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) + { + if (e.Node != null) + { + e.Node.Checked = !e.Node.Checked; + //UpdateSelectionDrawFlags(e.Node); + } + } + + private void SelDrawableModelsTreeView_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; //stops annoying ding sound... + } + + private void SelectionWidgetCheckBox_CheckedChanged(object sender, EventArgs e) + { + ShowWidget = SelectionWidgetCheckBox.Checked; + } + + private void ShowToolbarCheckBox_CheckedChanged(object sender, EventArgs e) + { + ToolbarPanel.Visible = ShowToolbarCheckBox.Checked; + } + + private void ToolbarNewButton_ButtonClick(object sender, EventArgs e) + { + New(); + } + + private void ToolbarNewProjectButton_Click(object sender, EventArgs e) + { + NewProject(); + } + + private void ToolbarNewYmapButton_Click(object sender, EventArgs e) + { + NewYmap(); + } + + private void ToolbarNewYndButton_Click(object sender, EventArgs e) + { + NewYnd(); + } + + private void ToolbarNewTrainsButton_Click(object sender, EventArgs e) + { + NewTrainTrack(); + } + + private void ToolbarNewScenarioButton_Click(object sender, EventArgs e) + { + NewScenario(); + } + + private void ToolbarOpenButton_ButtonClick(object sender, EventArgs e) + { + Open(); + } + + private void ToolbarOpenProjectButton_Click(object sender, EventArgs e) + { + OpenProject(); + } + + private void ToolbarOpenYmapButton_Click(object sender, EventArgs e) + { + OpenYmap(); + } + + private void ToolbarOpenYndButton_Click(object sender, EventArgs e) + { + OpenYnd(); + } + + private void ToolbarOpenTrainsButton_Click(object sender, EventArgs e) + { + OpenTrainTrack(); + } + + private void ToolbarOpenScenarioButton_Click(object sender, EventArgs e) + { + OpenScenario(); + } + + private void ToolbarSaveButton_Click(object sender, EventArgs e) + { + Save(); + } + + private void ToolbarSaveAllButton_Click(object sender, EventArgs e) + { + SaveAll(); + } + + private void ToolbarSelectButton_ButtonClick(object sender, EventArgs e) + { + SetMouseSelect(!ToolbarSelectButton.Checked); + SetWidgetMode("Default"); + } + + private void ToolbarSelectEntityButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Entity"); + SetMouseSelect(true); + } + + private void ToolbarSelectEntityExtensionButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Entity Extension"); + SetMouseSelect(true); + } + + private void ToolbarSelectArchetypeExtensionButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Archetype Extension"); + SetMouseSelect(true); + } + + private void ToolbarSelectTimeCycleModifierButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Time Cycle Modifier"); + SetMouseSelect(true); + } + + private void ToolbarSelectCarGeneratorButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Car Generator"); + SetMouseSelect(true); + } + + private void ToolbarSelectGrassButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Grass"); + SetMouseSelect(true); + } + + private void ToolbarSelectWaterQuadButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Water Quad"); + SetMouseSelect(true); + } + + private void ToolbarSelectCollisionButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Collision"); + SetMouseSelect(true); + } + + private void ToolbarSelectNavMeshButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Nav Mesh"); + SetMouseSelect(true); + } + + private void ToolbarSelectPathButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Path"); + SetMouseSelect(true); + } + + private void ToolbarSelectTrainTrackButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Train Track"); + SetMouseSelect(true); + } + + private void ToolbarSelectDistantLodLightsButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Distant Lod Lights"); + SetMouseSelect(true); + } + + private void ToolbarSelectMloInstanceButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Mlo Instance"); + SetMouseSelect(true); + } + + private void ToolbarSelectScenarioButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Scenario"); + SetMouseSelect(true); + } + + private void ToolbarMoveButton_Click(object sender, EventArgs e) + { + SetWidgetMode(ToolbarMoveButton.Checked ? "Default" : "Position"); + } + + private void ToolbarRotateButton_Click(object sender, EventArgs e) + { + SetWidgetMode(ToolbarRotateButton.Checked ? "Default" : "Rotation"); + } + + private void ToolbarScaleButton_Click(object sender, EventArgs e) + { + SetWidgetMode(ToolbarScaleButton.Checked ? "Default" : "Scale"); + } + + private void ToolbarTransformSpaceButton_ButtonClick(object sender, EventArgs e) + { + SetWidgetSpace(Widget.ObjectSpace ? "World space" : "Object space"); + } + + private void ToolbarObjectSpaceButton_Click(object sender, EventArgs e) + { + SetWidgetSpace("Object space"); + } + + private void ToolbarWorldSpaceButton_Click(object sender, EventArgs e) + { + SetWidgetSpace("World space"); + } + + private void ToolbarUndoButton_ButtonClick(object sender, EventArgs e) + { + Undo(); + } + + private void ToolbarUndoListButton_Click(object sender, EventArgs e) + { + var tsi = sender as ToolStripItem; + if (tsi == null) return; + var step = tsi.Tag as UndoStep; + if (step == null) return; + if (UndoSteps.Count == 0) return; + var cstep = UndoSteps.Peek(); + while (cstep != null) + { + Undo(); + if (cstep == step) break; + if (UndoSteps.Count == 0) break; + cstep = UndoSteps.Peek(); + } + } + + private void ToolbarRedoButton_ButtonClick(object sender, EventArgs e) + { + Redo(); + } + + private void ToolbarRedoListButton_Click(object sender, EventArgs e) + { + var tsi = sender as ToolStripItem; + if (tsi == null) return; + var step = tsi.Tag as UndoStep; + if (step == null) return; + if (RedoSteps.Count == 0) return; + var cstep = RedoSteps.Peek(); + while (cstep != null) + { + Redo(); + if (cstep == step) break; + if (RedoSteps.Count == 0) break; + cstep = RedoSteps.Peek(); + } + } + + private void ToolbarInfoWindowButton_Click(object sender, EventArgs e) + { + ShowInfoForm(); + } + + private void ToolbarProjectWindowButton_Click(object sender, EventArgs e) + { + ShowProjectForm(); + } + + private void ToolbarAddItemButton_Click(object sender, EventArgs e) + { + AddItem(); + } + + private void ToolbarDeleteItemButton_Click(object sender, EventArgs e) + { + DeleteItem(); + } + + private void ToolbarCopyButton_Click(object sender, EventArgs e) + { + CopyItem(); + } + + private void ToolbarPasteButton_Click(object sender, EventArgs e) + { + PasteItem(); + } + + private void ToolbarCameraModeButton_ButtonClick(object sender, EventArgs e) + { + ToggleCameraMode(); + } + + private void ToolbarCameraPerspectiveButton_Click(object sender, EventArgs e) + { + SetCameraMode("Perspective"); + } + + private void ToolbarCameraMapViewButton_Click(object sender, EventArgs e) + { + SetCameraMode("2D Map"); + } + + private void ToolbarCameraOrthographicButton_Click(object sender, EventArgs e) + { + SetCameraMode("Orthographic"); + } + + private void SelectionModeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + SetSelectionMode(SelectionModeComboBox.Text); + } + + private void SelectionModeComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void ViewModeComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void WorldMaxLodComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void DlcLevelComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void CameraModeComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void RenderModeComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void TextureSamplerComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void TextureCoordsComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void MarkerStyleComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void LocatorStyleComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void BoundsStyleComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void WeatherComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void WeatherRegionComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void CloudsComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + private void CloudParamComboBox_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + } + + + public enum WorldRenderMode + { + Default = 0, + SingleTexture = 1, + VertexNormals = 2, + VertexTangents = 3, + VertexColour = 4, + TextureCoord = 5, + } + + public enum WorldControlMode + { + Free = 0, + Ped = 1, + Car = 2, + Heli = 3, + Plane = 4, + Jetpack = 10, + } + + + public class MapIcon + { + public string Name { get; set; } + public string Filepath { get; set; } + public Texture2D Tex { get; set; } + public ShaderResourceView TexView { get; set; } + public Vector3 Center { get; set; } //in image pixels + public float Scale { get; set; } //screen pixels per icon pixel + public int TexWidth { get; set; } + public int TexHeight { get; set; } + + public MapIcon(string name, string filepath, int texw, int texh, float centerx, float centery, float scale) + { + Name = name; + Filepath = filepath; + TexWidth = texw; + TexHeight = texh; + Center = new Vector3(centerx, centery, 0.0f); + Scale = scale; + + if (!File.Exists(filepath)) + { + throw new Exception("File not found."); + } + } + + public void LoadTexture(Device device, Action errorAction) + { + try + { + if (device != null) + { + Tex = TextureLoader.CreateTexture2DFromBitmap(device, TextureLoader.LoadBitmap(new SharpDX.WIC.ImagingFactory2(), Filepath)); + TexView = new ShaderResourceView(device, Tex); + } + } + catch (Exception ex) + { + errorAction("Could not load map icon " + Filepath + " for " + Name + "!\n\n" + ex.ToString()); + } + } + + public void UnloadTexture() + { + if (TexView != null) + { + TexView.Dispose(); + TexView = null; + } + if (Tex != null) + { + Tex.Dispose(); + Tex = null; + } + } + + public override string ToString() + { + return Name; + } + } + + public class MapMarker + { + public MapIcon Icon { get; set; } + public Vector3 WorldPos { get; set; } //actual world pos + public Vector3 CamRelPos { get; set; } //updated per frame + public Vector3 ScreenPos { get; set; } //position on screen (updated per frame) + public string Name { get; set; } + public List Properties { get; set; } //additional data + public bool IsMovable { get; set; } + public float Distance { get; set; } //length of CamRelPos, updated per frame + + public void Parse(string s) + { + Vector3 p = new Vector3(0.0f); + string[] ss = s.Split(','); + if (ss.Length > 1) + { + FloatUtil.TryParse(ss[0].Trim(), out p.X); + FloatUtil.TryParse(ss[1].Trim(), out p.Y); + } + if (ss.Length > 2) + { + FloatUtil.TryParse(ss[2].Trim(), out p.Z); + } + if (ss.Length > 3) + { + Name = ss[3].Trim(); + } + else + { + Name = string.Empty; + } + for (int i = 4; i < ss.Length; i++) + { + if (Properties == null) Properties = new List(); + Properties.Add(ss[i].Trim()); + } + WorldPos = p; + } + + public override string ToString() + { + string cstr = Get3DWorldPosString(); + if (!string.IsNullOrEmpty(Name)) + { + cstr += ", " + Name; + if (Properties != null) + { + foreach (string prop in Properties) + { + cstr += ", " + prop; + } + } + } + return cstr; + } + + public string Get2DWorldPosString() + { + return string.Format(CultureInfo.InvariantCulture, "{0}, {1}", WorldPos.X, WorldPos.Y); + } + public string Get3DWorldPosString() + { + return string.Format(CultureInfo.InvariantCulture, "{0}, {1}, {2}", WorldPos.X, WorldPos.Y, WorldPos.Z); + } + + + } + + public struct MapSphere + { + public Vector3 CamRelPos { get; set; } + public float Radius { get; set; } + } + public struct MapBox + { + public Vector3 CamRelPos { get; set; } + public Vector3 BBMin { get; set; } + public Vector3 BBMax { get; set; } + public Quaternion Orientation { get; set; } + public Vector3 Scale { get; set; } + } + + public struct MapSelection + { + public YmapEntityDef EntityDef { get; set; } + public Archetype Archetype { get; set; } + public DrawableBase Drawable { get; set; } + public DrawableGeometry Geometry { get; set; } + public MetaWrapper EntityExtension { get; set; } + public MetaWrapper ArchetypeExtension { get; set; } + public YmapTimeCycleModifier TimeCycleModifier { get; set; } + public YmapCarGen CarGenerator { get; set; } + public YmapGrassInstanceBatch GrassBatch { get; set; } + public YmapDistantLODLights DistantLodLights { get; set; } + public YmapEntityDef MloEntityDef { get; set; } + public WaterQuad WaterQuad { get; set; } + public Bounds CollisionBounds { get; set; } + public YnvPoly NavPoly { get; set; } + public YndNode PathNode { get; set; } + public YndLink PathLink { get; set; } + public TrainTrackNode TrainTrackNode { get; set; } + public ScenarioNode ScenarioNode { get; set; } + public MCScenarioChainingEdge ScenarioEdge { get; set; } + + + public BoundingBox AABB { get; set; } + public int GeometryIndex { get; set; } + public Vector3 CamRel { get; set; } + public float HitDist { get; set; } + + + public bool HasValue + { + get + { + return (EntityDef != null) || + (Archetype != null) || + (Drawable != null) || + (Geometry != null) || + (EntityExtension != null) || + (ArchetypeExtension != null) || + (TimeCycleModifier != null) || + (CarGenerator != null) || + (GrassBatch != null) || + (WaterQuad != null) || + (CollisionBounds != null) || + (NavPoly != null) || + (PathNode != null) || + (TrainTrackNode != null) || + (DistantLodLights != null) || + (MloEntityDef != null) || + (ScenarioNode != null); + } + } + + public bool HasHit + { + get { return (HitDist != float.MaxValue); } + } + + + public void Clear() + { + EntityDef = null; + Archetype = null; + Drawable = null; + Geometry = null; + EntityExtension = null; + ArchetypeExtension = null; + TimeCycleModifier = null; + CarGenerator = null; + GrassBatch = null; + WaterQuad = null; + CollisionBounds = null; + NavPoly = null; + PathNode = null; + PathLink = null; + TrainTrackNode = null; + DistantLodLights = null; + MloEntityDef = null; + ScenarioNode = null; + ScenarioEdge = null; + AABB = new BoundingBox(); + GeometryIndex = 0; + CamRel = new Vector3(); + HitDist = float.MaxValue; + } + + public string GetNameString(string defval) + { + string name = defval; + if (EntityDef != null) + { + name = EntityDef.CEntityDef.archetypeName.ToString(); + } + else if (Archetype != null) + { + name = Archetype.Hash.ToString(); + } + else if (TimeCycleModifier != null) + { + name = TimeCycleModifier.CTimeCycleModifier.name.ToString(); + } + else if (CarGenerator != null) + { + name = CarGenerator.CCarGen.carModel.ToString(); + } + else if (DistantLodLights != null) + { + name = DistantLodLights.Ymap?.Name ?? ""; + } + else if (CollisionBounds != null) + { + name = CollisionBounds.GetName(); + } + if (EntityExtension != null) + { + name = EntityExtension.Name; + } + if (ArchetypeExtension != null) + { + name = ArchetypeExtension.Name; + } + if (WaterQuad != null) + { + name = "WaterQuad " + WaterQuad.ToString(); + } + if (NavPoly != null) + { + name = "NavPoly " + NavPoly.ToString(); + } + if (PathNode != null) + { + name = "PathNode " + PathNode.AreaID.ToString() + "." + PathNode.NodeID.ToString(); //+ FloatUtil.GetVector3String(PathNode.Position); + } + if (TrainTrackNode != null) + { + name = "TrainTrackNode " + FloatUtil.GetVector3String(TrainTrackNode.Position); + } + if (ScenarioNode != null) + { + name = ScenarioNode.ToString(); + } + return name; + } + + public string GetFullNameString(string defval) + { + string name = defval; + if (EntityDef != null) + { + name = EntityDef.CEntityDef.archetypeName.ToString(); + } + else if (Archetype != null) + { + name = Archetype.Hash.ToString(); + } + else if (CollisionBounds != null) + { + name = CollisionBounds.GetName(); + } + if (Geometry != null) + { + name += " (" + GeometryIndex.ToString() + ")"; + } + if (TimeCycleModifier != null) + { + name = TimeCycleModifier.CTimeCycleModifier.name.ToString(); + } + if (CarGenerator != null) + { + name = CarGenerator.CCarGen.carModel.ToString(); + } + if (EntityExtension != null) + { + name += ": " + EntityExtension.Name; + } + if (ArchetypeExtension != null) + { + name += ": " + ArchetypeExtension.Name; + } + if (WaterQuad != null) + { + name = "WaterQuad " + WaterQuad.ToString(); + } + if (NavPoly != null) + { + name = "NavPoly " + NavPoly.ToString(); + } + if (PathNode != null) + { + name = "PathNode " + PathNode.AreaID.ToString() + "." + PathNode.NodeID.ToString();// + FloatUtil.GetVector3String(PathNode.Position); + } + if (TrainTrackNode != null) + { + name = "TrainTrackNode " + FloatUtil.GetVector3String(TrainTrackNode.Position); + } + if (ScenarioNode != null) + { + name = ScenarioNode.ToString(); + } + return name; + } + + } + + public enum MapSelectionMode + { + None = 0, + Entity = 1, + EntityExtension = 2, + ArchetypeExtension = 3, + TimeCycleModifier = 4, + CarGenerator = 5, + Grass = 6, + WaterQuad = 7, + Collision = 8, + NavMesh = 9, + Path = 10, + TrainTrack = 11, + DistantLodLights = 12, + MloInstance = 13, + Scenario = 14, + PopZone = 15, + } + + + + public class KeyBindings + { + public Keys MoveForward = Keys.W; + public Keys MoveBackward = Keys.S; + public Keys MoveLeft = Keys.A; + public Keys MoveRight = Keys.D; + public Keys MoveUp = Keys.R; + public Keys MoveDown = Keys.F; + public Keys MoveSlowerZoomIn = Keys.Z; + public Keys MoveFasterZoomOut = Keys.X; + public Keys ToggleMouseSelect = Keys.C; + public Keys ToggleToolbar = Keys.T; + public Keys ExitEditMode = Keys.Q; + public Keys EditPosition = Keys.W; + public Keys EditRotation = Keys.E; + public Keys EditScale = Keys.R; + public Keys Jump = Keys.Space; //for control mode + + public KeyBindings(StringCollection sc) + { + foreach (string s in sc) + { + string[] parts = s.Split(':'); + if (parts.Length == 2) + { + string sval = parts[1].Trim(); + Keys k = (Keys)Enum.Parse(typeof(Keys), sval); + SetBinding(parts[0], k); + } + } + } + + public void SetBinding(string name, Keys k) + { + switch (name) + { + case "Move Forwards": MoveForward = k; break; + case "Move Backwards": MoveBackward = k; break; + case "Move Left": MoveLeft = k; break; + case "Move Right": MoveRight = k; break; + case "Move Up": MoveUp = k; break; + case "Move Down": MoveDown = k; break; + case "Move Slower / Zoom In": MoveSlowerZoomIn = k; break; + case "Move Faster / Zoom Out": MoveFasterZoomOut = k; break; + case "Toggle Mouse Select": ToggleMouseSelect = k; break; + case "Toggle Toolbar": ToggleToolbar = k; break; + case "Exit Edit Mode": ExitEditMode = k; break; + case "Edit Position": EditPosition = k; break; + case "Edit Rotation": EditRotation = k; break; + case "Edit Scale": EditScale = k; break; + } + } + + public StringCollection GetSetting() + { + StringCollection sc = new StringCollection(); + sc.Add(GetSettingItem("Move Forwards", MoveForward)); + sc.Add(GetSettingItem("Move Backwards", MoveBackward)); + sc.Add(GetSettingItem("Move Left", MoveLeft)); + sc.Add(GetSettingItem("Move Right", MoveRight)); + sc.Add(GetSettingItem("Move Up", MoveUp)); + sc.Add(GetSettingItem("Move Down", MoveDown)); + sc.Add(GetSettingItem("Move Slower / Zoom In", MoveSlowerZoomIn)); + sc.Add(GetSettingItem("Move Faster / Zoom Out", MoveFasterZoomOut)); + sc.Add(GetSettingItem("Toggle Mouse Select", ToggleMouseSelect)); + sc.Add(GetSettingItem("Toggle Toolbar", ToggleToolbar)); + sc.Add(GetSettingItem("Exit Edit Mode", ExitEditMode)); + sc.Add(GetSettingItem("Edit Position", EditPosition)); + sc.Add(GetSettingItem("Edit Rotation", EditRotation)); + sc.Add(GetSettingItem("Edit Scale", EditScale)); + return sc; + } + + private string GetSettingItem(string name, Keys val) + { + return name + ": " + val.ToString(); + } + + public KeyBindings Copy() + { + return (KeyBindings)MemberwiseClone(); + } + + } + + + +} diff --git a/WorldForm.resx b/WorldForm.resx new file mode 100644 index 0000000..aed5002 --- /dev/null +++ b/WorldForm.resx @@ -0,0 +1,691 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 182, 17 + + + dt1_lod +hw1_lod +cs1_lod +cs1_lod2 +cs1_lod3 +cs2_lod +cs2_lod2 +cs3_lod +cs4_lod +cs5_lod +cs6_lod +ch1_lod +ch2_lod +ch2_lod2 +ch2_lod3 +ch2_lod4 +ch3_lod +ss1_lod +sc1_lod +sp1_lod +sm_lod +id1_lod +id2_lod +bh1_lod +vb_lod +po1_lod +ap1_lod +kt1_lod +ufo_lod +ufo_eye +ufo + + + + 298, 17 + + + 447, 17 + + + 559, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADESURBVDhPzZI7DgIhGIQ5grUnsPQMnMgLWMo1bDyJiYUV + h7CxEo1Aiw7+E9ldWF+Nk0w2wMy3/z5UqRDCwjk3iTEmGmvsS6Ste2gtJYvrdjklJK9xLtGhcAeEdqtZ + Ouw3uUgA1tgXSH0SGdsyfD0dcwHXAmqRk0pXCNMsN+y893OpPYVDjFw8d9JaD2yMqUNYgjkBCmd36bgJ + 6b+DMUAJkXr9K9QANM6QkfpD/f/gYwCESfgnfgWg/gcw5peAdyzxX6TUDfMCML1omZa9AAAAAElFTkSu + QmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEcSURBVDhPlZKxqsIwFIb7Bvc+idxHuPQVXFpQcOhe8Amc + OqqzCBdU6HQfQIfunVwKoi7FQQeF9GrajufmhDYkTaMY+EjPyf//TZtY9aCUfhVFQRggQbBfSV4PFJ8v + GekMf8HqzqE3jXhIhRwsqKyWxYpJ3bzcMpBD4jgG27Y1RACaZ+sEPvoLbmqCa/f7AzLyJ2gGcDO+bXe6 + ajugDypMiBJQluU3f2DiZ+YmT3eANWIyIyKgFsv/AOs2k4wSgIXneRBFEaRpyhew10ZbwNb3fU1oYrPe + qAF5no/CMNSEJsbjiRqAty9JEk1ownEcNaA6BeK6riY2cdgf+SwC2Gf8BEGgCU2slis+iwB2mQZ4Ak3h + K0QAIeQTi/cp4B9tCZE2c6oRhQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABRSURBVDhPY6AK+Pbt239S8NevX+dDtUIASNDJyQmOP7z/ + CMfIYiC6ra0N0xBSDABhmCFQ7aQbAMJEG4CMkdXQ1gBi8KgBg9IAcjBUOyWAgQEAoTb4kYkPBE8AAAAA + SUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB2SURBVDhP7ZCxDcAgDAQZKTMwnBdiMIJk0SZ6YksoYEOR + Mi8ddvFc4WCl1no5ZGY+pDoPijHGxplLQ3ciWks8AaZKpD5mJuhFAB2pj+kFFt8I8FiklKYfFXTcY+FQ + nmQpwPQkpqAXadFi/1hWfsEj2EHqr4RwAzbn8IoLYvtxAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPtY7bCcAgDEUdoaN0hOIWbtMvF/Lflfzx8dl6 + JSmlKNTQHgg+uDmJ+pyc81ErxBhX+poDAmutXAKB1louYYFYcheIJE/BtKQnmJKMBCiWULQPCxA2xrS7 + 9x6NV1G0DwI06XDONQFE9R0qC8XG0JRQStlw8haQpZR2ir0DDaItGITRRFu1mt7iZ5Q6AVRB/GG9LRsl + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACrSURBVDhPpVJbDoAgDONInoHD8c9J/SH8Kl02rZORGJs0 + DNaWh6YZWmtb730vpRwgaqxpew0255yFn0K82YeoLMYQXQY2Y0RPZU/YsSEAdbcrgNeU93X8nVUoYRww + 00jIpLGkD0m24AnxrGbC+z8Ax7CQWquIVzQtxjHfo0cU2k429+bXl2AhRg7g4MH4rzSj7cY1eiqLgXQ2 + cwh6Kovh34TN4bE9OGRtTukExpYH+BWfUFQAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFRSURBVDhPfZMxboNAEEU5Qo6QI+QIET1SWncp6OmpUrm1 + 6JFSuuQGuKaioQ89xRYYKDfz1jt4TYhX+trRnz9/2Z0h+m9N0/Q1z7MFxJ5+vpZleRfx9ziOP03T2MPh + 4EAMRw6Nl9+XkK+SvHDaMAy2KAobx/ED4Mj5L7oYY17WYiENApJd19k0Tf8YwJFDU5Ylu3iIiQQVBCKS + SZLYuq6dSIuJ4cihUY4rYbAKwzjPc3d3QLynIV4NjsfjQxJwIgg5NGg1dgacIHu7NdgDGoHxNTcDf7oz + oG17hUC/Mqi5X+F8Pjti20Z9VKCdQkvuwQBkWeaEcDwerdOdPAZoVO8MGIrwRE0I2r7vd2cCUENtdL1e + 30Rs9GUBBhRvO6Dw9zfUumn0Jq32HIOtKdDZ4L9Yi8MlY/0phRUGahpOZGB+8iXPF7OOiXbB/0yV3P3j + poiiXxmvX1sw0rqWAAAAAElFTkSuQmCC + + + + + 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 + AElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPlVM9ixpRFJ2fkJ+wPyE/ISgqCEoQBBtBMjYi + jmunhSCMWO4iiLhBWCwEq1goSLYwItlCBG20MBZRSGLn7OJXefLOZWaza7JFLrx5M/fcc+59797Rntvp + dHp3OBxu7c//N0X+cjweQSHbRdGY8rVtjPulZVlvbPiPMXA8HqNUKoHBDFKEqTLUajUUi0XBut0ulN/a + 7/dvbaqm2cFWKpWCy+XCaDSSoEqlgmQyiVwuh2w2i0QigVAohHQ6LbhKeiECKmOh3+/D7/eLQDwex3A4 + hK7rKBQKqFaroFg+n0csFoPX60W9Xmeltyz9YrvdgtkJUICr1WphsVhgvV5jPp+j0WjANE0R9/l8CAQC + rAKaerR7vR6i0SjcbjeazSZms5lkYAWRSATlchmr1QqsknEej0eSOAJyxnA4jMlkgsFgIMT2pzYerEdZ + fKePGC/VqfJJIJPJIBgMioOA/kHH/df7J4FviyWMlCHYcrmUnRe52+2+a3yQ6CyCP3/8ws3NR3XzOdlJ + pqCTlTuPydZLF9hTe2AEdDLffb6TO3C+HQGSpQPn9rwCEpiV2c8F2Hab8tIIctpI4rkdAQpeXV0LpmIs + O/xv41FUwJSTyFs3zaIcwTAMdDodkqcvRvg1UyVebjYbi7PAweEMKPL1P3+i14wTqoT4B1pqf2+7z0zT + fgPQbDDZyZreTQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADpSURBVDhPjVIxEoJADOQpPsLCmp5f8ABL/II/wKGTT0jj + J2jUVm3RAihP9mRnYu4ymJmdySzZvYQkYQzD4CTA9X2/nfIOQO4LrYBos197IJ8E57ZtXZ7nHsjBjeO4 + miXfQDEhDYjm1HhkWeaqqgL3240UauDbq3t7PO5PVxS7sJt/DQjdzeII2gAoy4NL09R/nwcJf+L1cguE + 4DBGfazjBhIspBg5OBpHDUBSIEXaDPjLgIUWHzXAunShNkBNzKDDarAirMoyCNbIwFHI88XcfAkwD0kH + zlR2QwPzlGOhu1l81Qp2Y7+aJB877HaG+O29gAAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFySURBVDhPhVI9S8RAEN0/4D+wsLKwtbKTg2CV1sI6YGth + cbb+ALE9DYgYg4XNWSh3CGIrggjh8NRSTyVFTMR8QMKYN7prTLL4YLLJZN6bmZ0RWZbR5OaK/Mcx5XlO + AM7w7ZV9cRxTFEWfJdZEGxCwPztFx4tzJemFpGDfXODTcRyyLIs8z6NS5CJJkpkf6jdKB12uWyxyvrpM + o6M9cuen+YTYcDBkM02TbNtGRcGfaoqioKoI7HZ3m9I05Xbeg5Dt+WlC3e5GsxqdAFrj/sNIicDq1Qhc + FkoHESLXW5v8Pjrrk+/7DQFYr7dDnU6HEwhcFggQQSVwynvApUbhhyLejx+4DefA+RUAGSKopIq7wQmd + riwpMkggQwTfSgCP0gKchmEoAsw9dJkks1b/KQEJfMBZDZKBOn+rAMZVD6wLIKZNIMBoMCKMSifQGKME + lgLLgSXBsqBvmQmmXaQ6sKbVaqSAdpXbUK/m36w6yGr0WYX4AtJHmpxbRwouAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACZSURBVDhPzZLLDYYgEIQpwZq4UwCtcLIDS7MQDj744YqM + WR8hu/mN0cRJJgac/WCi6jWllLrizHgoaigmC2FjTNZa77bWZu89ID3FZAGAoXGYdmPtnFtvQjFZHGCD + sICyyXYO4XcZIHae53ANgJf1aVvnW4DzAJ4wbnkLcHaMsaWxQ/8AFJP1CKD+CrDYuVYJSf8+3/kjUmoB + 0WKNJAuziQ0AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACKSURBVDhP7Y3LDYAgEEQpwVKsgSoojl4swSbUCwc0Aa7q + 4BJN+IjGo5O8ZJndGVhKxpjWWts551aih0fre+0BLaVchRAezPB2NXSSV/gVwXGYPJiVUt6ns1ghCDjn + UQG86w3FToVgDcWCWS9Fvi/Ao0RVAcwUjwpyhzmf4n8BFApS5HZRwRuONGMbrIJ1JIN8O2QAAAAASUVO + RK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAE/SURBVDhPpdO/K0VhHMfxKxRJopCSEkLya7BIUURk + Mhhk8SNEMkoGlqtEilAipfgvjAYDhfIHWC1CrMf7fXNOF3dw+dZr+Z7v+dznPM9zY0EQ/EvKZjpSNtMR + Vi+eYOcencjH8mcv9IxNlCAbUfnyAcZwhUu0Yg3XmMUMNvCIY1QiCilDP4awC4eGsYNbLGAAbdjDGwbh + ShKVh3LYuMA5xrGPG4yiCploh58TRyOiciD8VlcxAleQHGDlwBlX4l5FZXoFDvGOCWzje0ANDFhFj42w + MlCAZjiwhSPcITlgDi+YR4eNIvjCItyDFTiwhFMkB3jcDzjDNBqQ+GWHX2GQL69jCq7AXshnJ/BZdAoG + lKIPkzDZ+9CFanQjvAf25ZF+uQdZKEYtmuBGFSIXhtejBe5PHX7cxL9Xqj/I7wWxD01NBsCnq3n2AAAA + AElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAE/SURBVDhPpdPLK0RhGMfxcYuNQlHKRu5JbGyklLBw + 2SjZKJeESJZSFkrUxMLGQkooW7H3L8jlH8DWRm7r4/s9zZnOTLMwzVOfpp5zzu993/OcSQRBUJCczXzk + bOYjqhF8wM4nZlGN7VQv4rVD1KEMYdXAh08wj2v8YABJ3GMVKzjAO87QiDCkCA0YwyRc3dW2YOgzNjCK + XhzjF+NwJ2FAJQyx4S6+sYlzPGEGTShBH1xgD13IKG96xSWWcYp4gFUBA9yJx0yXN7zgFouYwBEeEQ9o + gQE7GLJhRQ/fwCNMoRn7yA5YwxfW0W/DesAdFjCNNpRjF/EAx/2GK3jEToRv1i1lG4Rji/dc+QJLSE+h + FCaZ6Oj8nYNj7cYwou/A48mRpr+DYlShFT0xvqxa1KMj1TOwHRlfYmGV6w/yf0HiD5hgB8y7ZINJAAAA + AElFTkSuQmCC + + + + + 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 + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//r7//v8//7+/wAAAAAAAAAA + APb4/7/F84eP0e/0//7+/wAAAAAAAP7+//z9//v8//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz9//b5//X4//v8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////w////4 + P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA + AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA + AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v// + /////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/WorldInfoForm.Designer.cs b/WorldInfoForm.Designer.cs new file mode 100644 index 0000000..265ddf3 --- /dev/null +++ b/WorldInfoForm.Designer.cs @@ -0,0 +1,641 @@ +using CodeWalker.WinForms; + +namespace CodeWalker +{ + partial class WorldInfoForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WorldInfoForm)); + this.SelectionTabControl = new System.Windows.Forms.TabControl(); + this.SelectionEntityTabPage = new System.Windows.Forms.TabPage(); + this.SelEntityPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.SelectionArchetypeTabPage = new System.Windows.Forms.TabPage(); + this.SelArchetypePropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.SelectionDrawableTabPage = new System.Windows.Forms.TabPage(); + this.SelDrawablePropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.SelectionExtensionTabPage = new System.Windows.Forms.TabPage(); + this.SelExtensionPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.SelectionModelsTabPage = new System.Windows.Forms.TabPage(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.SelDrawableModelsTreeView = new CodeWalker.WinForms.TreeViewFix(); + this.SelDrawableModelPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.SelectionTexturesTabPage = new System.Windows.Forms.TabPage(); + this.splitContainer2 = new System.Windows.Forms.SplitContainer(); + this.SelDrawableTexturesTreeView = new CodeWalker.WinForms.TreeViewFix(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.SelTextureDimensionsLabel = new System.Windows.Forms.Label(); + this.SelTextureMipTrackBar = new System.Windows.Forms.TrackBar(); + this.SelTextureMipLabel = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.SelTextureDictionaryTextBox = new System.Windows.Forms.TextBox(); + this.SelTextureNameTextBox = new System.Windows.Forms.TextBox(); + this.SelDrawableTexturePictureBox = new System.Windows.Forms.PictureBox(); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.SelDrawableTexturePropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.SelectionHierarchyTabPage = new System.Windows.Forms.TabPage(); + this.splitContainer3 = new System.Windows.Forms.SplitContainer(); + this.HierarchyTreeView = new System.Windows.Forms.TreeView(); + this.HierarchyPropertyGrid = new CodeWalker.WinForms.PropertyGridFix(); + this.MouseSelectCheckBox = new System.Windows.Forms.CheckBox(); + this.SelectionNameTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label25 = new System.Windows.Forms.Label(); + this.SelectionModeComboBox = new System.Windows.Forms.ComboBox(); + this.SelectionTabControl.SuspendLayout(); + this.SelectionEntityTabPage.SuspendLayout(); + this.SelectionArchetypeTabPage.SuspendLayout(); + this.SelectionDrawableTabPage.SuspendLayout(); + this.SelectionExtensionTabPage.SuspendLayout(); + this.SelectionModelsTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.SelectionTexturesTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); + this.splitContainer2.Panel1.SuspendLayout(); + this.splitContainer2.Panel2.SuspendLayout(); + this.splitContainer2.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.SelTextureMipTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.SelDrawableTexturePictureBox)).BeginInit(); + this.tabPage4.SuspendLayout(); + this.SelectionHierarchyTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); + this.splitContainer3.Panel1.SuspendLayout(); + this.splitContainer3.Panel2.SuspendLayout(); + this.splitContainer3.SuspendLayout(); + this.SuspendLayout(); + // + // SelectionTabControl + // + this.SelectionTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectionTabControl.Controls.Add(this.SelectionEntityTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionArchetypeTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionDrawableTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionExtensionTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionModelsTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionTexturesTabPage); + this.SelectionTabControl.Controls.Add(this.SelectionHierarchyTabPage); + this.SelectionTabControl.Location = new System.Drawing.Point(10, 48); + this.SelectionTabControl.Name = "SelectionTabControl"; + this.SelectionTabControl.SelectedIndex = 0; + this.SelectionTabControl.Size = new System.Drawing.Size(735, 480); + this.SelectionTabControl.TabIndex = 28; + // + // SelectionEntityTabPage + // + this.SelectionEntityTabPage.Controls.Add(this.SelEntityPropertyGrid); + this.SelectionEntityTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionEntityTabPage.Name = "SelectionEntityTabPage"; + this.SelectionEntityTabPage.Padding = new System.Windows.Forms.Padding(3); + this.SelectionEntityTabPage.Size = new System.Drawing.Size(727, 454); + this.SelectionEntityTabPage.TabIndex = 0; + this.SelectionEntityTabPage.Text = "Entity"; + this.SelectionEntityTabPage.UseVisualStyleBackColor = true; + // + // SelEntityPropertyGrid + // + this.SelEntityPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelEntityPropertyGrid.HelpVisible = false; + this.SelEntityPropertyGrid.Location = new System.Drawing.Point(0, 0); + this.SelEntityPropertyGrid.Name = "SelEntityPropertyGrid"; + this.SelEntityPropertyGrid.Size = new System.Drawing.Size(727, 454); + this.SelEntityPropertyGrid.TabIndex = 25; + this.SelEntityPropertyGrid.ToolbarVisible = false; + // + // SelectionArchetypeTabPage + // + this.SelectionArchetypeTabPage.Controls.Add(this.SelArchetypePropertyGrid); + this.SelectionArchetypeTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionArchetypeTabPage.Name = "SelectionArchetypeTabPage"; + this.SelectionArchetypeTabPage.Padding = new System.Windows.Forms.Padding(3); + this.SelectionArchetypeTabPage.Size = new System.Drawing.Size(727, 454); + this.SelectionArchetypeTabPage.TabIndex = 1; + this.SelectionArchetypeTabPage.Text = "Archetype"; + this.SelectionArchetypeTabPage.UseVisualStyleBackColor = true; + // + // SelArchetypePropertyGrid + // + this.SelArchetypePropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelArchetypePropertyGrid.HelpVisible = false; + this.SelArchetypePropertyGrid.Location = new System.Drawing.Point(0, 0); + this.SelArchetypePropertyGrid.Name = "SelArchetypePropertyGrid"; + this.SelArchetypePropertyGrid.Size = new System.Drawing.Size(727, 454); + this.SelArchetypePropertyGrid.TabIndex = 26; + this.SelArchetypePropertyGrid.ToolbarVisible = false; + // + // SelectionDrawableTabPage + // + this.SelectionDrawableTabPage.Controls.Add(this.SelDrawablePropertyGrid); + this.SelectionDrawableTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionDrawableTabPage.Name = "SelectionDrawableTabPage"; + this.SelectionDrawableTabPage.Size = new System.Drawing.Size(727, 454); + this.SelectionDrawableTabPage.TabIndex = 2; + this.SelectionDrawableTabPage.Text = "Drawable"; + this.SelectionDrawableTabPage.UseVisualStyleBackColor = true; + // + // SelDrawablePropertyGrid + // + this.SelDrawablePropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawablePropertyGrid.HelpVisible = false; + this.SelDrawablePropertyGrid.Location = new System.Drawing.Point(0, 0); + this.SelDrawablePropertyGrid.Name = "SelDrawablePropertyGrid"; + this.SelDrawablePropertyGrid.Size = new System.Drawing.Size(727, 454); + this.SelDrawablePropertyGrid.TabIndex = 28; + this.SelDrawablePropertyGrid.ToolbarVisible = false; + // + // SelectionExtensionTabPage + // + this.SelectionExtensionTabPage.Controls.Add(this.SelExtensionPropertyGrid); + this.SelectionExtensionTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionExtensionTabPage.Name = "SelectionExtensionTabPage"; + this.SelectionExtensionTabPage.Size = new System.Drawing.Size(727, 454); + this.SelectionExtensionTabPage.TabIndex = 5; + this.SelectionExtensionTabPage.Text = "Extension"; + this.SelectionExtensionTabPage.UseVisualStyleBackColor = true; + // + // SelExtensionPropertyGrid + // + this.SelExtensionPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelExtensionPropertyGrid.HelpVisible = false; + this.SelExtensionPropertyGrid.Location = new System.Drawing.Point(0, 0); + this.SelExtensionPropertyGrid.Name = "SelExtensionPropertyGrid"; + this.SelExtensionPropertyGrid.Size = new System.Drawing.Size(727, 454); + this.SelExtensionPropertyGrid.TabIndex = 29; + this.SelExtensionPropertyGrid.ToolbarVisible = false; + // + // SelectionModelsTabPage + // + this.SelectionModelsTabPage.Controls.Add(this.splitContainer1); + this.SelectionModelsTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionModelsTabPage.Name = "SelectionModelsTabPage"; + this.SelectionModelsTabPage.Size = new System.Drawing.Size(727, 454); + this.SelectionModelsTabPage.TabIndex = 3; + this.SelectionModelsTabPage.Text = "Models"; + this.SelectionModelsTabPage.UseVisualStyleBackColor = true; + // + // splitContainer1 + // + this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.SelDrawableModelsTreeView); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.SelDrawableModelPropertyGrid); + this.splitContainer1.Size = new System.Drawing.Size(727, 454); + this.splitContainer1.SplitterDistance = 303; + this.splitContainer1.TabIndex = 2; + // + // SelDrawableModelsTreeView + // + this.SelDrawableModelsTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawableModelsTreeView.CheckBoxes = true; + this.SelDrawableModelsTreeView.Location = new System.Drawing.Point(0, 0); + this.SelDrawableModelsTreeView.Name = "SelDrawableModelsTreeView"; + this.SelDrawableModelsTreeView.Size = new System.Drawing.Size(300, 454); + this.SelDrawableModelsTreeView.TabIndex = 0; + this.SelDrawableModelsTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.SelDrawableModelsTreeView_AfterCheck); + this.SelDrawableModelsTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.SelDrawableModelsTreeView_AfterSelect); + // + // SelDrawableModelPropertyGrid + // + this.SelDrawableModelPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawableModelPropertyGrid.HelpVisible = false; + this.SelDrawableModelPropertyGrid.Location = new System.Drawing.Point(3, 0); + this.SelDrawableModelPropertyGrid.Name = "SelDrawableModelPropertyGrid"; + this.SelDrawableModelPropertyGrid.Size = new System.Drawing.Size(414, 454); + this.SelDrawableModelPropertyGrid.TabIndex = 27; + this.SelDrawableModelPropertyGrid.ToolbarVisible = false; + // + // SelectionTexturesTabPage + // + this.SelectionTexturesTabPage.Controls.Add(this.splitContainer2); + this.SelectionTexturesTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionTexturesTabPage.Name = "SelectionTexturesTabPage"; + this.SelectionTexturesTabPage.Size = new System.Drawing.Size(727, 454); + this.SelectionTexturesTabPage.TabIndex = 4; + this.SelectionTexturesTabPage.Text = "Textures"; + this.SelectionTexturesTabPage.UseVisualStyleBackColor = true; + // + // splitContainer2 + // + this.splitContainer2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer2.Location = new System.Drawing.Point(0, 0); + this.splitContainer2.Name = "splitContainer2"; + // + // splitContainer2.Panel1 + // + this.splitContainer2.Panel1.Controls.Add(this.SelDrawableTexturesTreeView); + // + // splitContainer2.Panel2 + // + this.splitContainer2.Panel2.Controls.Add(this.tabControl1); + this.splitContainer2.Size = new System.Drawing.Size(727, 454); + this.splitContainer2.SplitterDistance = 303; + this.splitContainer2.TabIndex = 1; + // + // SelDrawableTexturesTreeView + // + this.SelDrawableTexturesTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawableTexturesTreeView.HideSelection = false; + this.SelDrawableTexturesTreeView.Location = new System.Drawing.Point(0, 0); + this.SelDrawableTexturesTreeView.Name = "SelDrawableTexturesTreeView"; + this.SelDrawableTexturesTreeView.Size = new System.Drawing.Size(300, 454); + this.SelDrawableTexturesTreeView.TabIndex = 2; + this.SelDrawableTexturesTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.SelDrawableTexturesTreeView_AfterSelect); + // + // tabControl1 + // + this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Controls.Add(this.tabPage4); + this.tabControl1.Location = new System.Drawing.Point(3, 3); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(414, 451); + this.tabControl1.TabIndex = 31; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.SelTextureDimensionsLabel); + this.tabPage3.Controls.Add(this.SelTextureMipTrackBar); + this.tabPage3.Controls.Add(this.SelTextureMipLabel); + this.tabPage3.Controls.Add(this.label3); + this.tabPage3.Controls.Add(this.label2); + this.tabPage3.Controls.Add(this.SelTextureDictionaryTextBox); + this.tabPage3.Controls.Add(this.SelTextureNameTextBox); + this.tabPage3.Controls.Add(this.SelDrawableTexturePictureBox); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(406, 425); + this.tabPage3.TabIndex = 0; + this.tabPage3.Text = "Texture"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // SelTextureDimensionsLabel + // + this.SelTextureDimensionsLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.SelTextureDimensionsLabel.AutoSize = true; + this.SelTextureDimensionsLabel.Location = new System.Drawing.Point(334, 400); + this.SelTextureDimensionsLabel.Name = "SelTextureDimensionsLabel"; + this.SelTextureDimensionsLabel.Size = new System.Drawing.Size(10, 13); + this.SelTextureDimensionsLabel.TabIndex = 37; + this.SelTextureDimensionsLabel.Text = "-"; + // + // SelTextureMipTrackBar + // + this.SelTextureMipTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.SelTextureMipTrackBar.AutoSize = false; + this.SelTextureMipTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.SelTextureMipTrackBar.LargeChange = 1; + this.SelTextureMipTrackBar.Location = new System.Drawing.Point(59, 394); + this.SelTextureMipTrackBar.Maximum = 0; + this.SelTextureMipTrackBar.Name = "SelTextureMipTrackBar"; + this.SelTextureMipTrackBar.Size = new System.Drawing.Size(265, 31); + this.SelTextureMipTrackBar.TabIndex = 36; + this.SelTextureMipTrackBar.Scroll += new System.EventHandler(this.SelTextureMipTrackBar_Scroll); + // + // SelTextureMipLabel + // + this.SelTextureMipLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.SelTextureMipLabel.AutoSize = true; + this.SelTextureMipLabel.Location = new System.Drawing.Point(40, 400); + this.SelTextureMipLabel.Name = "SelTextureMipLabel"; + this.SelTextureMipLabel.Size = new System.Drawing.Size(13, 13); + this.SelTextureMipLabel.TabIndex = 35; + this.SelTextureMipLabel.Text = "0"; + // + // label3 + // + this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(7, 400); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(27, 13); + this.label3.TabIndex = 34; + this.label3.Text = "Mip:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(207, 9); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(57, 13); + this.label2.TabIndex = 33; + this.label2.Text = "Dictionary:"; + // + // SelTextureDictionaryTextBox + // + this.SelTextureDictionaryTextBox.Location = new System.Drawing.Point(270, 6); + this.SelTextureDictionaryTextBox.Name = "SelTextureDictionaryTextBox"; + this.SelTextureDictionaryTextBox.Size = new System.Drawing.Size(130, 20); + this.SelTextureDictionaryTextBox.TabIndex = 32; + // + // SelTextureNameTextBox + // + this.SelTextureNameTextBox.Location = new System.Drawing.Point(6, 6); + this.SelTextureNameTextBox.Name = "SelTextureNameTextBox"; + this.SelTextureNameTextBox.Size = new System.Drawing.Size(192, 20); + this.SelTextureNameTextBox.TabIndex = 31; + // + // SelDrawableTexturePictureBox + // + this.SelDrawableTexturePictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawableTexturePictureBox.BackColor = System.Drawing.Color.DarkGray; + this.SelDrawableTexturePictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.SelDrawableTexturePictureBox.Location = new System.Drawing.Point(0, 36); + this.SelDrawableTexturePictureBox.Name = "SelDrawableTexturePictureBox"; + this.SelDrawableTexturePictureBox.Size = new System.Drawing.Size(406, 351); + this.SelDrawableTexturePictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.SelDrawableTexturePictureBox.TabIndex = 29; + this.SelDrawableTexturePictureBox.TabStop = false; + // + // tabPage4 + // + this.tabPage4.Controls.Add(this.SelDrawableTexturePropertyGrid); + this.tabPage4.Location = new System.Drawing.Point(4, 22); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Padding = new System.Windows.Forms.Padding(3); + this.tabPage4.Size = new System.Drawing.Size(406, 425); + this.tabPage4.TabIndex = 1; + this.tabPage4.Text = "Info"; + this.tabPage4.UseVisualStyleBackColor = true; + // + // SelDrawableTexturePropertyGrid + // + this.SelDrawableTexturePropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelDrawableTexturePropertyGrid.HelpVisible = false; + this.SelDrawableTexturePropertyGrid.LineColor = System.Drawing.SystemColors.ControlDark; + this.SelDrawableTexturePropertyGrid.Location = new System.Drawing.Point(0, 0); + this.SelDrawableTexturePropertyGrid.Name = "SelDrawableTexturePropertyGrid"; + this.SelDrawableTexturePropertyGrid.Size = new System.Drawing.Size(406, 425); + this.SelDrawableTexturePropertyGrid.TabIndex = 28; + this.SelDrawableTexturePropertyGrid.ToolbarVisible = false; + // + // SelectionHierarchyTabPage + // + this.SelectionHierarchyTabPage.Controls.Add(this.splitContainer3); + this.SelectionHierarchyTabPage.Location = new System.Drawing.Point(4, 22); + this.SelectionHierarchyTabPage.Name = "SelectionHierarchyTabPage"; + this.SelectionHierarchyTabPage.Size = new System.Drawing.Size(727, 454); + this.SelectionHierarchyTabPage.TabIndex = 6; + this.SelectionHierarchyTabPage.Text = "Hierarchy"; + this.SelectionHierarchyTabPage.UseVisualStyleBackColor = true; + // + // splitContainer3 + // + this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer3.Location = new System.Drawing.Point(0, 0); + this.splitContainer3.Name = "splitContainer3"; + // + // splitContainer3.Panel1 + // + this.splitContainer3.Panel1.Controls.Add(this.HierarchyTreeView); + // + // splitContainer3.Panel2 + // + this.splitContainer3.Panel2.Controls.Add(this.HierarchyPropertyGrid); + this.splitContainer3.Size = new System.Drawing.Size(727, 454); + this.splitContainer3.SplitterDistance = 291; + this.splitContainer3.TabIndex = 0; + // + // HierarchyTreeView + // + this.HierarchyTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.HierarchyTreeView.FullRowSelect = true; + this.HierarchyTreeView.HideSelection = false; + this.HierarchyTreeView.Location = new System.Drawing.Point(3, 3); + this.HierarchyTreeView.Name = "HierarchyTreeView"; + this.HierarchyTreeView.Size = new System.Drawing.Size(285, 448); + this.HierarchyTreeView.TabIndex = 0; + this.HierarchyTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.HierarchyTreeView_AfterSelect); + // + // HierarchyPropertyGrid + // + this.HierarchyPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.HierarchyPropertyGrid.HelpVisible = false; + this.HierarchyPropertyGrid.Location = new System.Drawing.Point(3, 3); + this.HierarchyPropertyGrid.Name = "HierarchyPropertyGrid"; + this.HierarchyPropertyGrid.Size = new System.Drawing.Size(426, 448); + this.HierarchyPropertyGrid.TabIndex = 26; + this.HierarchyPropertyGrid.ToolbarVisible = false; + // + // MouseSelectCheckBox + // + this.MouseSelectCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.MouseSelectCheckBox.AutoSize = true; + this.MouseSelectCheckBox.Location = new System.Drawing.Point(598, 14); + this.MouseSelectCheckBox.Name = "MouseSelectCheckBox"; + this.MouseSelectCheckBox.Size = new System.Drawing.Size(143, 17); + this.MouseSelectCheckBox.TabIndex = 26; + this.MouseSelectCheckBox.Text = "Mouse select (right click)"; + this.MouseSelectCheckBox.UseVisualStyleBackColor = true; + this.MouseSelectCheckBox.CheckedChanged += new System.EventHandler(this.MouseSelectCheckBox_CheckedChanged); + // + // SelectionNameTextBox + // + this.SelectionNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.SelectionNameTextBox.Location = new System.Drawing.Point(56, 12); + this.SelectionNameTextBox.Name = "SelectionNameTextBox"; + this.SelectionNameTextBox.Size = new System.Drawing.Size(317, 20); + this.SelectionNameTextBox.TabIndex = 29; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 15); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 13); + this.label1.TabIndex = 30; + this.label1.Text = "Name:"; + // + // label25 + // + this.label25.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(408, 15); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(37, 13); + this.label25.TabIndex = 32; + this.label25.Text = "Mode:"; + // + // SelectionModeComboBox + // + this.SelectionModeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.SelectionModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.SelectionModeComboBox.FormattingEnabled = true; + this.SelectionModeComboBox.Items.AddRange(new object[] { + "Entity", + "Entity Extension", + "Archetype Extension", + "Time Cycle Modifier", + "Car Generator", + "Grass", + "Water Quad", + "Collision", + "Nav Mesh", + "Path", + "Train Track", + "Distant Lod Lights", + "Mlo Instance", + "Scenario"}); + this.SelectionModeComboBox.Location = new System.Drawing.Point(453, 12); + this.SelectionModeComboBox.Name = "SelectionModeComboBox"; + this.SelectionModeComboBox.Size = new System.Drawing.Size(121, 21); + this.SelectionModeComboBox.TabIndex = 31; + this.SelectionModeComboBox.SelectedIndexChanged += new System.EventHandler(this.SelectionModeComboBox_SelectedIndexChanged); + // + // WorldInfoForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(757, 540); + this.Controls.Add(this.label25); + this.Controls.Add(this.SelectionModeComboBox); + this.Controls.Add(this.label1); + this.Controls.Add(this.SelectionNameTextBox); + this.Controls.Add(this.SelectionTabControl); + this.Controls.Add(this.MouseSelectCheckBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "WorldInfoForm"; + this.Text = "Info - CodeWalker by dexyfex"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.WorldInfoForm_FormClosed); + this.Load += new System.EventHandler(this.WorldInfoForm_Load); + this.SelectionTabControl.ResumeLayout(false); + this.SelectionEntityTabPage.ResumeLayout(false); + this.SelectionArchetypeTabPage.ResumeLayout(false); + this.SelectionDrawableTabPage.ResumeLayout(false); + this.SelectionExtensionTabPage.ResumeLayout(false); + this.SelectionModelsTabPage.ResumeLayout(false); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.SelectionTexturesTabPage.ResumeLayout(false); + this.splitContainer2.Panel1.ResumeLayout(false); + this.splitContainer2.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); + this.splitContainer2.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.SelTextureMipTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.SelDrawableTexturePictureBox)).EndInit(); + this.tabPage4.ResumeLayout(false); + this.SelectionHierarchyTabPage.ResumeLayout(false); + this.splitContainer3.Panel1.ResumeLayout(false); + this.splitContainer3.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); + this.splitContainer3.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TabControl SelectionTabControl; + private System.Windows.Forms.TabPage SelectionEntityTabPage; + private CodeWalker.WinForms.PropertyGridFix SelEntityPropertyGrid; + private System.Windows.Forms.TabPage SelectionArchetypeTabPage; + private CodeWalker.WinForms.PropertyGridFix SelArchetypePropertyGrid; + private System.Windows.Forms.TabPage SelectionDrawableTabPage; + private System.Windows.Forms.CheckBox MouseSelectCheckBox; + private System.Windows.Forms.TextBox SelectionNameTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TabPage SelectionModelsTabPage; + private System.Windows.Forms.SplitContainer splitContainer1; + private TreeViewFix SelDrawableModelsTreeView; + private CodeWalker.WinForms.PropertyGridFix SelDrawableModelPropertyGrid; + private System.Windows.Forms.TabPage SelectionTexturesTabPage; + private System.Windows.Forms.SplitContainer splitContainer2; + private TreeViewFix SelDrawableTexturesTreeView; + private System.Windows.Forms.PictureBox SelDrawableTexturePictureBox; + private CodeWalker.WinForms.PropertyGridFix SelDrawableTexturePropertyGrid; + private CodeWalker.WinForms.PropertyGridFix SelDrawablePropertyGrid; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.TabPage tabPage4; + private System.Windows.Forms.TrackBar SelTextureMipTrackBar; + private System.Windows.Forms.Label SelTextureMipLabel; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox SelTextureDictionaryTextBox; + private System.Windows.Forms.TextBox SelTextureNameTextBox; + private System.Windows.Forms.Label SelTextureDimensionsLabel; + private System.Windows.Forms.Label label25; + private System.Windows.Forms.ComboBox SelectionModeComboBox; + private System.Windows.Forms.TabPage SelectionExtensionTabPage; + private CodeWalker.WinForms.PropertyGridFix SelExtensionPropertyGrid; + private System.Windows.Forms.TabPage SelectionHierarchyTabPage; + private System.Windows.Forms.SplitContainer splitContainer3; + private System.Windows.Forms.TreeView HierarchyTreeView; + private PropertyGridFix HierarchyPropertyGrid; + } +} \ No newline at end of file diff --git a/WorldInfoForm.cs b/WorldInfoForm.cs new file mode 100644 index 0000000..dc69b08 --- /dev/null +++ b/WorldInfoForm.cs @@ -0,0 +1,489 @@ +using CodeWalker.GameFiles; +using CodeWalker.Rendering; +using CodeWalker.Utils; +using SharpDX; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class WorldInfoForm : Form + { + WorldForm WorldForm; + MapSelection Selection; + string SelectionMode = ""; + bool MouseSelectEnable = false; + + public WorldInfoForm(WorldForm worldForm) + { + WorldForm = worldForm; + InitializeComponent(); + + //SelectionModeComboBox.SelectedIndex = 0; + } + + private void MouseSelectCheckBox_CheckedChanged(object sender, EventArgs e) + { + if (MouseSelectCheckBox.Checked != MouseSelectEnable) + { + MouseSelectEnable = MouseSelectCheckBox.Checked; + WorldForm.OnInfoFormSelectionModeChanged(SelectionMode, MouseSelectEnable); + } + } + + private void SelectionModeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + if (SelectionModeComboBox.Text != SelectionMode) + { + SelectionMode = SelectionModeComboBox.Text; + WorldForm.OnInfoFormSelectionModeChanged(SelectionMode, MouseSelectEnable); + } + } + + public void SetSelectionMode(string mode, bool enable) + { + SelectionMode = mode; + MouseSelectEnable = enable; + SelectionModeComboBox.Text = mode; + MouseSelectCheckBox.Checked = enable; + } + + public void SetSelection(MapSelection item) + { + Selection = item; + + SelectionNameTextBox.Text = item.GetNameString("Nothing selected"); + //SelEntityPropertyGrid.SelectedObject = item.EntityDef; + SelArchetypePropertyGrid.SelectedObject = item.Archetype; + SelDrawablePropertyGrid.SelectedObject = item.Drawable; + SelDrawableModelPropertyGrid.SelectedObject = null; + SelDrawableModelsTreeView.Nodes.Clear(); + SelDrawableTexturesTreeView.Nodes.Clear(); + SelDrawableTexturePropertyGrid.SelectedObject = null; + SelDrawableTexturePictureBox.Image = null; + HierarchyTreeView.Nodes.Clear(); + if (item.Drawable != null) + { + AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsHigh, "High Detail", true); + AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsMedium, "Medium Detail", false); + AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsLow, "Low Detail", false); + AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsVeryLow, "Very Low Detail", false); + //AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsX, "X Detail", false); + } + + if (item.EntityDef != null) + { + AddSelectionEntityHierarchyNodes(item.EntityDef); + } + + + if (item.TimeCycleModifier != null) + { + SelectionEntityTabPage.Text = "Time Cycle Modifier"; + SelEntityPropertyGrid.SelectedObject = item.TimeCycleModifier; + } + else if (item.CarGenerator != null) + { + SelectionEntityTabPage.Text = "Car Generator"; + SelEntityPropertyGrid.SelectedObject = item.CarGenerator; + } + else if (item.DistantLodLights != null) + { + SelectionEntityTabPage.Text = "Distant LOD Lights"; + SelEntityPropertyGrid.SelectedObject = item.DistantLodLights; + } + else if (item.GrassBatch != null) + { + SelectionEntityTabPage.Text = "Grass"; + SelEntityPropertyGrid.SelectedObject = item.GrassBatch; + } + else if (item.WaterQuad != null) + { + SelectionEntityTabPage.Text = "Water Quad"; + SelEntityPropertyGrid.SelectedObject = item.WaterQuad; + } + else if (item.NavPoly != null) + { + SelectionEntityTabPage.Text = "Nav Poly"; + SelEntityPropertyGrid.SelectedObject = item.NavPoly; + } + else if (item.PathNode != null) + { + SelectionEntityTabPage.Text = "Path Node"; + SelEntityPropertyGrid.SelectedObject = item.PathNode; + } + else if (item.TrainTrackNode != null) + { + SelectionEntityTabPage.Text = "Train Track Node"; + SelEntityPropertyGrid.SelectedObject = item.TrainTrackNode; + } + else if (item.ScenarioNode != null) + { + SelectionEntityTabPage.Text = item.ScenarioNode.FullTypeName; + SelEntityPropertyGrid.SelectedObject = item.ScenarioNode; + } + else + { + SelectionEntityTabPage.Text = "Entity"; + SelEntityPropertyGrid.SelectedObject = item.EntityDef; + } + + + if (item.EntityExtension != null) + { + SelectionExtensionTabPage.Text = "Entity Extension"; + SelExtensionPropertyGrid.SelectedObject = item.EntityExtension; + } + else if (item.ArchetypeExtension != null) + { + SelectionExtensionTabPage.Text = "Archetype Extension"; + SelExtensionPropertyGrid.SelectedObject = item.ArchetypeExtension; + } + else if (item.CollisionBounds != null) + { + SelectionExtensionTabPage.Text = "Collision Bounds"; + SelExtensionPropertyGrid.SelectedObject = item.CollisionBounds; + } + else + { + SelectionExtensionTabPage.Text = "Extension"; + SelExtensionPropertyGrid.SelectedObject = null; + } + + } + private void AddSelectionDrawableModelsTreeNodes(ResourcePointerList64 models, string prefix, bool check) + { + if (models == null) return; + if (models.data_items == null) return; + + for (int mi = 0; mi < models.data_items.Length; mi++) + { + var model = models.data_items[mi]; + string mprefix = prefix + " " + (mi + 1).ToString(); + var mnode = SelDrawableModelsTreeView.Nodes.Add(mprefix + " " + model.ToString()); + mnode.Tag = model; + mnode.Checked = check; + + var tmnode = SelDrawableTexturesTreeView.Nodes.Add(mprefix + " " + model.ToString()); + tmnode.Tag = model; + + if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + + foreach (var geom in model.Geometries.data_items) + { + var gname = geom.ToString(); + var gnode = mnode.Nodes.Add(gname); + gnode.Tag = geom; + gnode.Checked = true;// check; + + var tgnode = tmnode.Nodes.Add(gname); + tgnode.Tag = geom; + + if ((geom.Shader != null) && (geom.Shader.ParametersList != null) && (geom.Shader.ParametersList.Hashes != null)) + { + var pl = geom.Shader.ParametersList; + var h = pl.Hashes; + var p = pl.Parameters; + for (int ip = 0; ip < h.Length; ip++) + { + var hash = pl.Hashes[ip]; + var parm = pl.Parameters[ip]; + var tex = parm.Data as TextureBase; + if (tex != null) + { + var t = tex as Texture; + var tstr = tex.Name.Trim(); + if (t != null) + { + tstr = string.Format("{0} ({1}x{2}, embedded)", tex.Name, t.Width, t.Height); + } + var tnode = tgnode.Nodes.Add(hash.ToString().Trim() + ": " + tstr); + tnode.Tag = tex; + } + } + tgnode.Expand(); + } + + } + + mnode.Expand(); + tmnode.Expand(); + } + } + + private void AddSelectionEntityHierarchyNodes(YmapEntityDef entity) + { + if (entity == null) return; + + var e = entity; + TreeNode tn = null; + TreeNode seltn = null; + + while (e != null) + { + var newtn = new TreeNode(e.Name); + newtn.Tag = e; + if (tn != null) + { + newtn.Nodes.Add(tn); + } + else + { + seltn = newtn; + } + if (e.Children != null) + { + foreach (var c in e.Children) + { + if ((tn != null) && (c == tn.Tag)) continue; + var ctn = new TreeNode(c.Name); + ctn.Tag = c; + newtn.Nodes.Add(ctn); + } + } + + tn = newtn; + e = e.Parent; + } + + if (tn != null) + { + HierarchyTreeView.Nodes.Add(tn); + tn.ExpandAll(); + } + if (seltn != null) + { + HierarchyTreeView.SelectedNode = seltn; + } + + } + + + private void DisplayTexture(Texture tex, int mip) + { + try + { + int cmip = Math.Min(Math.Max(mip, 0), tex.Levels - 1); + byte[] pixels = DDSIO.GetPixels(tex, cmip); + int w = tex.Width >> cmip; + int h = tex.Height >> cmip; + Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); + + if (pixels != null) + { + var BoundsRect = new System.Drawing.Rectangle(0, 0, w, h); + BitmapData bmpData = bmp.LockBits(BoundsRect, ImageLockMode.WriteOnly, bmp.PixelFormat); + IntPtr ptr = bmpData.Scan0; + int bytes = bmpData.Stride * bmp.Height; + Marshal.Copy(pixels, 0, ptr, bytes); + bmp.UnlockBits(bmpData); + } + + SelDrawableTexturePictureBox.Image = bmp; + SelTextureDimensionsLabel.Text = w.ToString() + " x " + h.ToString(); + } + catch (Exception ex) + { + MessageBox.Show("Error reading texture mip:\n" + ex.ToString()); + SelDrawableTexturePictureBox.Image = null; + } + } + + private void SelectTexture(TextureBase texbase, bool mipchange) + { + Texture tex = texbase as Texture; + YtdFile ytd = null; + string errstr = string.Empty; + if ((tex == null)&&(texbase!=null)) + { + //need to load from txd. + var arch = Selection.Archetype; + uint texhash = texbase.NameHash; + uint txdHash = (arch != null) ? arch.TextureDict.Hash : 0; + tex = TryGetTextureFromYtd(texhash, txdHash, out ytd); + if (tex == null) + { //search parent ytds... + uint ptxdhash = WorldForm.GameFileCache.TryGetParentYtdHash(txdHash); + while ((ptxdhash != 0) && (tex == null)) + { + tex = TryGetTextureFromYtd(texhash, ptxdhash, out ytd); + if (tex == null) + { + ptxdhash = WorldForm.GameFileCache.TryGetParentYtdHash(ptxdhash); + } + else + { } + } + if (tex == null) + { + ytd = WorldForm.GameFileCache.TryGetTextureDictForTexture(texhash); + if (ytd != null) + { + int tries = 0; + while (!ytd.Loaded && (tries < 500)) //wait upto ~5 sec + { + System.Threading.Thread.Sleep(10); + tries++; + } + if (ytd.Loaded) + { + tex = ytd.TextureDict.Lookup(texhash); + } + } + if (tex == null) + { + ytd = null; + errstr = ""; + } + } + } + } + if (tex != null) + { + int mip = 0; + if (mipchange) + { + mip = SelTextureMipTrackBar.Value; + if (mip >= tex.Levels) mip = tex.Levels - 1; + } + else + { + SelTextureMipTrackBar.Maximum = tex.Levels - 1; + } + DisplayTexture(tex, mip); + + + //try get owner drawable to get the name for the dictionary textbox... + object owner = null; + if (Selection.Drawable != null) + { + owner = Selection.Drawable.Owner; + } + YdrFile ydr = owner as YdrFile; + YddFile ydd = owner as YddFile; + YftFile yft = owner as YftFile; + + SelTextureNameTextBox.Text = tex.Name; + SelTextureDictionaryTextBox.Text = (ytd != null) ? ytd.Name : (ydr != null) ? ydr.Name : (ydd != null) ? ydd.Name : (yft != null) ? yft.Name : string.Empty; + } + else + { + SelDrawableTexturePictureBox.Image = null; + SelTextureNameTextBox.Text = errstr; + SelTextureDictionaryTextBox.Text = string.Empty; + SelTextureMipTrackBar.Value = 0; + SelTextureMipTrackBar.Maximum = 0; + SelTextureDimensionsLabel.Text = "-"; + } + } + + private Texture TryGetTextureFromYtd(uint texHash, uint txdHash, out YtdFile ytd) + { + if (txdHash != 0) + { + ytd = WorldForm.GameFileCache.GetYtd(txdHash); + if (ytd != null) + { + int tries = 0; + while (!ytd.Loaded && (tries < 500)) //wait upto ~5 sec + { + System.Threading.Thread.Sleep(10); + tries++; + } + if (ytd.Loaded) + { + return ytd.TextureDict.Lookup(texHash); + } + } + } + ytd = null; + return null; + } + + + private void WorldInfoForm_Load(object sender, EventArgs e) + { + SetSelection(Selection); + } + + private void WorldInfoForm_FormClosed(object sender, FormClosedEventArgs e) + { + WorldForm.OnInfoFormClosed(); + } + + public void SyncSelDrawableModelsTreeNode(TreeNode node) + { + //called by the world form when a selection treeview node is checked/unchecked. + foreach (TreeNode mnode in SelDrawableModelsTreeView.Nodes) + { + if (mnode.Tag == node.Tag) + { + if (mnode.Checked != node.Checked) + { + mnode.Checked = node.Checked; + } + } + foreach (TreeNode gnode in mnode.Nodes) + { + if (gnode.Tag == node.Tag) + { + if (gnode.Checked != node.Checked) + { + gnode.Checked = node.Checked; + } + } + } + } + } + + private void SelDrawableModelsTreeView_AfterCheck(object sender, TreeViewEventArgs e) + { + WorldForm.SyncSelDrawableModelsTreeNode(e.Node); + } + + private void SelDrawableModelsTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + SelDrawableModelPropertyGrid.SelectedObject = e.Node?.Tag; + } + + private void SelDrawableTexturesTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + SelDrawableTexturePropertyGrid.SelectedObject = e.Node?.Tag; + + TextureBase texbase = e.Node?.Tag as TextureBase; + + SelTextureMipTrackBar.Value = 0; + SelTextureMipLabel.Text = "0"; + + SelectTexture(texbase, false); + } + + private void SelTextureMipTrackBar_Scroll(object sender, EventArgs e) + { + var node = SelDrawableTexturesTreeView.SelectedNode; + + TextureBase texbase = node?.Tag as TextureBase; + + SelTextureMipLabel.Text = SelTextureMipTrackBar.Value.ToString(); + + SelectTexture(texbase, true); + } + + private void HierarchyTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + var sele = HierarchyTreeView.SelectedNode?.Tag as YmapEntityDef; + HierarchyPropertyGrid.SelectedObject = sele; + } + } +} diff --git a/WorldInfoForm.resx b/WorldInfoForm.resx new file mode 100644 index 0000000..1431f6b --- /dev/null +++ b/WorldInfoForm.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/WorldSearchForm.Designer.cs b/WorldSearchForm.Designer.cs new file mode 100644 index 0000000..92cb078 --- /dev/null +++ b/WorldSearchForm.Designer.cs @@ -0,0 +1,668 @@ +namespace CodeWalker +{ + partial class WorldSearchForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WorldSearchForm)); + this.MainTabControl = new System.Windows.Forms.TabControl(); + this.EntitySearchTabPage = new System.Windows.Forms.TabPage(); + this.splitContainer2 = new System.Windows.Forms.SplitContainer(); + this.EntityResultsListView = new System.Windows.Forms.ListView(); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.EntityResultPanel = new System.Windows.Forms.Panel(); + this.EntityResultViewModelButton = new System.Windows.Forms.Button(); + this.EntityResultPropertyGrid = new CodeWalker.WinForms.ReadOnlyPropertyGrid(); + this.label7 = new System.Windows.Forms.Label(); + this.EntityResultGoToButton = new System.Windows.Forms.Button(); + this.label8 = new System.Windows.Forms.Label(); + this.EntityResultYmapTextBox = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.EntityResultNameTextBox = new System.Windows.Forms.TextBox(); + this.EntitySearchStatusLabel = new System.Windows.Forms.Label(); + this.EntitySearchAbortButton = new System.Windows.Forms.Button(); + this.EntitySearchButton = new System.Windows.Forms.Button(); + this.EntitySearchLoadedOnlyCheckBox = new System.Windows.Forms.CheckBox(); + this.EntitySearchHashLabel = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.EntitySearchTextBox = new System.Windows.Forms.TextBox(); + this.ArchetypeSearchTabPage = new System.Windows.Forms.TabPage(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.ArchetypeResultsListView = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.ArchetypeResultPanel = new System.Windows.Forms.Panel(); + this.ArchetypeResultPropertyGrid = new CodeWalker.WinForms.ReadOnlyPropertyGrid(); + this.label6 = new System.Windows.Forms.Label(); + this.ArchetypeResultViewModelButton = new System.Windows.Forms.Button(); + this.label5 = new System.Windows.Forms.Label(); + this.ArchetypeResultFindEntitiesButton = new System.Windows.Forms.Button(); + this.ArchetypeResultYtypTextBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.ArchetypeResultNameTextBox = new System.Windows.Forms.TextBox(); + this.ArchetypeSearchStatusLabel = new System.Windows.Forms.Label(); + this.ArchetypeSearchAbortButton = new System.Windows.Forms.Button(); + this.ArchetypeSearchButton = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.ArchetypeSearchTextBox = new System.Windows.Forms.TextBox(); + this.EntitySearchExportResultsButton = new System.Windows.Forms.Button(); + this.ArchetypeSearchExportResultsButton = new System.Windows.Forms.Button(); + this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog(); + this.MainTabControl.SuspendLayout(); + this.EntitySearchTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); + this.splitContainer2.Panel1.SuspendLayout(); + this.splitContainer2.Panel2.SuspendLayout(); + this.splitContainer2.SuspendLayout(); + this.EntityResultPanel.SuspendLayout(); + this.ArchetypeSearchTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.ArchetypeResultPanel.SuspendLayout(); + this.SuspendLayout(); + // + // MainTabControl + // + this.MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.MainTabControl.Controls.Add(this.EntitySearchTabPage); + this.MainTabControl.Controls.Add(this.ArchetypeSearchTabPage); + this.MainTabControl.Location = new System.Drawing.Point(4, 4); + this.MainTabControl.Name = "MainTabControl"; + this.MainTabControl.SelectedIndex = 0; + this.MainTabControl.Size = new System.Drawing.Size(530, 421); + this.MainTabControl.TabIndex = 0; + // + // EntitySearchTabPage + // + this.EntitySearchTabPage.Controls.Add(this.EntitySearchExportResultsButton); + this.EntitySearchTabPage.Controls.Add(this.splitContainer2); + this.EntitySearchTabPage.Controls.Add(this.EntitySearchStatusLabel); + this.EntitySearchTabPage.Controls.Add(this.EntitySearchAbortButton); + this.EntitySearchTabPage.Controls.Add(this.EntitySearchButton); + this.EntitySearchTabPage.Controls.Add(this.EntitySearchLoadedOnlyCheckBox); + this.EntitySearchTabPage.Controls.Add(this.EntitySearchHashLabel); + this.EntitySearchTabPage.Controls.Add(this.label1); + this.EntitySearchTabPage.Controls.Add(this.EntitySearchTextBox); + this.EntitySearchTabPage.Location = new System.Drawing.Point(4, 22); + this.EntitySearchTabPage.Name = "EntitySearchTabPage"; + this.EntitySearchTabPage.Padding = new System.Windows.Forms.Padding(3); + this.EntitySearchTabPage.Size = new System.Drawing.Size(522, 395); + this.EntitySearchTabPage.TabIndex = 0; + this.EntitySearchTabPage.Text = "Entity Search"; + this.EntitySearchTabPage.UseVisualStyleBackColor = true; + // + // splitContainer2 + // + this.splitContainer2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer2.Location = new System.Drawing.Point(0, 94); + this.splitContainer2.Name = "splitContainer2"; + // + // splitContainer2.Panel1 + // + this.splitContainer2.Panel1.Controls.Add(this.EntityResultsListView); + // + // splitContainer2.Panel2 + // + this.splitContainer2.Panel2.Controls.Add(this.EntityResultPanel); + this.splitContainer2.Size = new System.Drawing.Size(522, 301); + this.splitContainer2.SplitterDistance = 325; + this.splitContainer2.TabIndex = 8; + // + // EntityResultsListView + // + this.EntityResultsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityResultsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader3, + this.columnHeader4}); + this.EntityResultsListView.FullRowSelect = true; + this.EntityResultsListView.HideSelection = false; + this.EntityResultsListView.Location = new System.Drawing.Point(3, 0); + this.EntityResultsListView.MultiSelect = false; + this.EntityResultsListView.Name = "EntityResultsListView"; + this.EntityResultsListView.Size = new System.Drawing.Size(319, 298); + this.EntityResultsListView.TabIndex = 8; + this.EntityResultsListView.UseCompatibleStateImageBehavior = false; + this.EntityResultsListView.View = System.Windows.Forms.View.Details; + this.EntityResultsListView.VirtualMode = true; + this.EntityResultsListView.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.EntityResultsListView_RetrieveVirtualItem); + this.EntityResultsListView.SelectedIndexChanged += new System.EventHandler(this.EntityResultsListView_SelectedIndexChanged); + this.EntityResultsListView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.EntityResultsListView_MouseDoubleClick); + // + // columnHeader3 + // + this.columnHeader3.Text = "Name"; + this.columnHeader3.Width = 131; + // + // columnHeader4 + // + this.columnHeader4.Text = "File"; + this.columnHeader4.Width = 161; + // + // EntityResultPanel + // + this.EntityResultPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityResultPanel.Controls.Add(this.EntityResultViewModelButton); + this.EntityResultPanel.Controls.Add(this.EntityResultPropertyGrid); + this.EntityResultPanel.Controls.Add(this.label7); + this.EntityResultPanel.Controls.Add(this.EntityResultGoToButton); + this.EntityResultPanel.Controls.Add(this.label8); + this.EntityResultPanel.Controls.Add(this.EntityResultYmapTextBox); + this.EntityResultPanel.Controls.Add(this.label9); + this.EntityResultPanel.Controls.Add(this.EntityResultNameTextBox); + this.EntityResultPanel.Enabled = false; + this.EntityResultPanel.Location = new System.Drawing.Point(3, 0); + this.EntityResultPanel.Name = "EntityResultPanel"; + this.EntityResultPanel.Size = new System.Drawing.Size(187, 298); + this.EntityResultPanel.TabIndex = 9; + // + // EntityResultViewModelButton + // + this.EntityResultViewModelButton.Location = new System.Drawing.Point(94, 91); + this.EntityResultViewModelButton.Name = "EntityResultViewModelButton"; + this.EntityResultViewModelButton.Size = new System.Drawing.Size(89, 23); + this.EntityResultViewModelButton.TabIndex = 5; + this.EntityResultViewModelButton.Text = "View model"; + this.EntityResultViewModelButton.UseVisualStyleBackColor = true; + this.EntityResultViewModelButton.Click += new System.EventHandler(this.EntityResultViewModelButton_Click); + // + // EntityResultPropertyGrid + // + this.EntityResultPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityResultPropertyGrid.HelpVisible = false; + this.EntityResultPropertyGrid.Location = new System.Drawing.Point(3, 146); + this.EntityResultPropertyGrid.Name = "EntityResultPropertyGrid"; + this.EntityResultPropertyGrid.ReadOnly = true; + this.EntityResultPropertyGrid.Size = new System.Drawing.Size(181, 152); + this.EntityResultPropertyGrid.TabIndex = 7; + this.EntityResultPropertyGrid.ToolbarVisible = false; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(3, 130); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(56, 13); + this.label7.TabIndex = 6; + this.label7.Text = "Entity info:"; + // + // EntityResultGoToButton + // + this.EntityResultGoToButton.Location = new System.Drawing.Point(3, 91); + this.EntityResultGoToButton.Name = "EntityResultGoToButton"; + this.EntityResultGoToButton.Size = new System.Drawing.Size(89, 23); + this.EntityResultGoToButton.TabIndex = 4; + this.EntityResultGoToButton.Text = "Go to entity"; + this.EntityResultGoToButton.UseVisualStyleBackColor = true; + this.EntityResultGoToButton.Click += new System.EventHandler(this.EntityResultGoToButton_Click); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(3, 48); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(53, 13); + this.label8.TabIndex = 2; + this.label8.Text = "Ymap file:"; + // + // EntityResultYmapTextBox + // + this.EntityResultYmapTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityResultYmapTextBox.BackColor = System.Drawing.SystemColors.Window; + this.EntityResultYmapTextBox.Location = new System.Drawing.Point(3, 64); + this.EntityResultYmapTextBox.Name = "EntityResultYmapTextBox"; + this.EntityResultYmapTextBox.ReadOnly = true; + this.EntityResultYmapTextBox.Size = new System.Drawing.Size(180, 20); + this.EntityResultYmapTextBox.TabIndex = 3; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(3, 7); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(80, 13); + this.label9.TabIndex = 0; + this.label9.Text = "Selected result:"; + // + // EntityResultNameTextBox + // + this.EntityResultNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntityResultNameTextBox.BackColor = System.Drawing.SystemColors.Window; + this.EntityResultNameTextBox.Location = new System.Drawing.Point(3, 23); + this.EntityResultNameTextBox.Name = "EntityResultNameTextBox"; + this.EntityResultNameTextBox.ReadOnly = true; + this.EntityResultNameTextBox.Size = new System.Drawing.Size(180, 20); + this.EntityResultNameTextBox.TabIndex = 1; + // + // EntitySearchStatusLabel + // + this.EntitySearchStatusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.EntitySearchStatusLabel.AutoEllipsis = true; + this.EntitySearchStatusLabel.Location = new System.Drawing.Point(6, 73); + this.EntitySearchStatusLabel.Name = "EntitySearchStatusLabel"; + this.EntitySearchStatusLabel.Size = new System.Drawing.Size(510, 18); + this.EntitySearchStatusLabel.TabIndex = 7; + this.EntitySearchStatusLabel.Text = "Ready"; + // + // EntitySearchAbortButton + // + this.EntitySearchAbortButton.Enabled = false; + this.EntitySearchAbortButton.Location = new System.Drawing.Point(152, 43); + this.EntitySearchAbortButton.Name = "EntitySearchAbortButton"; + this.EntitySearchAbortButton.Size = new System.Drawing.Size(75, 23); + this.EntitySearchAbortButton.TabIndex = 4; + this.EntitySearchAbortButton.Text = "Abort"; + this.EntitySearchAbortButton.UseVisualStyleBackColor = true; + this.EntitySearchAbortButton.Click += new System.EventHandler(this.EntitySearchAbortButton_Click); + // + // EntitySearchButton + // + this.EntitySearchButton.Location = new System.Drawing.Point(71, 43); + this.EntitySearchButton.Name = "EntitySearchButton"; + this.EntitySearchButton.Size = new System.Drawing.Size(75, 23); + this.EntitySearchButton.TabIndex = 3; + this.EntitySearchButton.Text = "Search"; + this.EntitySearchButton.UseVisualStyleBackColor = true; + this.EntitySearchButton.Click += new System.EventHandler(this.EntitySearchButton_Click); + // + // EntitySearchLoadedOnlyCheckBox + // + this.EntitySearchLoadedOnlyCheckBox.AutoSize = true; + this.EntitySearchLoadedOnlyCheckBox.Checked = true; + this.EntitySearchLoadedOnlyCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.EntitySearchLoadedOnlyCheckBox.Location = new System.Drawing.Point(277, 47); + this.EntitySearchLoadedOnlyCheckBox.Name = "EntitySearchLoadedOnlyCheckBox"; + this.EntitySearchLoadedOnlyCheckBox.Size = new System.Drawing.Size(105, 17); + this.EntitySearchLoadedOnlyCheckBox.TabIndex = 5; + this.EntitySearchLoadedOnlyCheckBox.Text = "Loaded files only"; + this.EntitySearchLoadedOnlyCheckBox.UseVisualStyleBackColor = true; + // + // EntitySearchHashLabel + // + this.EntitySearchHashLabel.AutoSize = true; + this.EntitySearchHashLabel.Location = new System.Drawing.Point(276, 16); + this.EntitySearchHashLabel.Name = "EntitySearchHashLabel"; + this.EntitySearchHashLabel.Size = new System.Drawing.Size(22, 13); + this.EntitySearchHashLabel.TabIndex = 1; + this.EntitySearchHashLabel.Text = " "; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(6, 16); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(59, 13); + this.label1.TabIndex = 2; + this.label1.Text = "Search for:"; + // + // EntitySearchTextBox + // + this.EntitySearchTextBox.Location = new System.Drawing.Point(71, 13); + this.EntitySearchTextBox.Name = "EntitySearchTextBox"; + this.EntitySearchTextBox.Size = new System.Drawing.Size(199, 20); + this.EntitySearchTextBox.TabIndex = 0; + this.EntitySearchTextBox.TextChanged += new System.EventHandler(this.EntitySearchTextBox_TextChanged); + this.EntitySearchTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.EntitySearchTextBox_KeyPress); + // + // ArchetypeSearchTabPage + // + this.ArchetypeSearchTabPage.Controls.Add(this.ArchetypeSearchExportResultsButton); + this.ArchetypeSearchTabPage.Controls.Add(this.splitContainer1); + this.ArchetypeSearchTabPage.Controls.Add(this.ArchetypeSearchStatusLabel); + this.ArchetypeSearchTabPage.Controls.Add(this.ArchetypeSearchAbortButton); + this.ArchetypeSearchTabPage.Controls.Add(this.ArchetypeSearchButton); + this.ArchetypeSearchTabPage.Controls.Add(this.label3); + this.ArchetypeSearchTabPage.Controls.Add(this.ArchetypeSearchTextBox); + this.ArchetypeSearchTabPage.Location = new System.Drawing.Point(4, 22); + this.ArchetypeSearchTabPage.Name = "ArchetypeSearchTabPage"; + this.ArchetypeSearchTabPage.Size = new System.Drawing.Size(522, 395); + this.ArchetypeSearchTabPage.TabIndex = 1; + this.ArchetypeSearchTabPage.Text = "Archetype Search"; + this.ArchetypeSearchTabPage.UseVisualStyleBackColor = true; + // + // splitContainer1 + // + this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer1.Location = new System.Drawing.Point(0, 94); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.ArchetypeResultsListView); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.ArchetypeResultPanel); + this.splitContainer1.Size = new System.Drawing.Size(522, 301); + this.splitContainer1.SplitterDistance = 325; + this.splitContainer1.TabIndex = 7; + // + // ArchetypeResultsListView + // + this.ArchetypeResultsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ArchetypeResultsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.ArchetypeResultsListView.FullRowSelect = true; + this.ArchetypeResultsListView.HideSelection = false; + this.ArchetypeResultsListView.Location = new System.Drawing.Point(3, 0); + this.ArchetypeResultsListView.MultiSelect = false; + this.ArchetypeResultsListView.Name = "ArchetypeResultsListView"; + this.ArchetypeResultsListView.Size = new System.Drawing.Size(319, 298); + this.ArchetypeResultsListView.TabIndex = 6; + this.ArchetypeResultsListView.UseCompatibleStateImageBehavior = false; + this.ArchetypeResultsListView.View = System.Windows.Forms.View.Details; + this.ArchetypeResultsListView.VirtualMode = true; + this.ArchetypeResultsListView.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.ArchetypeResultsListView_RetrieveVirtualItem); + this.ArchetypeResultsListView.SelectedIndexChanged += new System.EventHandler(this.ArchetypeResultsListView_SelectedIndexChanged); + this.ArchetypeResultsListView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.ArchetypeResultsListView_MouseDoubleClick); + // + // columnHeader1 + // + this.columnHeader1.Text = "Name"; + this.columnHeader1.Width = 131; + // + // columnHeader2 + // + this.columnHeader2.Text = "File"; + this.columnHeader2.Width = 161; + // + // ArchetypeResultPanel + // + this.ArchetypeResultPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ArchetypeResultPanel.Controls.Add(this.ArchetypeResultPropertyGrid); + this.ArchetypeResultPanel.Controls.Add(this.label6); + this.ArchetypeResultPanel.Controls.Add(this.ArchetypeResultViewModelButton); + this.ArchetypeResultPanel.Controls.Add(this.label5); + this.ArchetypeResultPanel.Controls.Add(this.ArchetypeResultFindEntitiesButton); + this.ArchetypeResultPanel.Controls.Add(this.ArchetypeResultYtypTextBox); + this.ArchetypeResultPanel.Controls.Add(this.label4); + this.ArchetypeResultPanel.Controls.Add(this.ArchetypeResultNameTextBox); + this.ArchetypeResultPanel.Enabled = false; + this.ArchetypeResultPanel.Location = new System.Drawing.Point(3, 0); + this.ArchetypeResultPanel.Name = "ArchetypeResultPanel"; + this.ArchetypeResultPanel.Size = new System.Drawing.Size(187, 298); + this.ArchetypeResultPanel.TabIndex = 7; + // + // ArchetypeResultPropertyGrid + // + this.ArchetypeResultPropertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ArchetypeResultPropertyGrid.HelpVisible = false; + this.ArchetypeResultPropertyGrid.Location = new System.Drawing.Point(3, 146); + this.ArchetypeResultPropertyGrid.Name = "ArchetypeResultPropertyGrid"; + this.ArchetypeResultPropertyGrid.ReadOnly = true; + this.ArchetypeResultPropertyGrid.Size = new System.Drawing.Size(181, 152); + this.ArchetypeResultPropertyGrid.TabIndex = 7; + this.ArchetypeResultPropertyGrid.ToolbarVisible = false; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(3, 130); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(78, 13); + this.label6.TabIndex = 6; + this.label6.Text = "Archetype info:"; + // + // ArchetypeResultViewModelButton + // + this.ArchetypeResultViewModelButton.Location = new System.Drawing.Point(94, 91); + this.ArchetypeResultViewModelButton.Name = "ArchetypeResultViewModelButton"; + this.ArchetypeResultViewModelButton.Size = new System.Drawing.Size(89, 23); + this.ArchetypeResultViewModelButton.TabIndex = 5; + this.ArchetypeResultViewModelButton.Text = "View model"; + this.ArchetypeResultViewModelButton.UseVisualStyleBackColor = true; + this.ArchetypeResultViewModelButton.Click += new System.EventHandler(this.ArchetypeResultViewModelButton_Click); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(3, 48); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(47, 13); + this.label5.TabIndex = 2; + this.label5.Text = "Ytyp file:"; + // + // ArchetypeResultFindEntitiesButton + // + this.ArchetypeResultFindEntitiesButton.Location = new System.Drawing.Point(3, 91); + this.ArchetypeResultFindEntitiesButton.Name = "ArchetypeResultFindEntitiesButton"; + this.ArchetypeResultFindEntitiesButton.Size = new System.Drawing.Size(89, 23); + this.ArchetypeResultFindEntitiesButton.TabIndex = 4; + this.ArchetypeResultFindEntitiesButton.Text = "Find entities"; + this.ArchetypeResultFindEntitiesButton.UseVisualStyleBackColor = true; + this.ArchetypeResultFindEntitiesButton.Click += new System.EventHandler(this.ArchetypeResultFindEntitiesButton_Click); + // + // ArchetypeResultYtypTextBox + // + this.ArchetypeResultYtypTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ArchetypeResultYtypTextBox.BackColor = System.Drawing.SystemColors.Window; + this.ArchetypeResultYtypTextBox.Location = new System.Drawing.Point(3, 64); + this.ArchetypeResultYtypTextBox.Name = "ArchetypeResultYtypTextBox"; + this.ArchetypeResultYtypTextBox.ReadOnly = true; + this.ArchetypeResultYtypTextBox.Size = new System.Drawing.Size(180, 20); + this.ArchetypeResultYtypTextBox.TabIndex = 3; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(3, 7); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(80, 13); + this.label4.TabIndex = 0; + this.label4.Text = "Selected result:"; + // + // ArchetypeResultNameTextBox + // + this.ArchetypeResultNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ArchetypeResultNameTextBox.BackColor = System.Drawing.SystemColors.Window; + this.ArchetypeResultNameTextBox.Location = new System.Drawing.Point(3, 23); + this.ArchetypeResultNameTextBox.Name = "ArchetypeResultNameTextBox"; + this.ArchetypeResultNameTextBox.ReadOnly = true; + this.ArchetypeResultNameTextBox.Size = new System.Drawing.Size(180, 20); + this.ArchetypeResultNameTextBox.TabIndex = 1; + // + // ArchetypeSearchStatusLabel + // + this.ArchetypeSearchStatusLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ArchetypeSearchStatusLabel.AutoEllipsis = true; + this.ArchetypeSearchStatusLabel.Location = new System.Drawing.Point(6, 73); + this.ArchetypeSearchStatusLabel.Name = "ArchetypeSearchStatusLabel"; + this.ArchetypeSearchStatusLabel.Size = new System.Drawing.Size(510, 18); + this.ArchetypeSearchStatusLabel.TabIndex = 6; + this.ArchetypeSearchStatusLabel.Text = "Ready"; + // + // ArchetypeSearchAbortButton + // + this.ArchetypeSearchAbortButton.Enabled = false; + this.ArchetypeSearchAbortButton.Location = new System.Drawing.Point(152, 43); + this.ArchetypeSearchAbortButton.Name = "ArchetypeSearchAbortButton"; + this.ArchetypeSearchAbortButton.Size = new System.Drawing.Size(75, 23); + this.ArchetypeSearchAbortButton.TabIndex = 4; + this.ArchetypeSearchAbortButton.Text = "Abort"; + this.ArchetypeSearchAbortButton.UseVisualStyleBackColor = true; + this.ArchetypeSearchAbortButton.Click += new System.EventHandler(this.ArchetypeSearchAbortButton_Click); + // + // ArchetypeSearchButton + // + this.ArchetypeSearchButton.Location = new System.Drawing.Point(71, 43); + this.ArchetypeSearchButton.Name = "ArchetypeSearchButton"; + this.ArchetypeSearchButton.Size = new System.Drawing.Size(75, 23); + this.ArchetypeSearchButton.TabIndex = 3; + this.ArchetypeSearchButton.Text = "Search"; + this.ArchetypeSearchButton.UseVisualStyleBackColor = true; + this.ArchetypeSearchButton.Click += new System.EventHandler(this.ArchetypeSearchButton_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(6, 16); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(59, 13); + this.label3.TabIndex = 1; + this.label3.Text = "Search for:"; + // + // ArchetypeSearchTextBox + // + this.ArchetypeSearchTextBox.Location = new System.Drawing.Point(71, 13); + this.ArchetypeSearchTextBox.Name = "ArchetypeSearchTextBox"; + this.ArchetypeSearchTextBox.Size = new System.Drawing.Size(199, 20); + this.ArchetypeSearchTextBox.TabIndex = 0; + this.ArchetypeSearchTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ArchetypeSearchTextBox_KeyPress); + // + // EntitySearchExportResultsButton + // + this.EntitySearchExportResultsButton.Enabled = false; + this.EntitySearchExportResultsButton.Location = new System.Drawing.Point(426, 43); + this.EntitySearchExportResultsButton.Name = "EntitySearchExportResultsButton"; + this.EntitySearchExportResultsButton.Size = new System.Drawing.Size(89, 23); + this.EntitySearchExportResultsButton.TabIndex = 6; + this.EntitySearchExportResultsButton.Text = "Export results..."; + this.EntitySearchExportResultsButton.UseVisualStyleBackColor = true; + this.EntitySearchExportResultsButton.Click += new System.EventHandler(this.EntitySearchExportResultsButton_Click); + // + // ArchetypeSearchExportResultsButton + // + this.ArchetypeSearchExportResultsButton.Enabled = false; + this.ArchetypeSearchExportResultsButton.Location = new System.Drawing.Point(426, 43); + this.ArchetypeSearchExportResultsButton.Name = "ArchetypeSearchExportResultsButton"; + this.ArchetypeSearchExportResultsButton.Size = new System.Drawing.Size(89, 23); + this.ArchetypeSearchExportResultsButton.TabIndex = 5; + this.ArchetypeSearchExportResultsButton.Text = "Export results..."; + this.ArchetypeSearchExportResultsButton.UseVisualStyleBackColor = true; + this.ArchetypeSearchExportResultsButton.Click += new System.EventHandler(this.ArchetypeSearchExportResultsButton_Click); + // + // SaveFileDialog + // + this.SaveFileDialog.AddExtension = false; + this.SaveFileDialog.Filter = "Text files|*.txt|CSV files|*.csv|All files|*.*"; + // + // WorldSearchForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(536, 428); + this.Controls.Add(this.MainTabControl); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "WorldSearchForm"; + this.Text = "World Search - CodeWalker by dexyfex"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.WorldSearchForm_FormClosed); + this.MainTabControl.ResumeLayout(false); + this.EntitySearchTabPage.ResumeLayout(false); + this.EntitySearchTabPage.PerformLayout(); + this.splitContainer2.Panel1.ResumeLayout(false); + this.splitContainer2.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); + this.splitContainer2.ResumeLayout(false); + this.EntityResultPanel.ResumeLayout(false); + this.EntityResultPanel.PerformLayout(); + this.ArchetypeSearchTabPage.ResumeLayout(false); + this.ArchetypeSearchTabPage.PerformLayout(); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.ArchetypeResultPanel.ResumeLayout(false); + this.ArchetypeResultPanel.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TabControl MainTabControl; + private System.Windows.Forms.TabPage EntitySearchTabPage; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox EntitySearchTextBox; + private System.Windows.Forms.Label EntitySearchHashLabel; + private System.Windows.Forms.TabPage ArchetypeSearchTabPage; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox ArchetypeSearchTextBox; + private System.Windows.Forms.CheckBox EntitySearchLoadedOnlyCheckBox; + private System.Windows.Forms.Panel ArchetypeResultPanel; + private System.Windows.Forms.Button ArchetypeSearchButton; + private System.Windows.Forms.ListView ArchetypeResultsListView; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.Button ArchetypeResultFindEntitiesButton; + private System.Windows.Forms.TextBox ArchetypeResultYtypTextBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox ArchetypeResultNameTextBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Button ArchetypeSearchAbortButton; + private System.Windows.Forms.Label ArchetypeSearchStatusLabel; + private WinForms.ReadOnlyPropertyGrid ArchetypeResultPropertyGrid; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button ArchetypeResultViewModelButton; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.SplitContainer splitContainer2; + private System.Windows.Forms.ListView EntityResultsListView; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.Panel EntityResultPanel; + private WinForms.ReadOnlyPropertyGrid EntityResultPropertyGrid; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Button EntityResultGoToButton; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox EntityResultYmapTextBox; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox EntityResultNameTextBox; + private System.Windows.Forms.Label EntitySearchStatusLabel; + private System.Windows.Forms.Button EntitySearchAbortButton; + private System.Windows.Forms.Button EntitySearchButton; + private System.Windows.Forms.Button EntityResultViewModelButton; + private System.Windows.Forms.Button EntitySearchExportResultsButton; + private System.Windows.Forms.Button ArchetypeSearchExportResultsButton; + private System.Windows.Forms.SaveFileDialog SaveFileDialog; + } +} \ No newline at end of file diff --git a/WorldSearchForm.cs b/WorldSearchForm.cs new file mode 100644 index 0000000..d76d6e3 --- /dev/null +++ b/WorldSearchForm.cs @@ -0,0 +1,520 @@ +using CodeWalker.GameFiles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker +{ + public partial class WorldSearchForm : Form + { + private WorldForm WorldForm; + + private volatile bool AbortOperation = false; + + private List ArchetypeResults = new List(); + private List EntityResults = new List(); + + public WorldSearchForm(WorldForm worldForm) + { + WorldForm = worldForm; + InitializeComponent(); + } + + private void WorldSearchForm_FormClosed(object sender, FormClosedEventArgs e) + { + WorldForm.OnSearchFormClosed(); + } + + private void ArchetypeSearchTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == (char)13) + { + ArchetypeSearchButton_Click(sender, e); + e.Handled = true; + } + } + + private void ArchetypeSearchButton_Click(object sender, EventArgs e) + { + var s = ArchetypeSearchTextBox.Text; + var loadedOnly = false;// ArchetypeSearchLoadedOnlyCheckBox.Checked; //NOT WORKING... + + var gfc = WorldForm.GameFileCache; + if (!gfc.IsInited) + { + MessageBox.Show("Please wait for CodeWalker to initialise."); + return; + } + if (s.Length == 0) + { + MessageBox.Show("Please enter a search term."); + return; + } + if (s.Length < 2) + { + MessageBox.Show("You don't really want to search for that do you?"); + return; + } + + ArchetypeSearchTextBox.Enabled = false; + ArchetypeSearchButton.Enabled = false; + ArchetypeSearchAbortButton.Enabled = true; + ArchetypeSearchExportResultsButton.Enabled = false; + AbortOperation = false; + ArchetypeResults.Clear(); + ArchetypeResultsListView.VirtualListSize = 0; + + s = s.ToLowerInvariant(); + + Task.Run(() => + { + + var rpfman = gfc.RpfMan; + var rpflist = loadedOnly ? gfc.ActiveMapRpfFiles.Values.ToList() : rpfman.AllRpfs; + var results = new List(); + + foreach (var rpf in rpflist) + { + foreach (var entry in rpf.AllEntries) + { + try + { + if (AbortOperation) + { + ArchetypeSearchUpdateStatus("Search aborted!"); + ArchetypeSearchComplete(); + return; + } + if (entry.NameLower.EndsWith(".ytyp")) + { + ArchetypeSearchUpdateStatus(entry.Path); + + YtypFile ytyp = rpfman.GetFile(entry); + if (ytyp == null) continue; + if (ytyp.AllArchetypes == null) continue; + + foreach (var arch in ytyp.AllArchetypes) + { + if (arch.Name.ToLowerInvariant().Contains(s) + || arch.AssetName.ToLowerInvariant().Contains(s)) + { + ArchetypeSearchAddResult(arch); + results.Add(arch); + } + } + } + } + catch (Exception ex) + { + ArchetypeSearchUpdateStatus(ex.Message); + } + } + } + + ArchetypeSearchUpdateStatus("Search complete. " + results.Count.ToString() + " archetypes found."); + ArchetypeSearchComplete(); + }); + + } + + private void ArchetypeSearchUpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { ArchetypeSearchUpdateStatus(text); })); + } + else + { + ArchetypeSearchStatusLabel.Text = text; + } + } + catch { } + } + + private void ArchetypeSearchAddResult(Archetype arch) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { ArchetypeSearchAddResult(arch); })); + } + else + { + ArchetypeResults.Add(arch); + ArchetypeResultsListView.VirtualListSize = ArchetypeResults.Count; + } + } + catch { } + } + + private void ArchetypeSearchComplete() + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { ArchetypeSearchComplete(); })); + } + else + { + ArchetypeSearchTextBox.Enabled = true; + ArchetypeSearchButton.Enabled = true; + ArchetypeSearchAbortButton.Enabled = false; + ArchetypeSearchExportResultsButton.Enabled = true; + } + } + catch { } + } + + private void ArchetypeSearchAbortButton_Click(object sender, EventArgs e) + { + AbortOperation = true; + } + + private void ArchetypeSearchExportResultsButton_Click(object sender, EventArgs e) + { + if (ArchetypeResults.Count == 0) + { + MessageBox.Show("Nothing to export!"); + return; + } + + SaveFileDialog.FileName = "Archetypes_" + ArchetypeSearchTextBox.Text; + if (SaveFileDialog.ShowDialog() != DialogResult.OK) + { + return; + } + + string fname = SaveFileDialog.FileName; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine("Name, AssetName, YtypFile"); + foreach (var arch in ArchetypeResults) + { + sb.AppendLine(string.Format("{0}, {1}, {2}", arch.Name, arch.AssetName, arch.Ytyp?.FileEntry?.Path ?? "")); + } + + File.WriteAllText(fname, sb.ToString()); + } + + private void ArchetypeResultsListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) + { + if (e.ItemIndex < ArchetypeResults.Count) + { + var arch = ArchetypeResults[e.ItemIndex]; + var li = new ListViewItem(new[] { arch.Name, arch.Ytyp?.FileEntry?.Path ?? "" }); + li.Tag = arch; + e.Item = li; + } + else + { + e.Item = new ListViewItem("Error retrieving Archetype! Please tell dexyfex"); + } + } + + private void ArchetypeResultsListView_SelectedIndexChanged(object sender, EventArgs e) + { + if (ArchetypeResultsListView.SelectedIndices.Count == 0) + { + ArchetypeResultPanel.Enabled = false; + ArchetypeResultNameTextBox.Text = ""; + ArchetypeResultYtypTextBox.Text = ""; + ArchetypeResultPropertyGrid.SelectedObject = null; + } + else + { + var li = ArchetypeResultsListView.SelectedIndices[0]; + if (li < ArchetypeResults.Count) + { + var arch = ArchetypeResults[li]; + ArchetypeResultPanel.Enabled = true; + ArchetypeResultNameTextBox.Text = arch.Name; + ArchetypeResultYtypTextBox.Text = arch.Ytyp?.FileEntry?.Path ?? ""; + ArchetypeResultPropertyGrid.SelectedObject = arch; + } + } + } + + private void ArchetypeResultsListView_MouseDoubleClick(object sender, MouseEventArgs e) + { + if (ArchetypeResultsListView.SelectedIndices.Count > 0) + { + ArchetypeResultViewModelButton_Click(sender, e); + } + } + + private void ArchetypeResultFindEntitiesButton_Click(object sender, EventArgs e) + { + MainTabControl.SelectedTab = EntitySearchTabPage; + EntitySearchTextBox.Text = ArchetypeResultNameTextBox.Text; + EntitySearchButton_Click(sender, e); + } + + private void ArchetypeResultViewModelButton_Click(object sender, EventArgs e) + { + WorldForm.ShowModel(ArchetypeResultNameTextBox.Text); + } + + private void EntitySearchTextBox_TextChanged(object sender, EventArgs e) + { + //JenkHash h = new JenkHash(EntitySearchTextBox.Text, JenkHashInputEncoding.UTF8); + //EntitySearchHashLabel.Text = "Hash: " + h.HashUint.ToString() + " (" + h.HashHex + ")"; + } + + private void EntitySearchTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == (char)13) + { + EntitySearchButton_Click(sender, e); + e.Handled = true; + } + } + + private void EntitySearchButton_Click(object sender, EventArgs e) + { + var s = EntitySearchTextBox.Text; + var loadedOnly = EntitySearchLoadedOnlyCheckBox.Checked; + + var gfc = WorldForm.GameFileCache; + if (!gfc.IsInited) + { + MessageBox.Show("Please wait for CodeWalker to initialise."); + return; + } + if (s.Length == 0) + { + MessageBox.Show("Please enter a search term."); + return; + } + if (s.Length < 2) + { + MessageBox.Show("You don't really want to search for that do you?"); + return; + } + + EntitySearchTextBox.Enabled = false; + EntitySearchButton.Enabled = false; + EntitySearchAbortButton.Enabled = true; + EntitySearchLoadedOnlyCheckBox.Enabled = false; + EntitySearchExportResultsButton.Enabled = false; + AbortOperation = false; + EntityResults.Clear(); + EntityResultsListView.VirtualListSize = 0; + + s = s.ToLowerInvariant(); + //var h = JenkHash.GenHash(s, JenkHashInputEncoding.UTF8); + + Task.Run(() => + { + + var rpfman = gfc.RpfMan; + var rpflist = loadedOnly ? gfc.ActiveMapRpfFiles.Values.ToList() : rpfman.AllRpfs; + var results = new List(); + + foreach (var rpf in rpflist) + { + foreach (var entry in rpf.AllEntries) + { + try + { + if (AbortOperation) + { + EntitySearchUpdateStatus("Search aborted!"); + EntitySearchComplete(); + return; + } + if (entry.NameLower.EndsWith(".ymap")) + { + EntitySearchUpdateStatus(entry.Path); + + YmapFile ymap = rpfman.GetFile(entry); + if (ymap == null) continue; + if (ymap.AllEntities == null) continue; + + foreach (var ent in ymap.AllEntities) + { + //if (ent._CEntityDef.archetypeName.Hash == h) + if (ent.Name.ToLowerInvariant().Contains(s)) + { + EntitySearchAddResult(ent); + results.Add(ent); + } + } + } + } + catch (Exception ex) + { + EntitySearchUpdateStatus(ex.Message); + } + } + } + + EntitySearchUpdateStatus("Search complete. " + results.Count.ToString() + " entities found."); + EntitySearchComplete(); + }); + } + + private void EntitySearchUpdateStatus(string text) + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { EntitySearchUpdateStatus(text); })); + } + else + { + EntitySearchStatusLabel.Text = text; + } + } + catch { } + } + + private void EntitySearchAddResult(YmapEntityDef ent) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new Action(() => { EntitySearchAddResult(ent); })); + } + else + { + EntityResults.Add(ent); + EntityResultsListView.VirtualListSize = EntityResults.Count; + } + } + catch { } + } + + private void EntitySearchComplete() + { + try + { + if (InvokeRequired) + { + Invoke(new Action(() => { EntitySearchComplete(); })); + } + else + { + EntitySearchTextBox.Enabled = true; + EntitySearchButton.Enabled = true; + EntitySearchAbortButton.Enabled = false; + EntitySearchLoadedOnlyCheckBox.Enabled = true; + EntitySearchExportResultsButton.Enabled = true; + } + } + catch { } + } + + private void EntitySearchAbortButton_Click(object sender, EventArgs e) + { + AbortOperation = true; + } + + private void EntitySearchExportResultsButton_Click(object sender, EventArgs e) + { + if (EntityResults.Count == 0) + { + MessageBox.Show("Nothing to export!"); + return; + } + + SaveFileDialog.FileName = "Entities_" + EntitySearchTextBox.Text; + if (SaveFileDialog.ShowDialog() != DialogResult.OK) + { + return; + } + + string fname = SaveFileDialog.FileName; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine("ArchetypeName, PositionX, PositionY, PositionZ, RotationX, RotationY, RotationZ, RotationW, YmapFile"); + foreach (var ent in EntityResults) + { + sb.AppendLine(string.Format("{0}, {1}, {2}, {3}", ent.Name, FloatUtil.GetVector3String(ent._CEntityDef.position), FloatUtil.GetVector4String(ent._CEntityDef.rotation), ent.Ymap?.RpfFileEntry?.Path ?? "")); + } + + File.WriteAllText(fname, sb.ToString()); + } + + private void EntityResultsListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) + { + if (e.ItemIndex < EntityResults.Count) + { + var ent = EntityResults[e.ItemIndex]; + var li = new ListViewItem(new[] { ent.Name, ent.Ymap?.RpfFileEntry?.Path ?? "" }); + li.Tag = ent; + e.Item = li; + } + else + { + e.Item = new ListViewItem("Error retrieving YmapEntityDef! Please tell dexyfex"); + } + } + + private void EntityResultsListView_SelectedIndexChanged(object sender, EventArgs e) + { + if (EntityResultsListView.SelectedIndices.Count == 0) + { + EntityResultPanel.Enabled = false; + EntityResultNameTextBox.Text = ""; + EntityResultYmapTextBox.Text = ""; + EntityResultPropertyGrid.SelectedObject = null; + } + else + { + var li = EntityResultsListView.SelectedIndices[0]; + if (li < EntityResults.Count) + { + var ent = EntityResults[li]; + EntityResultPanel.Enabled = true; + EntityResultNameTextBox.Text = ent.Name; + EntityResultYmapTextBox.Text = ent.Ymap?.RpfFileEntry?.Path ?? ""; + EntityResultPropertyGrid.SelectedObject = ent; + } + } + } + + private void EntityResultsListView_MouseDoubleClick(object sender, MouseEventArgs e) + { + if (EntityResultsListView.SelectedIndices.Count > 0) + { + EntityResultGoToButton_Click(sender, e); + } + } + + private void EntityResultGoToButton_Click(object sender, EventArgs e) + { + if (EntityResultsListView.SelectedIndices.Count > 0) + { + var li = EntityResultsListView.SelectedIndices[0]; + if (li < EntityResults.Count) + { + var ent = EntityResults[li]; + if (ent.Archetype == null) + { + var gfc = WorldForm.GameFileCache; + ent.Archetype = gfc.GetArchetype(ent._CEntityDef.archetypeName); + } + WorldForm.GoToEntity(ent); + } + } + } + + private void EntityResultViewModelButton_Click(object sender, EventArgs e) + { + WorldForm.ShowModel(EntityResultNameTextBox.Text); + } + } +} diff --git a/WorldSearchForm.resx b/WorldSearchForm.resx new file mode 100644 index 0000000..c7e1c95 --- /dev/null +++ b/WorldSearchForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA + AABAAAAAAQAYAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv8/u3v+Pn6//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AP7+/vX3/rzA3OHl9fz9/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7//+zv+3Z6qcLI5Pr7/wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAP7+/+br+15in6+33vf5/wAAAAAAAAAAAAAAAP7+//7+/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//v8//v8//3+/wAAAAAAAAAAAAAAAAAAAP7+/+Ho+1dana20 + 4/b4/wAAAAAAAPz9//P2/+Tp/ezw/vz9/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///X4 + /9Pa+tPa+/H1//z9/wAAAAAAAAAAAAAAAP7+/93k+SsscaSr3PX3/wAAAP7+//L1/7W98AcWgrvC8Pj6 + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/+bs/xohiAEJdrvF9+7y//z9/wAAAAAAAAAA + AP7+/9rh+CEkapmh0/T3/wAAAPj6/9HZ/AEHcgEEb9LZ+/r7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAP7//+/z/3F+zAAAXwQLcZai3fb4/wAAAAAAAAAAAP3+/97l/E9Tmaau4fT3/wAAAO/0/1dd + sAAAV7a/8/H1//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPr8/+jv/46Y3QUUf6Ot + 5PX4/wAAAAAAAAAAAP3+/9zj+3Z6wLe/7fX4/wAAAPD0/212xnaAzerw//z9/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPv8/+/z/+Dm+/D0//z9/wAAAAAAAP7+//j6/9Pd+UhLjb/H + 9/D0//3+//n7/+nt/+jt//n7/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AP7///7+//7+//7+/wAAAAAAAPr8/+7z/83W+ImU2A0UdFNarr/K9env//X4//z9//3+//7//wAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7///j6/+Pq/255 + xhckjE5XsVVftUlTqwAKeTA9nr3H8+7z//v8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+//b4/9Tc+Sc0mRonj8rV/crX/ZSb48rX/brG8wwWgQAEdJei + 4efu//n7//7+//z9//z9//z9//z9//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//f5/+3y/+nv/+ft + /8vV+io2mImU2M7c/7vG9yIvlQAOfCg4mM3Y/s/c/4aR1AQRfGtzwtni/ebt/9vi/tri/tXd+9Tc+O3x + /vz9/wAAAAAAAAAAAAAAAAAAAAAAAPn6/87V+FVftkRPrFlnvSEqjQoUfmJvwWFvvg0TfQQIcxEchwAD + cy89n19rvVVitQwZgwAAaiMrkT9NqTVBoiw3mhQihig1mNLX+fv8/wAAAAAAAAAAAAAAAAAAAAAAAPb5 + /52l4EFLqoCK03yF0VBctGhyw52o5GVrvQAAaneBzsHM+jA3mhYgiTtIpJOf3ouW2AAAbmh0wbbA8bS+ + 7qiz5pCb16+56e/z//3+/wAAAAAAAAAAAAAAAAAAAAAAAPv8//H1/+vw/+zx/+nv/7/J9YqP3MbP/8LM + +hwqkFZftaCp5EhRrcTQ+9jj/8rW/UJMqn6J0ebt//X3//f5//b4//X3//f5//z9/wAAAAAAAAAAAAAA + AAAAAAAAAP7+//z9//3+/wAAAAAAAP3+/+7z/6at64iP3aWs7XN8zRIfhyUykp2o5MHM+oKM0xonjY6X + 2+jv//v8/wAAAP7+//n7//b5//r7//7//wAAAAAAAAAAAAAAAP7+//f5/+rw/9Pa9fL0/v7//wAAAAAA + APv8//H1/+Tr/7i/91liu0NPq0VQrS06m0NNqDdCoYqU1+nv//v8/wAAAAAAAPn7/9zi/qSt59ri/fL1 + //v8//7//wAAAPz9//D0/8rT+h0sjkVQrPD0/wAAAAAAAAAAAAAAAAAAAPz9/+7z/8LL9Jqk4aGq6LW/ + 8c3W9+Xs/vH1//v8/wAAAAAAAAAAAPf5/6at5gAAbxIfh6u16+Po/fr7/wAAAPb5/6ev5gAIeAAPernC + 8fX4/wAAAAAAAP3+//v8//z9/wAAAP3+//j6//P3//P2//b4//r8//7+//7+//v8//r8//3+/wAAAPv8 + /+Xr/nuIzwAAbBseg5Sb2fb5/wAAAPf5/8DF8pWe3d/n/vT3//39/wAAAPv8/+zx/87V9+3x/v3+/wAA + AP3+//j6//X4//v8/wAAAAAAAPn7/+Dm/snR9fD0//39//z8/fv8/+3y/8LK9aGq4dfd9/n7/wAAAPz9 + //b5//X4//v8/wAAAAAAAP7+/+7z/4aP1gEPet7k/f39/wAAAPf5/83U+ZCZ2u3x/v7+/wAAAPP3/215 + wgAJd7fB8/L1//7+/wAAAP3+//j6//f5//r8//7+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAPj6/87W/AAA + X2duue3y//7+/wAAAPD0/05asBQfidzj/P39/wAAAPX4/6Su6AAAXBccgtff/vv8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPP3/3F8xhYli9Xe/fn6/wAAAAAAAO3y/1pltQAJd9be + /fv8/wAAAPz9/+rw/36I0Bknjs/W+vv8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAPf5/8HI7tnf+/X4//7+/wAAAAAAAO/0/3R7xgAAb9ng/Pz9/wAAAAAAAPn7/+Ln/dLY+fP2//3+ + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP3+//r7//v8//7+/wAAAAAAAAAA + APb4/7/F84eP0e/0//7+/wAAAAAAAP7+//z9//v8//3+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz9//b5//X4//v8/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////w////4 + P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA + AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA + AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v// + /////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/icons/icon_glokon_debug_32x32.png b/icons/icon_glokon_debug_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..97de45779e7197eb008676dc37a95322508287e5 GIT binary patch literal 1952 zcmaJ?c~lek77k!g6BVRD5k*6!SPRKyvKVF{AS6*E5-Cs;Jt~A`2q`3!WgsDdP%QOG z^W4An{L}Cz` zB2#w_2_X=id{uE$Od7QcmZNIA%#NX()LNWPAcTaOv@&@rf>DwXrAou2+Rk2}Qd9~a zRl`7<(LoLy0>MBElL4{-kO43u8VJH{E(|WAOe`uM zO|M9XV+6}4V&N|yH3h@8FaQ{hM!JzjNA*eogdhlDFaai$h9hW(ObsS8(KLpIlO6%{9GT>*{^BnAM=s3QBQgxt$DwH2WcQ*| zPz*Jspjrx_Px)A)(kM`)VX?ik6G9QaDg#k0)1zw2cxhnOd%{NuSz!1QCZEq?^T(w# zAVCnH$zlpw5Ld_zr%rGc?@4=tEBL=$02c$;`}(&&Pnz)Iv0vX!E&g~n_lO1`c0E4T z#N91t2!tsfB0+eZsi#_!n&K{T4`l^+58OyD%S6w=y@P=wo&LH}$k-0!!GBQ{yep3*3EmKbPF92A}w!-QP4E zeD>3f=R5xW`o(=Y-S}kRv%6WXyhmHvk26bRmJ;{mMK*resIPUMk+pl>^Gz|Jparz|>Dt%llx^|^+XB3uNT$J&h}4VKot5H)Z8=)t^o&xM8fTXVC}5mSnd!@$8$pL%zQXc?_hY)PJEXG-qew1kKKCpOF{hyI4icD-(EPsZ?k#gRH@eiW{Hi6Z=mRY9q45ZmpqMJP2IOA8k$2)w(l1S| zi4yPEW46kzPn5+G{72=FM>lwSM0aeq780NDUeH7w$n0HxlU4Oq%k4JXXJ3<|m%j|T zV)Zp}XHM^9mPIn>!1=S+A1x$#H3)q|^SSV*Pr@Bo=3nBs|2z_R)74GeFN*yFJabri zPHesBKo9kp4`QKP*E$Rrl1@vjq%#gw3^pd@UpjuMd;67*kDlZm&ra0e`3Va4E|v(1 zrRx$q-7aPMxjBaA^;cZi2ClT)o^PAQ`F;4U(j?pMXKqd+Kl@S83}#)3&l-*2#nk|1 zmsWMAh{Y@K&ilPIsN!&zE;6xp=(d$o@W9bDt9@{~afHZD5K`NP&4b*zY{~VAO@uxoW*H=Th!qrHJ%3lDrxR7RuSfm^RC!PoQKyb{+r zZ9BKAat}Fv4fXkjLU`MSoi`nT;*nlPl;S_@e7C&ftsd0vB|EG?oN;2#W4Eq`wzZ`l z1N)EBH`Xa1gmjk=Pp2;>=kQu;PCIgZK6hsw2sj8@`p6eQ+~F7C`rX3&eJ|Yh&$6ZN z=tf&_WilNsoz5LPMbZ8EY>UqIkKj_3ffa@WQU+2R_G zW|Lk_P5Wc^=y_7nPRzQhXkX8PT}9bhmj+%B(eeftz4gf{Rs@{BQ?qT^n17J%>PN<_ zs(ZOx#_pbKj!$M-TgkR8a>?1n%db+y&x;K{Nfnm$87{%S%@qYh1YzQgMOQ{kIL7)f z$$_QMkotW?Q`TtbB^>uIVUMmh)s%-k$aQcgR9*yo*K{_Wv;Q+iLb0GGA~FAemRA!* literal 0 HcmV?d00001 diff --git a/icons/icon_glokon_normal_32x32.png b/icons/icon_glokon_normal_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..3c655315a50f2d32f5dcd29f5814d8ef793b7f7b GIT binary patch literal 2074 zcmaJ?X;f3^77de7hN6fdL*bH888o@MAt59ZkPHYs0s#S|Kto6_5Fmp|ATi)jEd{9$ zK^&++tCc~PfR)jfA|g0d3RDn8X`~g22#7pw(WgQa3-BJ-`av zY+-6|ia;PNf`jOh+7r-yCM&eNOr?6RJ?!KRwtR~?Nv_~ZVMG95oCpKKLT)k~33K^7 zciez|5eNepK@?lgW`>e^Vj+gB!(fy`iI$B(`1&g)TwWS12NL0Afrx^fZRq5ERqM)DM+ma!x!+$-ZY%I z4-HG85eQxo#PFsDLbw2Lh)N?6=|m!tzRV34$>dxS4_@X9{^sKUkxQmYVXj;(jS`E~ zm%GPG5zEE06tM)L(E#_Y0uf)Vka_4TyCf8r3Nm4Spj0db-j;?ecu#m5gF*A5W9c*k zo~D!T!|=jW14)56TmXcn({acpF8@7gFL4?FmkVmefV#f^PoI}f+Tqb%-%YLd@ow&6 zk#^Xn+NlOZiXa5S@K7*4AWC_+J4P5<8g0G%zb!}f(chk*s|3Dx+4qL)3avX~x7(+B zUC)IQ<^%kf&vK!W2Ird>dlE}x@h8lQtqJ^v6uR+^3AVfo>y106x6g{s&-NjoO7rLk zLps!8-@Sr@TR5fJqvFw~`5!c+&qigvlzGpU4wLv#!h>$LmmG;dv$blXHhPnxritCo zGoaKC@5;HzIm!Jx%{?DEzG)ThkNWzt$*yg%vu_o8B=585*?>!hdjle^!$847)&9hB zi0>-j930mkXBcJPRo0tT_uHEuX4a|xGcJX+qT?~`=jvGc=BupUI9_#F4@nnT7JWvU zx3=CtY=RBBO`KADO~ir?S?MbDZ=h)UyRY{Ir?c zTdnbNvj}9Opr%*Ypj_FO^S-eKuZb7$1RjphGl(=CdSn{1nEe|o>lgz5OlFj0zuQJ# zgbB&DJTdBaYWq>WPUr9RPwTJn|7A>K-t@>re;vv2x^-*==Wc0bkgG-=q|uZ4A52zv z4$g4)!zZ`B!8(n^92iV)8Fh2n1q@6dpRe9%yuAXSjahH>c(A!N%W_qpq z!(ocXD!V1ZJi5bT@p>Igp41S~;*kUQ^T&_gWa^#15yz<*tTT;%b+FK8er?;Y_D}L~ zV+MYAHm2_9ejRTa8e)YXVNCH?vjoExRJ(XPa^Aj)5MfoIw_e0bdJl<& zGH&A=VhFwaa;84`${JhNh5s<-;GLqT3plia(Y>>Ug=IDo_B+ox?Tz8s zWLUX6^e!BtVf2n(lb%HFSv01T^<5M>dG&eb3*)}8jJ?HTX z{tHP0zg-k;(&yAQsB_~-suwP0C2l;P**D_&ExvrZLO}C1R1OL6iC@-G3p0^fdZ|A@ zU~(?cV)tywIHWWQN@-TVXt_GDm?i0C%z9|nP7o%5%X5QXI9Z)Mjptt8m z+5htJ@F6m>##!Z}I8L{^V;vuPYk&V|ve4Jyq4VT876_){M?gUv9krx}bitmxnKB2kTq)ZaWdyBrR^~ zk1fRK2*3>;*+b!tUhH+gd3zrzwtLRZ+|PBY#Fxd}Lc%Bh2lB4n`*Bqv%YS!!>ZYf` zw))MZ6X$wd&vxPxUG#Ui*0lC!RXcnNq2l(m4i)#zajXhin(2iiMaD2~>}BH%=aYjI zHkK8X?Vi!Q{zLsS((Q;>)EB^|w%I?LBh9W?E`Ie;U7lK`8a^|}uca#&*CZeoufCo# TsPSvo{jGx;Vf1=x!oEKNs9;G? literal 0 HcmV?d00001 diff --git a/icons/icon_google_marker_64x64.png b/icons/icon_google_marker_64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..58687287974cb59f79102175b0ad24b98cde73ff GIT binary patch literal 2014 zcmbVNdr%X19^as*C=XN1tEkr{sK_JPY?1{MNXV0#npi*%QlCF+nL?(@A3J3 z-{0AtNo(HrSrEJc001A=Dn$wQSwRk3JM+pp&8t@DZRGHB% zECoXic{zPpJOIownNqc+R-+c`aWflrW7rO}m0|-xe1gM@>NjB|n1N-PEF$Ju$5|$5 zGKiS#5DiCTm19QJDkp)hb*@R(J2&YC24;d7jCTkr1!jyyL5DfpViP(<%;$QA)Y^Rv zF~R2$a+8Sp!YQpL36$dm1|n>PrRQ*AFh;brh|6VB2$n6+LZS|q#TGiN zL4n!ygvm;pa0}?xh-Toqq=-p*`XU6gRik;S*kYSW6qPc_fm$J$&4J8jcU;fWHZleK zj~lN<+fwta7?gt9@LWPq)gv=>mQ3aDw+*?0lsCe62@_QmG+Tk|bIq8AR4GJE>V|DF z8H6#>9GQa8lgSaj0)~~*Qkg)Zkn&`)d_*QoR48Y4yo$@0DL7Ik%$Fkw?B)uTe5sNn zP2@`D9Ik+`nB}T0HWIbyv01w&%I*x8_nTayoWM{LCsJ`dd$t3Tj5vwgjJOq)%fXfF zOcn!fw}rc_^CDOUMwm8ZhC~84gU{0|G`+$+FE%EFkLnQ?qDK%`W+oqDp$62z;$wOY z)}ttor-zv{e8c~fHi&Wva`(r7^~>xL)r9Wl%kHN(FXsodP(wpd)3NaG4L<;w>!ngi zQyo|D)xt(Ush{MdF27ygpLO|f$j<4RAMkq0{)&8QQ(1*9gyFR~`O}ko{L+{KSHImE z#E>R=4tXAApglXH97vF59g_th#LgR8?gmM0{%1|P;AUb}WpSD?PP^w+jFN381m z4&c!T-MI&ft^wt7t|ei0SKg6E_#2qrt5*UKhbC)J?QUt_hWyU;=*dWR#jWLZF*2C# zyQ6tg!Nu|nkBj#7$*%0MlCpXCx7|Dp@!E$cww@iFn7p&B^o^1~ExYL>j+<=U7xbEL z)3#?xQ3LkQyPt39OsM{w=HrS?Q%m2MYu}DLfHwd&hs(8@SC$l)FOBbm&jbaQZYVbG^1ceTQ4&Bfy0 zz^QCnJnR7!ow?mU=ymzswc7bHl8m0Pn?bk#{E)AndjFVMECn7HFXzm4Ekgto`;Yv7 z_``Zx*A8$Az0NLmOdneOgAI$`_H!h@zbw4qOhkQ0&PJ0~5OcprS9{TeK$b9dX@Dpc*LcwHLbRJJ8}4=s6pYpvH%;Qgx2HD3orIE%X08N7k>gOZ2{ zwqhyj_J@#PH;_#8pbbj+|--^nV%7q+t5ztR|d+sav zaBJ&y)R5~^*oJX53aDCvUk`jo*;X4G2c{n*6<_EM-Sd#(#PO2!-Gvv{KWzuAd`GH$ zz71ZeJMQmHf8uNtbfv8vemy=a`%nNdp7u%HDPH}@NrNm=|G@H9f!@_Az=;DKec5-r ztsi}|Wa^j5fT8if`i@-ol_WFXLUUHrA^GMbVyx(rFk~rbV+1WJxx3%KJY2A{zBKKv zG&O5WC@tt@Z~uV$sq@DpaP5xZUYvG*-p#NlKVfmDAx+{x`r97RIk9s;3*4L5{ZsKj z2{9e1Oz^NuT9Pkxdz3JY_gp~DsAU4lJ>z7=e>X6+omPR*$p<5Wnu*h+bu`z}8_#-y z(=Bi0R}SB>(bJRTJvY8~I@f~(H{KfEI|5B?WnYiwmUf1pU8s9}!TT>oTp{3daXUS~ wv~JW>*R|)%4`^B-Ab+0je+kzg&e>^nfXJ&1EjW2)p8JohQm#=n%X9_*204}jnE(I) literal 0 HcmV?d00001 diff --git a/packages.config b/packages.config new file mode 100644 index 0000000..c1709b5 --- /dev/null +++ b/packages.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file