commit a8243c3e0e164f9222380f5d00524ec8e56f8c91 Author: dexyfex Date: Thu Sep 21 20:33:05 2017 +1000 R26_dev8 - First public commit 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 -- + + + + + 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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/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 + 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/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 + + + + + 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/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 + + + + + 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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/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 + + + + + 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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/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 + 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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/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 0000000..6c7a70d Binary files /dev/null and b/Resources/CW.ico differ diff --git a/Resources/CW16.ico b/Resources/CW16.ico new file mode 100644 index 0000000..e3c8999 Binary files /dev/null and b/Resources/CW16.ico differ diff --git a/Resources/magic.dat b/Resources/magic.dat new file mode 100644 index 0000000..34a0c25 Binary files /dev/null and b/Resources/magic.dat differ diff --git a/SelectFolderForm.Designer.cs b/SelectFolderForm.Designer.cs new file mode 100644 index 0000000..a23879e --- /dev/null +++ b/SelectFolderForm.Designer.cs @@ -0,0 +1,121 @@ +namespace CodeWalker +{ + partial class SelectFolderForm + { + /// + /// 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 + + + + + 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/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 0000000..c9d9284 Binary files /dev/null and b/Shaders/BasicPS.cso differ 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 0000000..e71feed Binary files /dev/null and b/Shaders/BasicVS_Box.cso differ 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 0000000..aff28b3 Binary files /dev/null and b/Shaders/BasicVS_Capsule.cso differ 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 0000000..fafd522 Binary files /dev/null and b/Shaders/BasicVS_Cylinder.cso differ 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 0000000..c047c7e Binary files /dev/null and b/Shaders/BasicVS_PNCCT.cso differ 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 0000000..2956bf7 Binary files /dev/null and b/Shaders/BasicVS_PNCCTT.cso differ diff --git a/Shaders/BasicVS_PNCCTT.hlsl b/Shaders/BasicVS_PNCCTT.hlsl new file mode 100644 index 0000000..6143dfa --- /dev/null +++ b/Shaders/BasicVS_PNCCTT.hlsl @@ -0,0 +1,41 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + 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 = 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_PNCCTTT.cso b/Shaders/BasicVS_PNCCTTT.cso new file mode 100644 index 0000000..189fb7a Binary files /dev/null and b/Shaders/BasicVS_PNCCTTT.cso differ 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 0000000..7e63540 Binary files /dev/null and b/Shaders/BasicVS_PNCCTTTX.cso differ diff --git a/Shaders/BasicVS_PNCCTTTX.hlsl b/Shaders/BasicVS_PNCCTTTX.hlsl new file mode 100644 index 0000000..6db1419 --- /dev/null +++ b/Shaders/BasicVS_PNCCTTTX.hlsl @@ -0,0 +1,43 @@ +#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; + 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 = input.Texcoord2; + 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_PNCCTTX.cso b/Shaders/BasicVS_PNCCTTX.cso new file mode 100644 index 0000000..1d0be06 Binary files /dev/null and b/Shaders/BasicVS_PNCCTTX.cso differ 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 0000000..8f93137 Binary files /dev/null and b/Shaders/BasicVS_PNCCTX.cso differ diff --git a/Shaders/BasicVS_PNCCTX.hlsl b/Shaders/BasicVS_PNCCTX.hlsl new file mode 100644 index 0000000..f89e371 --- /dev/null +++ b/Shaders/BasicVS_PNCCTX.hlsl @@ -0,0 +1,41 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + 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 = 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, 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_PNCT.cso b/Shaders/BasicVS_PNCT.cso new file mode 100644 index 0000000..551cd1a Binary files /dev/null and b/Shaders/BasicVS_PNCT.cso differ 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 0000000..d0d01cf Binary files /dev/null and b/Shaders/BasicVS_PNCTTTX.cso differ diff --git a/Shaders/BasicVS_PNCTTTX.hlsl b/Shaders/BasicVS_PNCTTTX.hlsl new file mode 100644 index 0000000..0d2f905 --- /dev/null +++ b/Shaders/BasicVS_PNCTTTX.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 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.Colour0.xyz, iid); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = NormalTransform(input.Tangent.xyz); + + 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 = input.Texcoord1; + output.Texcoord2 = input.Texcoord2; + output.Colour0 = input.Colour0; + output.Colour1 = float4(0.5,0.5,0.5,1); //input.Colour + 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_PNCTTX.cso b/Shaders/BasicVS_PNCTTX.cso new file mode 100644 index 0000000..bb3ba42 Binary files /dev/null and b/Shaders/BasicVS_PNCTTX.cso differ diff --git a/Shaders/BasicVS_PNCTTX.hlsl b/Shaders/BasicVS_PNCTTX.hlsl new file mode 100644 index 0000000..c654d14 --- /dev/null +++ b/Shaders/BasicVS_PNCTTX.hlsl @@ -0,0 +1,41 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; + float4 Colour0 : COLOR0; + 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.Colour0.xyz, iid); + float4 cpos = ScreenTransform(opos); + float3 bnorm = NormalTransform(input.Normal); + float3 btang = NormalTransform(input.Tangent.xyz); + + 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 = input.Texcoord1; + 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, 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_PNCTX.cso b/Shaders/BasicVS_PNCTX.cso new file mode 100644 index 0000000..7fec2ec Binary files /dev/null and b/Shaders/BasicVS_PNCTX.cso differ diff --git a/Shaders/BasicVS_PNCTX.hlsl b/Shaders/BasicVS_PNCTX.hlsl new file mode 100644 index 0000000..dccd76f --- /dev/null +++ b/Shaders/BasicVS_PNCTX.hlsl @@ -0,0 +1,40 @@ +#include "BasicVS.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, 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 = NormalTransform(input.Tangent.xyz); + + 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, 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_Sphere.cso b/Shaders/BasicVS_Sphere.cso new file mode 100644 index 0000000..9a0faf7 Binary files /dev/null and b/Shaders/BasicVS_Sphere.cso differ diff --git a/Shaders/BasicVS_Sphere.hlsl b/Shaders/BasicVS_Sphere.hlsl new file mode 100644 index 0000000..37aaa8c --- /dev/null +++ b/Shaders/BasicVS_Sphere.hlsl @@ -0,0 +1,56 @@ +#include "BasicVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + //float3 Normal : NORMAL; +}; + +struct RenderableSphere +{ + float3 Center; + float Radius; + float3 Pad0; + uint Colour; +}; + +StructuredBuffer 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 0000000..3d6b742 Binary files /dev/null and b/Shaders/BoundingBoxVS.cso differ 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 0000000..88dd121 Binary files /dev/null and b/Shaders/BoundingSphereVS.cso differ 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 0000000..aa0a9da Binary files /dev/null and b/Shaders/BoundsPS.cso differ diff --git a/Shaders/BoundsPS.hlsl b/Shaders/BoundsPS.hlsl new file mode 100644 index 0000000..5ee01e1 --- /dev/null +++ b/Shaders/BoundsPS.hlsl @@ -0,0 +1,9 @@ +cbuffer PSVars : register(b0) +{ + float4 Colour; +} + +float4 main() : SV_TARGET +{ + return Colour; +} diff --git a/Shaders/CablePS.cso b/Shaders/CablePS.cso new file mode 100644 index 0000000..92f24f7 Binary files /dev/null and b/Shaders/CablePS.cso differ 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 0000000..6077bac Binary files /dev/null and b/Shaders/CableVS.cso differ 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 0000000..bb9cdf7 Binary files /dev/null and b/Shaders/CloudsPS.cso differ diff --git a/Shaders/CloudsPS.hlsl b/Shaders/CloudsPS.hlsl new file mode 100644 index 0000000..d08704b --- /dev/null +++ b/Shaders/CloudsPS.hlsl @@ -0,0 +1,301 @@ +#include "Clouds.hlsli" + + +Texture2D 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 0000000..db4431f Binary files /dev/null and b/Shaders/CloudsVS.cso differ 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 0000000..422b6e9 Binary files /dev/null and b/Shaders/DistantLightsPS.cso differ 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 0000000..df0188b Binary files /dev/null and b/Shaders/DistantLightsVS.cso differ 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 0000000..71e1845 Binary files /dev/null and b/Shaders/MarkerPS.cso differ 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 0000000..d9cc578 Binary files /dev/null and b/Shaders/MarkerVS.cso differ diff --git a/Shaders/MarkerVS.hlsl b/Shaders/MarkerVS.hlsl new file mode 100644 index 0000000..1446add --- /dev/null +++ b/Shaders/MarkerVS.hlsl @@ -0,0 +1,41 @@ +#include "Common.hlsli" + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4x4 ViewInv; + float4 ScreenScale; //xy = 1/wh +} +cbuffer VSMarkerVars : register(b1) +{ + float4 CamRel; + float2 Size; + float2 Offset; +} + + +struct VS_INPUT +{ + float4 Position : POSITION; + float2 Texcoord : TEXCOORD0; +}; +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 * ScreenScale.y, 1) + float3(Offset * ScreenScale.y, 0); + 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.Texcoord; + return output; +} + diff --git a/Shaders/PPBloomFilterBPHCS.cso b/Shaders/PPBloomFilterBPHCS.cso new file mode 100644 index 0000000..70bcf86 Binary files /dev/null and b/Shaders/PPBloomFilterBPHCS.cso differ diff --git a/Shaders/PPBloomFilterBPHCS.hlsl b/Shaders/PPBloomFilterBPHCS.hlsl new file mode 100644 index 0000000..b1e4baa --- /dev/null +++ b/Shaders/PPBloomFilterBPHCS.hlsl @@ -0,0 +1,62 @@ +//-------------------------------------------------------------------------------------- +// File: BrightPassAndHorizFilterCS.hlsl +// +// The CS for bright pass and horizontal blur, used in CS path of +// HDRToneMappingCS11 sample +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +static const float MIDDLE_GRAY = 0.72f; +static const float LUM_WHITE = 1.5f; +static const float BRIGHT_THRESHOLD = 50.0f;//0.8f; + +Texture2D Input : register( t0 ); +StructuredBuffer 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 0000000..c1c7273 Binary files /dev/null and b/Shaders/PPBloomFilterVCS.cso differ diff --git a/Shaders/PPBloomFilterVCS.hlsl b/Shaders/PPBloomFilterVCS.hlsl new file mode 100644 index 0000000..d37ec42 --- /dev/null +++ b/Shaders/PPBloomFilterVCS.hlsl @@ -0,0 +1,72 @@ +//VERTICAL FILTER ONLY +//-------------------------------------------------------------------------------------- +// File: FilterCS.hlsl +// +// The CSs for doing vertical and horizontal blur, used in CS path of +// HDRToneMappingCS11 sample +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//-------------------------------------------------------------------------------------- +StructuredBuffer 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 0000000..052c970 Binary files /dev/null and b/Shaders/PPCopyPixelsPS.cso differ 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 0000000..743bd5c Binary files /dev/null and b/Shaders/PPFinalPassPS.cso differ diff --git a/Shaders/PPFinalPassPS.hlsl b/Shaders/PPFinalPassPS.hlsl new file mode 100644 index 0000000..8614f68 --- /dev/null +++ b/Shaders/PPFinalPassPS.hlsl @@ -0,0 +1,41 @@ + +struct VS_Output +{ + float4 Pos : SV_POSITION; + float2 Tex : TEXCOORD0; +}; + + +Texture2D 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 0000000..d595a82 Binary files /dev/null and b/Shaders/PPFinalPassVS.cso differ 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 0000000..4f217d3 Binary files /dev/null and b/Shaders/PPLumBlendCS.cso differ diff --git a/Shaders/PPLumBlendCS.hlsl b/Shaders/PPLumBlendCS.hlsl new file mode 100644 index 0000000..b7831dd --- /dev/null +++ b/Shaders/PPLumBlendCS.hlsl @@ -0,0 +1,16 @@ +StructuredBuffer 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 0000000..6e0cb4d Binary files /dev/null and b/Shaders/PPReduceTo0DCS.cso differ 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 0000000..274c130 Binary files /dev/null and b/Shaders/PPReduceTo1DCS.cso differ 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 0000000..7af9a97 Binary files /dev/null and b/Shaders/PathBoxPS.cso differ diff --git a/Shaders/PathBoxPS.hlsl b/Shaders/PathBoxPS.hlsl new file mode 100644 index 0000000..98fb1cc --- /dev/null +++ b/Shaders/PathBoxPS.hlsl @@ -0,0 +1,17 @@ + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float4 Colour : COLOR0; + float3 Normal : NORMAL; +}; + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + float4 c = input.Colour; + + return float4(c.rgb, 1.0f); +} + + diff --git a/Shaders/PathBoxVS.cso b/Shaders/PathBoxVS.cso new file mode 100644 index 0000000..17aef3c Binary files /dev/null and b/Shaders/PathBoxVS.cso differ diff --git a/Shaders/PathBoxVS.hlsl b/Shaders/PathBoxVS.hlsl new file mode 100644 index 0000000..7ab7db5 --- /dev/null +++ b/Shaders/PathBoxVS.hlsl @@ -0,0 +1,45 @@ + + + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4 CameraPos; + float4 LightColour; +} + +StructuredBuffer 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 0000000..f1122fb Binary files /dev/null and b/Shaders/PathDynVS.cso differ 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 0000000..c3c9eb4 Binary files /dev/null and b/Shaders/PathPS.cso differ diff --git a/Shaders/PathPS.hlsl b/Shaders/PathPS.hlsl new file mode 100644 index 0000000..cf999cd --- /dev/null +++ b/Shaders/PathPS.hlsl @@ -0,0 +1,16 @@ + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + float4 Colour : COLOR0; +}; + + +float4 main(VS_OUTPUT input) : SV_TARGET +{ + float4 c = input.Colour; + + return float4(c.rgb, saturate(c.a)); +} + + diff --git a/Shaders/PathVS.cso b/Shaders/PathVS.cso new file mode 100644 index 0000000..0508de7 Binary files /dev/null and b/Shaders/PathVS.cso differ 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 0000000..78ab5de Binary files /dev/null and b/Shaders/ShadowPS.cso differ 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 0000000..b1a5314 Binary files /dev/null and b/Shaders/ShadowVS.cso differ diff --git a/Shaders/ShadowVS.hlsl b/Shaders/ShadowVS.hlsl new file mode 100644 index 0000000..ae63fb3 --- /dev/null +++ b/Shaders/ShadowVS.hlsl @@ -0,0 +1,93 @@ +#include "Common.hlsli" +#include "Quaternion.hlsli" + + +cbuffer VSSceneVars : register(b0) +{ + float4x4 ViewProj; + float4 WindVector; +} +cbuffer VSEntityVars : register(b1) +{ + float4 CamRel; + float4 Orientation; + uint HasSkeleton; + uint HasTransforms; + uint TintPaletteIndex; + uint Pad1; + float3 Scale; + uint Pad2; +} +cbuffer VSModelVars : register(b2) +{ + float4x4 Transform; +} +cbuffer GeomVars : register(b3) +{ + uint EnableTexture; + uint EnableTint; + uint IsDecal; + uint EnableWind; + float4 WindOverrideParams; +} + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 Texcoord : TEXCOORD0; + float4 Colour : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + //float3 Normal : NORMAL; + float2 Texcoord : TEXCOORD0; + //float4 Colour : COLOR0; + //float4 Tint : COLOR1; +}; + +//Texture2D 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 0000000..6bdfcaa Binary files /dev/null and b/Shaders/SkyMoonPS.cso differ 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 0000000..ec98e70 Binary files /dev/null and b/Shaders/SkyMoonVS.cso differ 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 0000000..a6c9029 Binary files /dev/null and b/Shaders/SkySunPS.cso differ 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 0000000..7f5b4bf Binary files /dev/null and b/Shaders/SkySunVS.cso differ 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 0000000..514108f Binary files /dev/null and b/Shaders/SkydomePS.cso differ 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 0000000..779704b Binary files /dev/null and b/Shaders/SkydomeVS.cso differ diff --git a/Shaders/SkydomeVS.hlsl b/Shaders/SkydomeVS.hlsl new file mode 100644 index 0000000..e5757a5 --- /dev/null +++ b/Shaders/SkydomeVS.hlsl @@ -0,0 +1,448 @@ +#include "Common.hlsli" +#include "Quaternion.hlsli" +#include "Skydome.hlsli" + +cbuffer VSSceneVars : register(b1) +{ + float4x4 ViewProj; + float4x4 ViewInv; +} +cbuffer VSEntityVars : register(b2) +{ + float4 CamRel; + float4 Orientation; +} +cbuffer VSModelVars : register(b3) +{ + float4x4 Transform; +} + + +struct VS_INPUT +{ + float4 Position : POSITION; + float2 Texcoord0 : TEXCOORD0; + float2 Texcoord1 : TEXCOORD1; +}; +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 +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 ipos = input.Position.xyz * 10.0; + float3 bpos = mulvq(ipos, Orientation); + float3 opos = CamRel.xyz + bpos; + float4 pos = float4(opos, 1); + float4 cpos = mul(pos, ViewProj); + cpos.z = DepthFunc(cpos.zw); + output.Position = cpos; + + float2 v1 = input.Texcoord0; + float2 v2 = input.Texcoord1; + + float4 r0, r1, r2, r3, r4, r5; + + r0.xy = v1 * 2.0 - 1.0; + r0.x = dot(r0.xy, r0.xy); + r0.x = 1 - r0.x; + r0.y = cloudConstants2.y * 0.1; + r1.xyz = float3(-ViewInv[3].xy, -horizonLevel); //mov r1.xy, -gViewInverse[3].xyxx + //mov r1.z, -horizonLevel + r2.xyz = opos;// float3(opos.xy, -opos.z); //(mad r2.xyz, v0.wwww, gWorld[3].xyzx, r2.xyzx) + r1.xyz = r1.xyz + r2.xyz; //add r1.xyz, r1.xyzx, r2.xyzx + r0.z = 1.0 / length(r1.xyz); // sqrt(r0.z); r0.z = dot(r1.xyz, r1.xyz); //dp3 r0.z, r1.xyzx, r1.xyzx //rsq r0.z, r0.z + r1.yw = -r1.xy*r0.z + sunDirection.xy; //mad r1.yw, -r1.xxxy, r0.zzzz, sunDirection.xxxy + r0.zw = r1.xz*r0.z; //mul r0.zw, r0.zzzz, r1.xxxz + r1.xy = r1.yw*r0.y; //mul r1.xy, r0.yyyy, r1.ywyy + output.o1.zw = -r1.xy*r0.x + v1.xy; //mad o1.zw, -r1.xxxy, r0.xxxx, v1.xxxy + output.o1.xy = v1.xy; //mov o1.xy, v1.xyxx + + //r0.x = dot(r2.xyz, r2.xyz); //dp3 r0.x, r2.xyzx, r2.xyzx + r0.x = 1.0 / length(r2.xyz); // sqrt(r0.x); //rsq r0.x, r0.x + r0.x = saturate(r0.x * -r2.z + 0.05); //************ invert+FUDGE //mul_sat r0.x, r0.x, r2.z + r0.x = r0.x * 5.0; //mul r0.x, r0.x, l(5.000000) + output.o2.w = min(r0.x, 1); //min o2.w, r0.x, l(1.000000) + output.o2.xyz = r2.xyz; //mov o2.xyz, r2.xyzx + + + r1.xyz = r2.xyz - ViewInv[3].xyz; //add r1.xyz, r2.xyzx, -gViewInverse[3].xyzx + r0.x = abs(r0.w) - zenithConstants.x; //add r0.x, |r0.w|, -zenithConstants.x + r0.y = 1.0 - zenithConstants.x; //add r0.y, -zenithConstants.x, l(1.000000) + r0.x = saturate(r0.x / r0.y); //div_sat r0.x, r0.x, r0.y + r0.x = saturate(r0.x / zenithConstants.w); //div_sat r0.x, r0.x, zenithConstants.w + r0.y = r0.z*-0.5 + 0.5; //mad r0.y, r0.z, l(-0.500000), l(0.500000) + r0.y = sqrt(r0.y); //sqrt r0.y, r0.y + r0.z = r0.y - azimuthTransitionPosition; //add r0.z, r0.y, -azimuthTransitionPosition + r1.w = 1.0 - azimuthTransitionPosition; //add r1.w, -azimuthTransitionPosition, l(1.000000) + r0.z = r0.z / r1.w; //div r0.z, r0.z, r1.w + r2.xyz = azimuthWestColor.xyz - azimuthTransitionColor.xyz; //add r2.xyz, azimuthWestColor.xyzx, -azimuthTransitionColor.xyzx + r2.xyz = r2.xyz*r0.z + azimuthTransitionColor.xyz; //mad r2.xyz, r0.zzzz, r2.xyzx, azimuthTransitionColor.xyzx + r0.z = r0.y / azimuthTransitionPosition; //div r0.z, r0.y, azimuthTransitionPosition + r3.xyz = azimuthTransitionColor.xyz - azimuthEastColor.xyz; //add r3.xyz, -azimuthEastColor.xyzx, azimuthTransitionColor.xyzx + r3.xyz = r3.xyz*r0.z + azimuthEastColor.xyz; //mad r3.xyz, r0.zzzz, r3.xyzx, azimuthEastColor.xyzx + r0.z = r0.y < azimuthTransitionPosition; //lt r0.z, r0.y, azimuthTransitionPosition + r2.xyz = r0.z ? r3.xyz : r2.xyz; //movc r2.xyz, r0.zzzz, r3.xyzx, r2.xyzx + r3.xyz = zenithTransitionColor.xyz - r2.xyz; //add r3.xyz, -r2.xyzx, zenithTransitionColor.xyzx + r0.z = zenithConstants.z - zenithConstants.y; //add r0.z, -zenithConstants.y, zenithConstants.z + r0.y = r0.y*r0.z + zenithConstants.y; //mad r0.y, r0.y, r0.z, zenithConstants.y + r4.xyz = r3.xyz*r0.y + r2.xyz; //mad r4.xyz, r0.yyyy, r3.xyzx, r2.xyzx + r3.xyz = r3.xyz*r0.y; //mul r3.xyz, r3.xyzx, r0.yyyy + r5.xyz = zenithColor.xyz - r4.xyz; //add r5.xyz, -r4.xyzx, zenithColor.xyzx + r0.xyz = r5.xyz*r0.x + r4.xyz; //mad r0.xyz, r0.xxxx, r5.xyzx, r4.xyzx + r1.w = abs(r0.w) / zenithConstants.x; //div r1.w, |r0.w|, zenithConstants.x + r0.w = abs(r0.w) < zenithConstants.x; //lt r0.w, |r0.w|, zenithConstants.x + r2.xyz = r3.xyz*r1.w + r2.xyz; //mad r2.xyz, r1.wwww, r3.xyzx, r2.xyzx + r0.xyz = r0.w ? r2.xyz : r0.xyz; //movc r0.xyz, r0.wwww, r2.xyzx, r0.xyzx + output.o3.xyz = r0.xyz*hdrIntensity; //mul o3.xyz, r0.xyzx, hdrIntensity.xxxx + output.o3.w = 0; //mov o3.w, l(0) + + r0.xy = v1.xy - 0.5; //add r0.xy, v1.xyxx, l(-0.500000, -0.500000, 0.000000, 0.000000) + r2.xyzw = r0.xyyx + speedConstants.zzyy; //add r2.xyzw, r0.xyyx, speedConstants.zzyy + r0.xy = r0.xy + speedConstants.x; //add r0.xy, r0.xyxx, speedConstants.xxxx + output.o5.zw = r0.xy * smallCloudConstants.x; //mul o5.zw, r0.xxxy, smallCloudConstants.xxxx + + output.o4.xyzw = r2.xyzw * cloudDetailConstants.yyww; //mul o4.xyzw, r2.xyzw, cloudDetailConstants.yyww + + output.o5.xy = v2.xy * 64.0; //mul o5.xy, v2.xyxx, l(64.000000, 64.000000, 0.000000, 0.000000) + + output.o6.xy = v2.xy * 12.0; //mul o6.xy, v2.xyxx, l(12.000000, 12.000000, 0.000000, 0.000000) + + r0.x = dot(r1.xyz, r1.xyz); //dp3 r0.x, r1.xyzx, r1.xyzx + r0.y = sqrt(r0.x); //sqrt r0.y, r0.x + r0.x = 1.0 / sqrt(r0.x); //rsq r0.x, r0.x + r0.xzw = r1.xyz*r0.x; //mul r0.xzw, r0.xxxx, r1.xxyz + //r1.x = r0.y - globalFogParams[0].x; //add r1.x, r0.y, -globalFogParams[0].x + //max r1.x, r1.x, l(0.000000) + //div r0.y, r1.x, r0.y + //mul r0.y, r0.y, r1.z + //mul r1.y, r0.y, globalFogParams[2].z + //lt r0.y, l(0.010000), |r0.y| + //mul r1.z, r1.y, l(-1.442695) + //exp r1.z, r1.z + //add r1.z, -r1.z, l(1.000000) + //div r1.y, r1.z, r1.y + //movc r0.y, r0.y, r1.y, l(1.000000) + //mul r1.y, r1.x, globalFogParams[1].w + //mul r1.x, r1.x, -globalFogParams[1].z + //mul r1.x, r1.x, l(1.442695) + //exp r1.x, r1.x + //add r1.x, -r1.x, l(1.000000) + //mul r0.y, r0.y, r1.y + //min r0.y, r0.y, l(1.000000) + //mul r0.y, r0.y, l(1.442695) + //exp r0.y, r0.y + //min r0.y, r0.y, l(1.000000) + //add r0.y, -r0.y, l(1.000000) + //mul_sat o7.w, r0.y, globalFogParams[2].y + + //dp3_sat r0.y, r0.xzwx, globalFogParams[3].xyzx + //dp3_sat r0.x, r0.xzwx, globalFogParams[4].xyzx + //log r0.x, r0.x + //mul r0.x, r0.x, globalFogParams[4].w + //exp r0.x, r0.x + //log r0.y, r0.y + //mul r0.y, r0.y, globalFogParams[3].w + //exp r0.y, r0.y + //add r1.yzw, -globalFogColorE.xxyz, globalFogColorMoon.xxyz + //mad r0.xzw, r0.xxxx, r1.yyzw, globalFogColorE.xxyz + //add r1.yzw, -r0.xxzw, globalFogColor.xxyz + //mad r0.xyz, r0.yyyy, r1.yzwy, r0.xzwx + //add r0.xyz, r0.xyzx, -globalFogColorN.xyzx + //mad o7.xyz, r1.xxxx, r0.xyzx, globalFogColorN.xyzx + + + + output.o7 = float4(input.Texcoord1, 0, 0); + return output; +} + + + + +/* + +sky normal all VS: + +v1 = Texcoord0 +v2 = Texcoord1 + + +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 +mad o0.xyzw, v0.wwww, gWorldViewProj[3].xyzw, r0.xyzw + +mad r0.xy, v1.xyxx, l(2.000000, 2.000000, 0.000000, 0.000000), l(-1.000000, -1.000000, 0.000000, 0.000000) +dp2 r0.x, r0.xyxx, r0.xyxx +add r0.x, -r0.x, l(1.000000) +mul r0.y, cloudConstants2.y, l(0.100000) +mov r1.xy, -gViewInverse[3].xyxx +mov r1.z, -horizonLevel +mul r2.xyz, v0.yyyy, gWorld[1].xyzx +mad r2.xyz, v0.xxxx, gWorld[0].xyzx, r2.xyzx +mad r2.xyz, v0.zzzz, gWorld[2].xyzx, r2.xyzx +mad r2.xyz, v0.wwww, gWorld[3].xyzx, r2.xyzx +add r1.xyz, r1.xyzx, r2.xyzx +dp3 r0.z, r1.xyzx, r1.xyzx +rsq r0.z, r0.z +mad r1.yw, -r1.xxxy, r0.zzzz, sunDirection.xxxy +mul r0.zw, r0.zzzz, r1.xxxz +mul r1.xy, r0.yyyy, r1.ywyy +mad o1.zw, -r1.xxxy, r0.xxxx, v1.xxxy +mov o1.xy, v1.xyxx + + +dp3 r0.x, r2.xyzx, r2.xyzx +rsq r0.x, r0.x +mul_sat r0.x, r0.x, r2.z +mul r0.x, r0.x, l(5.000000) +min o2.w, r0.x, l(1.000000) +mov o2.xyz, r2.xyzx + +add r1.xyz, r2.xyzx, -gViewInverse[3].xyzx +add r0.x, |r0.w|, -zenithConstants.x +add r0.y, -zenithConstants.x, l(1.000000) +div_sat r0.x, r0.x, r0.y +div_sat r0.x, r0.x, zenithConstants.w +mad r0.y, r0.z, l(-0.500000), l(0.500000) +sqrt r0.y, r0.y +add r0.z, r0.y, -azimuthTransitionPosition +add r1.w, -azimuthTransitionPosition, l(1.000000) +div r0.z, r0.z, r1.w +add r2.xyz, azimuthWestColor.xyzx, -azimuthTransitionColor.xyzx +mad r2.xyz, r0.zzzz, r2.xyzx, azimuthTransitionColor.xyzx +div r0.z, r0.y, azimuthTransitionPosition +add r3.xyz, -azimuthEastColor.xyzx, azimuthTransitionColor.xyzx +mad r3.xyz, r0.zzzz, r3.xyzx, azimuthEastColor.xyzx +lt r0.z, r0.y, azimuthTransitionPosition +movc r2.xyz, r0.zzzz, r3.xyzx, r2.xyzx +add r3.xyz, -r2.xyzx, zenithTransitionColor.xyzx +add r0.z, -zenithConstants.y, zenithConstants.z +mad r0.y, r0.y, r0.z, zenithConstants.y +mad r4.xyz, r0.yyyy, r3.xyzx, r2.xyzx +mul r3.xyz, r3.xyzx, r0.yyyy +add r5.xyz, -r4.xyzx, zenithColor.xyzx +mad r0.xyz, r0.xxxx, r5.xyzx, r4.xyzx +div r1.w, |r0.w|, zenithConstants.x +lt r0.w, |r0.w|, zenithConstants.x +mad r2.xyz, r1.wwww, r3.xyzx, r2.xyzx +movc r0.xyz, r0.wwww, r2.xyzx, r0.xyzx +mul o3.xyz, r0.xyzx, hdrIntensity.xxxx +mov o3.w, l(0) + +add r0.xy, v1.xyxx, l(-0.500000, -0.500000, 0.000000, 0.000000) +add r2.xyzw, r0.xyyx, speedConstants.zzyy +add r0.xy, r0.xyxx, speedConstants.xxxx +mul o5.zw, r0.xxxy, smallCloudConstants.xxxx + +mul o4.xyzw, r2.xyzw, cloudDetailConstants.yyww + +mul o5.xy, v2.xyxx, l(64.000000, 64.000000, 0.000000, 0.000000) + +mul o6.xy, v2.xyxx, l(12.000000, 12.000000, 0.000000, 0.000000) + +dp3 r0.x, r1.xyzx, r1.xyzx +sqrt r0.y, r0.x +rsq r0.x, r0.x +mul r0.xzw, r0.xxxx, r1.xxyz +add r1.x, r0.y, -globalFogParams[0].x +max r1.x, r1.x, l(0.000000) +div r0.y, r1.x, r0.y +mul r0.y, r0.y, r1.z +mul r1.y, r0.y, globalFogParams[2].z +lt r0.y, l(0.010000), |r0.y| +mul r1.z, r1.y, l(-1.442695) +exp r1.z, r1.z +add r1.z, -r1.z, l(1.000000) +div r1.y, r1.z, r1.y +movc r0.y, r0.y, r1.y, l(1.000000) +mul r1.y, r1.x, globalFogParams[1].w +mul r1.x, r1.x, -globalFogParams[1].z +mul r1.x, r1.x, l(1.442695) +exp r1.x, r1.x +add r1.x, -r1.x, l(1.000000) +mul r0.y, r0.y, r1.y +min r0.y, r0.y, l(1.000000) +mul r0.y, r0.y, l(1.442695) +exp r0.y, r0.y +min r0.y, r0.y, l(1.000000) +add r0.y, -r0.y, l(1.000000) +mul_sat o7.w, r0.y, globalFogParams[2].y + +dp3_sat r0.y, r0.xzwx, globalFogParams[3].xyzx +dp3_sat r0.x, r0.xzwx, globalFogParams[4].xyzx +log r0.x, r0.x +mul r0.x, r0.x, globalFogParams[4].w +exp r0.x, r0.x +log r0.y, r0.y +mul r0.y, r0.y, globalFogParams[3].w +exp r0.y, r0.y +add r1.yzw, -globalFogColorE.xxyz, globalFogColorMoon.xxyz +mad r0.xzw, r0.xxxx, r1.yyzw, globalFogColorE.xxyz +add r1.yzw, -r0.xxzw, globalFogColor.xxyz +mad r0.xyz, r0.yyyy, r1.yzwy, r0.xzwx +add r0.xyz, r0.xyzx, -globalFogColorN.xyzx +mad o7.xyz, r1.xxxx, r0.xyzx, globalFogColorN.xyzx + +ret +// Approximately 107 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 +// 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 +// +// } +// +// 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 sky_system_locals +// { +// +// float3 azimuthEastColor; // Offset: 0 Size: 12 +// float3 azimuthWestColor; // Offset: 16 Size: 12 +// float3 azimuthTransitionColor; // Offset: 32 Size: 12 +// float azimuthTransitionPosition; // Offset: 44 Size: 4 +// float3 zenithColor; // Offset: 48 Size: 12 +// float3 zenithTransitionColor; // Offset: 64 Size: 12 +// float4 zenithConstants; // Offset: 80 Size: 16 +// float4 skyPlaneColor; // Offset: 96 Size: 16 [unused] +// float4 skyPlaneParams; // Offset: 112 Size: 16 [unused] +// float hdrIntensity; // Offset: 128 Size: 4 +// float3 sunColor; // Offset: 132 Size: 12 [unused] +// float3 sunColorHdr; // Offset: 144 Size: 12 [unused] +// float3 sunDiscColorHdr; // Offset: 160 Size: 12 [unused] +// float4 sunConstants; // Offset: 176 Size: 16 [unused] +// float3 sunDirection; // Offset: 192 Size: 12 +// float3 sunPosition; // Offset: 208 Size: 12 [unused] +// float3 cloudBaseMinusMidColour; // Offset: 224 Size: 12 [unused] +// float3 cloudMidColour; // Offset: 240 Size: 12 [unused] +// float3 cloudShadowMinusBaseColourTimesShadowStrength;// Offset: 256 Size: 12 [unused] +// float4 cloudDetailConstants; // Offset: 272 Size: 16 +// float4 cloudConstants1; // Offset: 288 Size: 16 [unused] +// float4 cloudConstants2; // Offset: 304 Size: 16 +// float4 smallCloudConstants; // Offset: 320 Size: 16 +// float3 smallCloudColorHdr; // Offset: 336 Size: 12 [unused] +// float4 effectsConstants; // Offset: 352 Size: 16 [unused] +// float horizonLevel; // Offset: 368 Size: 4 +// float3 speedConstants; // Offset: 372 Size: 12 +// float starfieldIntensity; // Offset: 384 Size: 4 [unused] +// float3 moonDirection; // Offset: 388 Size: 12 [unused] +// float3 moonPosition; // Offset: 400 Size: 12 [unused] +// float moonIntensity; // Offset: 412 Size: 4 [unused] +// float3 lunarCycle; // Offset: 416 Size: 12 [unused] +// float3 moonColor; // Offset: 432 Size: 12 [unused] +// 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 +// ------------------------------ ---------- ------- ----------- -------------- ------ +// rage_matrices cbuffer NA NA cb1 1 +// lighting_globals cbuffer NA NA cb3 1 +// sky_system_locals cbuffer NA NA cb12 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyzw 0 NONE float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 xy 2 NONE float xy +// SV_InstanceID 0 x 3 INSTID uint +// +// +// 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 +// TEXCOORD 5 xy 6 NONE float xy +// TEXCOORD 6 xyzw 7 NONE float xyzw +// +vs_4_0 +dcl_constantbuffer CB1[16], immediateIndexed +dcl_constantbuffer CB3[59], immediateIndexed +dcl_constantbuffer CB12[24], immediateIndexed +dcl_input v0.xyzw +dcl_input v1.xy +dcl_input v2.xy +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_output o6.xy +dcl_output o7.xyzw +dcl_temps 6 + +*/ \ No newline at end of file diff --git a/Shaders/TerrainPS.cso b/Shaders/TerrainPS.cso new file mode 100644 index 0000000..bcc1d67 Binary files /dev/null and b/Shaders/TerrainPS.cso differ 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 0000000..e20d728 Binary files /dev/null and b/Shaders/TerrainVS_PNCCT.cso differ diff --git a/Shaders/TerrainVS_PNCCT.hlsl b/Shaders/TerrainVS_PNCCT.hlsl new file mode 100644 index 0000000..af7ee7b --- /dev/null +++ b/Shaders/TerrainVS_PNCCT.hlsl @@ -0,0 +1,39 @@ +#include "TerrainVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float4 Colour0 : COLOR0; + float4 Colour1 : COLOR1; + float2 Texcoord : TEXCOORD0; +}; + +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.Texcoord0 = input.Texcoord; + 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, 0); + output.Bitangent = float4(cross(btang, bnorm), 0); + return output; +} diff --git a/Shaders/TerrainVS_PNCCTT.cso b/Shaders/TerrainVS_PNCCTT.cso new file mode 100644 index 0000000..5bcc67b Binary files /dev/null and b/Shaders/TerrainVS_PNCCTT.cso differ 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 0000000..3601f02 Binary files /dev/null and b/Shaders/TerrainVS_PNCCTTTX.cso differ 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 0000000..fe73154 Binary files /dev/null and b/Shaders/TerrainVS_PNCCTTX.cso differ 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 0000000..df8b4bd Binary files /dev/null and b/Shaders/TerrainVS_PNCCTX.cso differ diff --git a/Shaders/TerrainVS_PNCCTX.hlsl b/Shaders/TerrainVS_PNCCTX.hlsl new file mode 100644 index 0000000..6681019 --- /dev/null +++ b/Shaders/TerrainVS_PNCCTX.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; + 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 = 0.5; + 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_PNCTTTX.cso b/Shaders/TerrainVS_PNCTTTX.cso new file mode 100644 index 0000000..fe03555 Binary files /dev/null and b/Shaders/TerrainVS_PNCTTTX.cso differ 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 0000000..0c2ff0c Binary files /dev/null and b/Shaders/TerrainVS_PNCTTX.cso differ 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 0000000..d8645ac Binary files /dev/null and b/Shaders/TreesLodPS.cso differ 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 0000000..7097374 Binary files /dev/null and b/Shaders/TreesLodVS.cso differ 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 0000000..d287c4c Binary files /dev/null and b/Shaders/WaterPS.cso differ diff --git a/Shaders/WaterPS.hlsl b/Shaders/WaterPS.hlsl new file mode 100644 index 0000000..1a3ac40 --- /dev/null +++ b/Shaders/WaterPS.hlsl @@ -0,0 +1,800 @@ +#include "Shadowmap.hlsli" + +Texture2D 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 0000000..e9aecdd Binary files /dev/null and b/Shaders/WaterVS_PCT.cso differ diff --git a/Shaders/WaterVS_PCT.hlsl b/Shaders/WaterVS_PCT.hlsl new file mode 100644 index 0000000..e78fbc3 --- /dev/null +++ b/Shaders/WaterVS_PCT.hlsl @@ -0,0 +1,33 @@ +#include "WaterVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + 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(float3(0,0,1)); + float3 btang = float3(1,0,0);// 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_PNCT.cso b/Shaders/WaterVS_PNCT.cso new file mode 100644 index 0000000..de99c26 Binary files /dev/null and b/Shaders/WaterVS_PNCT.cso differ 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 0000000..8bb643c Binary files /dev/null and b/Shaders/WaterVS_PNCTX.cso differ 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 0000000..32f23ac Binary files /dev/null and b/Shaders/WaterVS_PT.cso differ diff --git a/Shaders/WaterVS_PT.hlsl b/Shaders/WaterVS_PT.hlsl new file mode 100644 index 0000000..94e6a7a --- /dev/null +++ b/Shaders/WaterVS_PT.hlsl @@ -0,0 +1,32 @@ +#include "WaterVS.hlsli" + +struct VS_INPUT +{ + float4 Position : POSITION; + float2 Texcoord0 : TEXCOORD0; +}; + + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT output; + float3 opos = ModelTransform(input.Position.xyz); + float4 cpos = ScreenTransform(opos); + float3 bnorm = float3(0, 0, 1);// NormalTransform(float3(0, 0, 1)); + float3 btang = float3(0,1,0);// 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 = 0.1; + output.Tangent = float4(btang, 1); + output.Bitangent = float4(cross(btang, bnorm), 0); + output.Flow = GetWaterFlow(input.Texcoord0, 1); + return output; +} + diff --git a/Shaders/WidgetPS.cso b/Shaders/WidgetPS.cso new file mode 100644 index 0000000..be37652 Binary files /dev/null and b/Shaders/WidgetPS.cso differ 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 0000000..b2ffd27 Binary files /dev/null and b/Shaders/WidgetVS.cso differ 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 0000000..d4472c9 Binary files /dev/null and b/Toolbar/cammode_2D.png differ diff --git a/Toolbar/cammode_3D.png b/Toolbar/cammode_3D.png new file mode 100644 index 0000000..615ea54 Binary files /dev/null and b/Toolbar/cammode_3D.png differ diff --git a/Toolbar/cammode_Or.png b/Toolbar/cammode_Or.png new file mode 100644 index 0000000..0a80253 Binary files /dev/null and b/Toolbar/cammode_Or.png differ diff --git a/Utils/Cache.cs b/Utils/Cache.cs new file mode 100644 index 0000000..3b8cd45 --- /dev/null +++ b/Utils/Cache.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CodeWalker +{ + public class Cache 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 + + + + + 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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/icons/icon_glokon_debug_32x32.png b/icons/icon_glokon_debug_32x32.png new file mode 100644 index 0000000..97de457 Binary files /dev/null and b/icons/icon_glokon_debug_32x32.png differ diff --git a/icons/icon_glokon_normal_32x32.png b/icons/icon_glokon_normal_32x32.png new file mode 100644 index 0000000..3c65531 Binary files /dev/null and b/icons/icon_glokon_normal_32x32.png differ diff --git a/icons/icon_google_marker_64x64.png b/icons/icon_google_marker_64x64.png new file mode 100644 index 0000000..5868728 Binary files /dev/null and b/icons/icon_google_marker_64x64.png differ 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