mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2026-05-17 00:54:57 +08:00
R26_dev8 - First public commit
This commit is contained in:
@@ -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<DrawableModel> 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 = "<Couldn't find texture!>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user