Ynd research V2 by fish-cfx

Some refactoring and adjustments by dexy
This commit is contained in:
dexy 2023-09-04 20:48:50 +10:00
parent d2293660b4
commit b55458b113
11 changed files with 2098 additions and 884 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.World
{
@ -493,7 +492,13 @@ namespace CodeWalker.World
}
//string str = sb.ToString();
}
public void PatchYndFile(YndFile ynd)
{
//ideally we should be able to revert to the vanilla ynd's after closing the project window,
//but codewalker can always just be restarted, so who cares really
NodeGrid.UpdateYnd(ynd);
}
private void AddRpfYnds(RpfFile rpffile, Dictionary<uint, RpfFileEntry> yndentries)
@ -565,8 +570,9 @@ namespace CodeWalker.World
ynd.Links = tlinks.ToArray();
}
public void BuildYndVerts(YndFile ynd, List<EditorVertex> tverts = null)
public void BuildYndVerts(YndFile ynd, YndNode[] selectedNodes, List<EditorVertex> tverts = null)
{
var laneColour = (uint) new Color4(0f, 0f, 1f, 1f).ToRgba();
var ynodes = ynd.Nodes;
if (ynodes == null) return;
@ -589,7 +595,18 @@ namespace CodeWalker.World
for (int l = 0; l < node.Links.Length; l++)
{
YndLink yl = node.Links[l];
var laneDir = yl.GetDirection();
var laneDirCross = Vector3.Cross(laneDir, Vector3.UnitZ);
var laneWidth = yl.GetLaneWidth();
var laneHalfWidth = laneWidth / 2;
var offset = yl.IsTwoWay()
? yl.LaneOffset * laneWidth - laneHalfWidth
: yl.LaneOffset - yl.LaneCountForward * laneWidth / 2f + laneHalfWidth;
var iOffset = yl.IsTwoWay() ? 1 : 0;
var tnode = yl.Node2;
if (tnode == null) continue; //invalid links could hit here
var tvert = new EditorVertex();
tvert.Position = tnode.Position;
@ -597,12 +614,42 @@ namespace CodeWalker.World
tverts.Add(nvert);
tverts.Add(tvert);
// Add lane display
for (int j = iOffset; j < yl.LaneCountForward + iOffset; j++)
{
var vertOffset = laneDirCross * (offset + laneWidth * j);
vertOffset.Z = 0.1f;
var lvert1 = new EditorVertex
{
Position = nvert.Position + vertOffset,
Colour = laneColour
};
var lvert2 = new EditorVertex
{
Position = tvert.Position + vertOffset,
Colour = laneColour
};
tverts.Add(lvert1);
tverts.Add(lvert2);
// Arrow
var apos = lvert1.Position + laneDir * yl.LinkLength / 2;
const float asize = 0.5f;
const float negasize = asize * -1f;
tverts.Add(new EditorVertex(){ Position = apos, Colour = laneColour});
tverts.Add(new EditorVertex() { Position = apos + laneDir * negasize + laneDirCross * asize, Colour = laneColour });
tverts.Add(new EditorVertex() { Position = apos, Colour = laneColour });
tverts.Add(new EditorVertex() { Position = apos + laneDir * negasize + laneDirCross * negasize, Colour = laneColour });
}
}
}
ynd.LinkedVerts = tverts.ToArray();
ynd.UpdateTriangleVertices();
ynd.UpdateTriangleVertices(selectedNodes);
}
public void BuildYndJuncs(YndFile ynd)
{
@ -646,10 +693,65 @@ namespace CodeWalker.World
BuildYndJuncs(ynd);
BuildYndVerts(ynd, tverts);
BuildYndVerts(ynd, null, tverts);
}
public YndFile[] GetYndFilesThatDependOnYndFile(YndFile file)
{
return AllYnds.Values.Where(y => y.Links.Any(l => l.Node2.AreaID == file.AreaID)).ToArray();
}
public void MoveYndArea(YndFile ynd, int desiredX, int desiredY)
{
var xDir = Math.Min(1, Math.Max(-1, desiredX - ynd.CellX));
var yDir = Math.Min(1, Math.Max(-1, desiredY - ynd.CellY));
var x = desiredX;
var y = desiredY;
if (xDir != 0)
{
while (x >= 0 && x <= 31)
{
if (NodeGrid.Cells[x, y].Ynd == null)
{
break;
}
x += xDir;
}
}
if (yDir != 0)
{
while (y >= 0 && y <= 31)
{
if (NodeGrid.Cells[x, y].Ynd == null)
{
break;
}
y += yDir;
}
}
ynd.CellX = x;
ynd.CellY = y;
var areaId = y * 32 + x;
ynd.AreaID = areaId;
ynd.Name = $"nodes{areaId}";
NodeGrid.UpdateYnd(ynd);
}
public void RecalculateAllYndIndices()
{
foreach (var yndFile in AllYnds.Values)
{
yndFile.RecalculateNodeIndices();
}
}
private void InitNavGrid()
{
@ -993,6 +1095,11 @@ namespace CodeWalker.World
for (int i = 0; i < items.Count; i++)
{
var item = items[i];
if (item == null)
{
continue;
}
var hash = item.Name;
if (!ymaps.ContainsKey(hash))
{
@ -1120,6 +1227,10 @@ namespace CodeWalker.World
for (int i = 0; i < mapdatalist.Count; i++)
{
var mapdata = mapdatalist[i];
if (mapdata == null)
{
continue;
}
if ((mapdata.ContentFlags & 1) == 0)
{ continue; } //only test HD ymaps
@ -2020,6 +2131,19 @@ namespace CodeWalker.World
return null;
}
public SpaceNodeGridCell GetCellForPosition(Vector3 position)
{
var x = (int)((position.X - CornerX) / CellSize);
var y = (int)((position.Y - CornerY) / CellSize);
if ((x >= 0) && (x < CellCountX) && (y >= 0) && (y < CellCountY))
{
return Cells[x, y];
}
return null;
}
public YndNode GetYndNode(ushort areaid, ushort nodeid)
{
@ -2031,6 +2155,23 @@ namespace CodeWalker.World
return cell.Ynd.Nodes[nodeid];
}
public void UpdateYnd(YndFile ynd)
{
for (int xx = 0; xx < Cells.GetLength(0); xx++)
{
for (int yy = 0; yy < Cells.GetLength(1); yy++)
{
if (Cells[xx, yy].Ynd == ynd)
{
Cells[xx, yy].Ynd = null;
}
}
}
var x = ynd.CellX;
var y = ynd.CellY;
Cells[x, y].Ynd = ynd;
}
}
public class SpaceNodeGridCell
{

View File

@ -42,6 +42,7 @@ namespace CodeWalker.Project.Panels
private void LoadItems()
{
MultiItem = new MapSelection();
MultiItem.WorldForm = ProjectForm.WorldForm;
MultiItem.Clear();
MultiItem.SetMultipleSelectionItems(Items);

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,7 @@ namespace CodeWalker.Project.Panels
private void UpdateFormTitle()
{
var sn = CurrentPathNode.StreetName.Hash == 0 ? "Path node" : CurrentPathNode.StreetName.ToString();
var sn = CurrentPathNode.StreetName.Hash == 0 ? "Path node" : CurrentPathNode?.StreetName.ToString() ?? string.Empty;
Text = sn + " " + CurrentPathNode.NodeID.ToString();
}
@ -108,6 +108,22 @@ namespace CodeWalker.Project.Panels
ProjectForm.WorldForm.SelectObject(CurrentPathNode);
}
if (PathNodesSpeedComboBox.Items.Count == 0)
{
PathNodesSpeedComboBox.Items.AddRange(Enum.GetValues(typeof(YndNodeSpeed)).Cast<object>().ToArray());
}
if (PathNodeSpecialTypeComboBox.Items.Count == 0)
{
PathNodeSpecialTypeComboBox.Items.AddRange(Enum.GetValues(typeof(YndNodeSpecialType)).Cast<object>().ToArray());
}
PathNodeSpecialTypeComboBox.SelectedItem = CurrentPathNode.Special;
PathNodesSpeedComboBox.SelectedItem = CurrentPathNode.Speed;
PathNodeEnableDisableButton.Text = CurrentPathNode.IsDisabledUnk0
? "Enable Section"
: "Disable Section";
}
}
@ -128,8 +144,8 @@ namespace CodeWalker.Project.Panels
{
populatingui = true;
PathNodeLinkPanel.Enabled = true;
PathNodeLinkAreaIDUpDown.Value = CurrentPathLink._RawData.AreaID;
PathNodeLinkNodeIDUpDown.Value = CurrentPathLink._RawData.NodeID;
PathNodeLinkAreaIDUpDown.Value = CurrentPathLink.Node2?.AreaID ?? 0;
PathNodeLinkNodeIDUpDown.Value = CurrentPathLink.Node2?.NodeID ?? 0;
UpdatePathNodeLinkFlagsUI(true, true);
@ -166,10 +182,10 @@ namespace CodeWalker.Project.Panels
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;
PathNodeJunctionMaxZUpDown.Value = (decimal)junc.MaxZ / 32;
PathNodeJunctionMinZUpDown.Value = (decimal)junc.MinZ / 32;
PathNodeJunctionPosXUpDown.Value = (decimal)junc.PositionX / 32;
PathNodeJunctionPosYUpDown.Value = (decimal)junc.PositionY / 32 ;
PathNodeJunctionHeightmapDimXUpDown.Value = junc.Heightmap.CountX;
PathNodeJunctionHeightmapDimYUpDown.Value = junc.Heightmap.CountY;
PathNodeJunctionHeightmapBytesTextBox.Text = junc.Heightmap?.GetDataString() ?? "";
@ -204,11 +220,6 @@ namespace CodeWalker.Project.Panels
PathNodeFlags11CheckBox.Checked = BitUtil.IsBitSet(flags1, 0);
PathNodeFlags12CheckBox.Checked = BitUtil.IsBitSet(flags1, 1);
PathNodeFlags13CheckBox.Checked = BitUtil.IsBitSet(flags1, 2);
PathNodeFlags14CheckBox.Checked = BitUtil.IsBitSet(flags1, 3);
PathNodeFlags15CheckBox.Checked = BitUtil.IsBitSet(flags1, 4);
PathNodeFlags16CheckBox.Checked = BitUtil.IsBitSet(flags1, 5);
PathNodeFlags17CheckBox.Checked = BitUtil.IsBitSet(flags1, 6);
PathNodeFlags18CheckBox.Checked = BitUtil.IsBitSet(flags1, 7);
PathNodeFlags21CheckBox.Checked = BitUtil.IsBitSet(flags2, 0);
PathNodeFlags22CheckBox.Checked = BitUtil.IsBitSet(flags2, 1);
@ -222,16 +233,15 @@ namespace CodeWalker.Project.Panels
PathNodeFlags31CheckBox.Checked = BitUtil.IsBitSet(flags3, 0);
PathNodeFlags32UpDown.Value = (flags3 >> 1) & 127;
PathNodeFlags41CheckBox.Checked = BitUtil.IsBitSet(flags4, 0);
PathNodeFlags42UpDown.Value = (flags4 >> 1) & 7;
PathNodeFlags45CheckBox.Checked = BitUtil.IsBitSet(flags4, 4);
PathNodeFlags46CheckBox.Checked = BitUtil.IsBitSet(flags4, 5);
PathNodeFlags47CheckBox.Checked = BitUtil.IsBitSet(flags4, 6);
PathNodeFlags42UpDown.Value = (flags4) & 15;
PathNodeFlags44UpDown.Value = (flags4 >> 4) & 7;
PathNodeFlags48CheckBox.Checked = BitUtil.IsBitSet(flags4, 7);
PathNodeFlags51CheckBox.Checked = BitUtil.IsBitSet(flags5, 0);
PathNodeFlags52CheckBox.Checked = BitUtil.IsBitSet(flags5, 1);
PathNodeFlags53CheckBox.Checked = BitUtil.IsBitSet(flags5, 2);
YndNodeIsPedNodeCheckBox.Checked = CurrentPathNode?.IsPedNode ?? false;
PathNodesSpeedComboBox.SelectedItem = CurrentPathNode?.Speed ?? (YndNodeSpeed)(-1);
PathNodeSpecialTypeComboBox.SelectedItem = CurrentPathNode?.Special ?? YndNodeSpecialType.None;
}
if (updateUpDowns)
{
@ -280,7 +290,7 @@ namespace CodeWalker.Project.Panels
PathNodeLinkFlags12CheckBox.Checked = BitUtil.IsBitSet(flags1, 1);
PathNodeLinkFlags13CheckBox.Checked = BitUtil.IsBitSet(flags1, 2);
PathNodeLinkFlags14CheckBox.Checked = BitUtil.IsBitSet(flags1, 3);
PathNodeLinkOffsetSizeUpDown.Value = (flags1 >> 4) & 7;
PathNodeLinkOffsetSizeUpDown.Value = flags1 >> 4 & 7;
PathNodeLinkFlags18CheckBox.Checked = BitUtil.IsBitSet(flags1, 7);
PathNodeLinkFlags21CheckBox.Checked = BitUtil.IsBitSet(flags2, 0);
@ -333,11 +343,6 @@ namespace CodeWalker.Project.Panels
flags1 = BitUtil.UpdateBit(flags1, 0, PathNodeFlags11CheckBox.Checked);
flags1 = BitUtil.UpdateBit(flags1, 1, PathNodeFlags12CheckBox.Checked);
flags1 = BitUtil.UpdateBit(flags1, 2, PathNodeFlags13CheckBox.Checked);
flags1 = BitUtil.UpdateBit(flags1, 3, PathNodeFlags14CheckBox.Checked);
flags1 = BitUtil.UpdateBit(flags1, 4, PathNodeFlags15CheckBox.Checked);
flags1 = BitUtil.UpdateBit(flags1, 5, PathNodeFlags16CheckBox.Checked);
flags1 = BitUtil.UpdateBit(flags1, 6, PathNodeFlags17CheckBox.Checked);
flags1 = BitUtil.UpdateBit(flags1, 7, PathNodeFlags18CheckBox.Checked);
flags2 = BitUtil.UpdateBit(flags2, 0, PathNodeFlags21CheckBox.Checked);
flags2 = BitUtil.UpdateBit(flags2, 1, PathNodeFlags22CheckBox.Checked);
@ -351,16 +356,11 @@ namespace CodeWalker.Project.Panels
flags3 = BitUtil.UpdateBit(flags3, 0, PathNodeFlags31CheckBox.Checked);
flags3 += (((uint)PathNodeFlags32UpDown.Value & 127u) << 1);
flags4 = BitUtil.UpdateBit(flags4, 0, PathNodeFlags41CheckBox.Checked);
flags4 += (((uint)PathNodeFlags42UpDown.Value & 7u) << 1);
flags4 = BitUtil.UpdateBit(flags4, 4, PathNodeFlags45CheckBox.Checked);
flags4 = BitUtil.UpdateBit(flags4, 5, PathNodeFlags46CheckBox.Checked);
flags4 = BitUtil.UpdateBit(flags4, 6, PathNodeFlags47CheckBox.Checked);
flags4 = (byte)((flags4 & ~ 15) | ((uint)PathNodeFlags42UpDown.Value & 15u));
flags4 = (byte)((flags4 & ~ 112) | ((uint)PathNodeFlags44UpDown.Value & 7) << 4);
flags4 = BitUtil.UpdateBit(flags4, 7, PathNodeFlags48CheckBox.Checked);
flags5 = BitUtil.UpdateBit(flags5, 0, PathNodeFlags51CheckBox.Checked);
flags5 = BitUtil.UpdateBit(flags5, 1, PathNodeFlags52CheckBox.Checked);
flags5 = BitUtil.UpdateBit(flags5, 2, PathNodeFlags53CheckBox.Checked);
lock (ProjectForm.ProjectSyncRoot)
@ -372,7 +372,8 @@ namespace CodeWalker.Project.Panels
}
if (CurrentPathNode.Flags1.Value != flags1)
{
CurrentPathNode.Flags1 = (byte)flags1;
// Ignore the last 5 bits for special type
CurrentPathNode.Flags1 = (byte)((uint)(CurrentPathNode.Flags1 &~ 7) | (flags1 & 7));
ProjectForm.SetYndHasChanged(true);
}
if (CurrentPathNode.Flags2.Value != flags2)
@ -387,15 +388,26 @@ namespace CodeWalker.Project.Panels
}
if (CurrentPathNode.Flags4.Value != flags4)
{
CurrentPathNode.Flags4 = (byte)flags4;
CurrentPathNode.Flags4 = (byte)(flags4);
ProjectForm.SetYndHasChanged(true);
}
if (CurrentPathNode.LinkCountUnk != flags5)
{
CurrentPathNode.LinkCountUnk = (byte)flags5;
// Ignore bits 1 and 2 for speed
CurrentPathNode.LinkCountUnk = (byte)((uint)(CurrentPathNode.LinkCountUnk &~ 0xF9) | (flags5 & 0xF9));
ProjectForm.SetYndHasChanged(true);
}
// Allow partner nodes to check if they've become an offroad junction
if (CurrentPathNode.Links != null)
{
foreach (var yndLink in CurrentPathNode.Links)
{
yndLink.Node2?.CheckIfJunction();
}
}
}
populatingui = true;
UpdatePathNodeFlagsUI(false, true); //update updowns
@ -423,7 +435,7 @@ namespace CodeWalker.Project.Panels
}
if (CurrentPathNode.Flags1.Value != flags1)
{
CurrentPathNode.Flags1 = (byte)flags1;
CurrentPathNode.Flags1 = (byte)((uint)(CurrentPathNode.Flags1 & ~7) | (flags1 & 7));
ProjectForm.SetYndHasChanged(true);
}
if (CurrentPathNode.Flags2.Value != flags2)
@ -443,7 +455,7 @@ namespace CodeWalker.Project.Panels
}
if (CurrentPathNode.LinkCountUnk != flags5)
{
CurrentPathNode.LinkCountUnk = (byte)flags5;
CurrentPathNode.LinkCountUnk = (byte)((uint)(CurrentPathNode.LinkCountUnk & ~0xF9) | (flags5 & 0xF9));
ProjectForm.SetYndHasChanged(true);
}
}
@ -475,8 +487,6 @@ namespace CodeWalker.Project.Panels
flags2 = BitUtil.UpdateBit(flags2, 0, PathNodeLinkFlags21CheckBox.Checked);
flags2 = BitUtil.UpdateBit(flags2, 1, PathNodeLinkFlags22CheckBox.Checked);
flags2 += (((uint)PathNodeLinkBackLanesUpDown.Value & 7u) << 2);
flags2 += (((uint)PathNodeLinkFwdLanesUpDown.Value & 7u) << 5);
bool updgfx = false;
lock (ProjectForm.ProjectSyncRoot)
@ -494,7 +504,24 @@ namespace CodeWalker.Project.Panels
}
if (CurrentPathLink.Flags2.Value != flags2)
{
CurrentPathLink.Flags2 = (byte)flags2;
CurrentPathLink.Flags2= (byte)((uint)(CurrentPathLink.Flags2 & ~ 3) | flags2);
ProjectForm.SetYndHasChanged(true);
updgfx = true;
}
int forwardLanes = (int)PathNodeLinkFwdLanesUpDown.Value;
if (forwardLanes != CurrentPathLink.LaneCountForward)
{
CurrentPathLink.SetForwardLanesBidirectionally(forwardLanes);
ProjectForm.SetYndHasChanged(true);
updgfx = true;
}
int backwardLanes = (int)PathNodeLinkBackLanesUpDown.Value;
if (backwardLanes != CurrentPathLink.LaneCountBackward)
{
CurrentPathLink.SetBackwardLanesBidirectionally(backwardLanes);
ProjectForm.SetYndHasChanged(true);
updgfx = true;
}
@ -555,6 +582,7 @@ namespace CodeWalker.Project.Panels
{
if (CurrentPathNode == null) return;
var l = CurrentPathNode.AddLink();
LoadPathNodeTabPage();
@ -572,6 +600,12 @@ namespace CodeWalker.Project.Panels
if (CurrentPathLink == null) return;
if (CurrentPathNode == null) return;
var partners = CurrentPathLink.Node2.Links.Where(l => l.Node2 == CurrentPathNode);
foreach (var partner in partners)
{
partner.Node1.RemoveLink(partner);
}
var r = CurrentPathNode.RemoveLink(CurrentPathLink);
if (!r) return;
@ -592,6 +626,7 @@ namespace CodeWalker.Project.Panels
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.
@ -618,9 +653,17 @@ namespace CodeWalker.Project.Panels
PathNodeLinkageStatusLabel.Text = "";
}
var partner = CurrentPathLink.Node2.Links.FirstOrDefault(l => l.Node2 == CurrentPathNode);
partner?.Node1.RemoveLink(partner);
CurrentPathLink.Node2 = linknode;
CurrentPathLink.UpdateLength();
var l2 = linknode?.AddLink(CurrentPathNode);
if (l2 != null && partner != null)
{
l2.CopyFlags(partner);
}
////need to rebuild the link verts.. updating the graphics should do it...
if (ProjectForm.WorldForm != null)
@ -679,7 +722,14 @@ namespace CodeWalker.Project.Panels
{
if (CurrentPathNode.Position != v)
{
CurrentPathNode.SetPosition(v);
CurrentPathNode.SetYndNodePosition(ProjectForm.WorldForm.Space, v, out var affectedFiles);
foreach (var affectedFile in affectedFiles)
{
ProjectForm.AddYndToProject(affectedFile);
ProjectForm.SetYndHasChanged(affectedFile, true);
}
ProjectForm.SetYndHasChanged(true);
change = true;
}
@ -933,17 +983,11 @@ namespace CodeWalker.Project.Panels
SetPathNodeFlagsFromCheckBoxes(); //treat this one like checkboxes
}
private void PathNodeFlags52CheckBox_CheckedChanged(object sender, EventArgs e)
private void PathNodeFlags44UpDown_ValueChanged(object sender, EventArgs e)
{
SetPathNodeFlagsFromCheckBoxes();
SetPathNodeFlagsFromCheckBoxes(); //treat this one like checkboxes
}
private void PathNodeFlags53CheckBox_CheckedChanged(object sender, EventArgs e)
{
SetPathNodeFlagsFromCheckBoxes();
}
private void PathNodeLinksListBox_SelectedIndexChanged(object sender, EventArgs e)
{
CurrentPathLink = PathNodeLinksListBox.SelectedItem as YndLink;
@ -1123,14 +1167,19 @@ namespace CodeWalker.Project.Panels
{
var j = new YndJunction();
//init new junction
j._RawData.HeightmapDimX = 1;
j._RawData.HeightmapDimY = 1;
j.Heightmap = new YndJunctionHeightmap(new byte[] { 255 }, j);
j._RawData.HeightmapDimX = 16;
j._RawData.HeightmapDimY = 16;
j.MaxZ = (short)(CurrentPathNode.Position.Z * 32 + 32);
j.MinZ = (short)(CurrentPathNode.Position.Z * 32 - 32);
j.PositionX = (short)(CurrentPathNode.Position.X * 4f - j.RawData.HeightmapDimY * 4f);
j.PositionY = (short)(CurrentPathNode.Position.Y * 4f - j.RawData.HeightmapDimY * 4f);
j.Heightmap = new YndJunctionHeightmap(Enumerable.Repeat((byte)255, j._RawData.HeightmapDimX * j._RawData.HeightmapDimY).ToArray(), j);
j.RefData = new NodeJunctionRef() { AreaID = (ushort)CurrentPathNode.AreaID, NodeID = (ushort)CurrentPathNode.NodeID };
CurrentPathNode.Junction = j;
}
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
}
LoadPathNodeJunctionPage();
@ -1141,7 +1190,7 @@ namespace CodeWalker.Project.Panels
if (populatingui) return;
if (CurrentPathNode == null) return;
if (CurrentPathNode.Junction == null) return;
short val = (short)PathNodeJunctionMaxZUpDown.Value;
short val = (short)(PathNodeJunctionMaxZUpDown.Value * 32);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentPathNode.Junction.MaxZ != val)
@ -1149,6 +1198,7 @@ namespace CodeWalker.Project.Panels
CurrentPathNode.Junction.MaxZ = val;
CurrentPathNode.Junction._RawData.MaxZ = val;
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
}
}
@ -1158,7 +1208,7 @@ namespace CodeWalker.Project.Panels
if (populatingui) return;
if (CurrentPathNode == null) return;
if (CurrentPathNode.Junction == null) return;
short val = (short)PathNodeJunctionMinZUpDown.Value;
short val = (short)(PathNodeJunctionMinZUpDown.Value * 32);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentPathNode.Junction.MinZ != val)
@ -1166,6 +1216,7 @@ namespace CodeWalker.Project.Panels
CurrentPathNode.Junction.MinZ = val;
CurrentPathNode.Junction._RawData.MinZ = val;
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
}
}
@ -1175,7 +1226,7 @@ namespace CodeWalker.Project.Panels
if (populatingui) return;
if (CurrentPathNode == null) return;
if (CurrentPathNode.Junction == null) return;
short val = (short)PathNodeJunctionPosXUpDown.Value;
short val = (short)(PathNodeJunctionPosXUpDown.Value * 32);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentPathNode.Junction.PositionX != val)
@ -1183,6 +1234,7 @@ namespace CodeWalker.Project.Panels
CurrentPathNode.Junction.PositionX = val;
CurrentPathNode.Junction._RawData.PositionX = val;
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
}
}
@ -1192,7 +1244,7 @@ namespace CodeWalker.Project.Panels
if (populatingui) return;
if (CurrentPathNode == null) return;
if (CurrentPathNode.Junction == null) return;
short val = (short)PathNodeJunctionPosYUpDown.Value;
short val = (short)(PathNodeJunctionPosYUpDown.Value * 32);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentPathNode.Junction.PositionY != val)
@ -1200,6 +1252,7 @@ namespace CodeWalker.Project.Panels
CurrentPathNode.Junction.PositionY = val;
CurrentPathNode.Junction._RawData.PositionY = val;
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
}
}
@ -1217,6 +1270,7 @@ namespace CodeWalker.Project.Panels
CurrentPathNode.Junction._RawData.HeightmapDimX = val;
CurrentPathNode.Junction.ResizeHeightmap();
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
}
LoadPathNodeJunctionPage();
@ -1235,6 +1289,7 @@ namespace CodeWalker.Project.Panels
CurrentPathNode.Junction._RawData.HeightmapDimY = val;
CurrentPathNode.Junction.ResizeHeightmap();
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
}
LoadPathNodeJunctionPage();
@ -1249,8 +1304,166 @@ namespace CodeWalker.Project.Panels
{
CurrentPathNode.Junction.SetHeightmap(PathNodeJunctionHeightmapBytesTextBox.Text);
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
//LoadPathNodeJunctionPage();
}
private void YndNodeJunctionGenerateButton_Click(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentPathNode == null) return;
if (CurrentPathNode.Junction == null) return;
lock (ProjectForm.ProjectSyncRoot)
{
CurrentPathNode.GenerateYndNodeJunctionHeightMap(ProjectForm.WorldForm.Space);
ProjectForm.SetYndHasChanged(true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
LoadPathNodeJunctionPage();
}
private void PathNodesSpeedComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentPathNode == null) return;
lock (ProjectForm.ProjectSyncRoot)
{
var speed = (YndNodeSpeed)PathNodesSpeedComboBox.SelectedItem;
if (CurrentPathNode.Speed != speed)
{
CurrentPathNode.Speed = speed;
ProjectForm.SetYndHasChanged(true);
UpdatePathNodeFlagsUI(true, true);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
}
}
}
private void PathNodeSpecialTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentPathNode == null) return;
lock (ProjectForm.ProjectSyncRoot)
{
var special = (YndNodeSpecialType)PathNodeSpecialTypeComboBox.SelectedItem;
if (CurrentPathNode.Special != special)
{
var isPedNode = CurrentPathNode.IsPedNode;
bool specialIsPedNode = YndNode.IsSpecialTypeAPedNode(special);
if (isPedNode != specialIsPedNode)
{
var res = MessageBox.Show(
specialIsPedNode
? "This operation will change this node from a vehicle node to a ped node. This will remove all links. Are you sure you want to do this?"
: "This operation will change this node from a ped node to a vehicle node. This will remove all links. Are you sure you want to do this?",
"Are you sure?",
MessageBoxButtons.YesNo
);
if (res == DialogResult.No)
{
PathNodeSpecialTypeComboBox.SelectedItem = CurrentPathNode.Special;
return;
}
if (ProjectForm != null)
{
CurrentPathNode.RemoveYndLinksForNode(ProjectForm.WorldForm.Space, out var affectedFiles);
ProjectForm.AddYndToProject(CurrentYndFile);
ProjectForm.WorldForm?.UpdatePathYndGraphics(CurrentYndFile, false);
foreach (var file in affectedFiles)
{
ProjectForm.AddYndToProject(file);
ProjectForm.WorldForm?.UpdatePathYndGraphics(file, false);
ProjectForm.SetYndHasChanged(file, true);
}
}
}
CurrentPathNode.Special = special;
YndNodeIsPedNodeCheckBox.Checked = CurrentPathNode.IsPedNode;
UpdatePathNodeFlagsUI(true, true);
ProjectForm.SetYndHasChanged(true);
}
}
}
private void PathNodeSelectPartnerButton_Click(object sender, EventArgs e)
{
if (CurrentPathLink == null)
return;
var partner = CurrentPathLink.Node2.Links.FirstOrDefault(l => l.Node2 == CurrentPathNode);
if (partner == null)
{
MessageBox.Show("Could not find partner!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
CurrentPathNode = partner.Node1;
CurrentPathLink = partner;
LoadPathNodeLinkPage();
LoadPathNodeLinkPage();
PathNodeLinksListBox.SelectedItem = partner;
}
private void PathNodeFloodCopyButton_Click(object sender, EventArgs e)
{
if (CurrentPathNode == null)
{
return;
}
CurrentPathNode.FloodCopyFlags(out var affectedFiles);
ProjectForm.AddYndToProject(CurrentYndFile);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
foreach (var affectedFile in affectedFiles)
{
ProjectForm.AddYndToProject(affectedFile);
ProjectForm.SetYndHasChanged(affectedFile, true);
ProjectForm.WorldForm.UpdatePathYndGraphics(affectedFile, false);
}
}
private void PathNodeEnableDisableButton_Click(object sender, EventArgs e)
{
if (CurrentPathNode == null)
{
return;
}
lock (ProjectForm.ProjectSyncRoot)
{
CurrentPathNode.IsDisabledUnk0 = !CurrentPathNode.IsDisabledUnk0;
CurrentPathNode.IsDisabledUnk1 = CurrentPathNode.IsDisabledUnk0;
CurrentPathNode.FloodCopyFlags(out var affectedFiles);
PathNodeEnableDisableButton.Text = CurrentPathNode.IsDisabledUnk0
? "Enable Section"
: "Disable Section";
ProjectForm.AddYndToProject(CurrentYndFile);
ProjectForm.WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
foreach (var affectedFile in affectedFiles)
{
ProjectForm.AddYndToProject(affectedFile);
ProjectForm.SetYndHasChanged(affectedFile, true);
ProjectForm.WorldForm.UpdatePathYndGraphics(affectedFile, false);
}
}
UpdatePathNodeFlagsUI(true, false);
}
}
}

View File

@ -55,53 +55,58 @@
// label88
//
this.label88.AutoSize = true;
this.label88.Location = new System.Drawing.Point(183, 20);
this.label88.Location = new System.Drawing.Point(274, 31);
this.label88.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label88.Name = "label88";
this.label88.Size = new System.Drawing.Size(17, 13);
this.label88.Size = new System.Drawing.Size(24, 20);
this.label88.TabIndex = 36;
this.label88.Text = "Y:";
//
// YndAreaIDYUpDown
//
this.YndAreaIDYUpDown.Location = new System.Drawing.Point(206, 18);
this.YndAreaIDYUpDown.Location = new System.Drawing.Point(309, 28);
this.YndAreaIDYUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
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.Size = new System.Drawing.Size(72, 26);
this.YndAreaIDYUpDown.TabIndex = 35;
this.YndAreaIDYUpDown.ValueChanged += new System.EventHandler(this.YndAreaIDYUpDown_ValueChanged);
//
// label87
//
this.label87.AutoSize = true;
this.label87.Location = new System.Drawing.Point(101, 20);
this.label87.Location = new System.Drawing.Point(152, 31);
this.label87.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label87.Name = "label87";
this.label87.Size = new System.Drawing.Size(17, 13);
this.label87.Size = new System.Drawing.Size(24, 20);
this.label87.TabIndex = 34;
this.label87.Text = "X:";
//
// YndAreaIDXUpDown
//
this.YndAreaIDXUpDown.Location = new System.Drawing.Point(124, 18);
this.YndAreaIDXUpDown.Location = new System.Drawing.Point(186, 28);
this.YndAreaIDXUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
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.Size = new System.Drawing.Size(72, 26);
this.YndAreaIDXUpDown.TabIndex = 33;
this.YndAreaIDXUpDown.ValueChanged += new System.EventHandler(this.YndAreaIDXUpDown_ValueChanged);
//
// label48
//
this.label48.AutoSize = true;
this.label48.Location = new System.Drawing.Point(23, 216);
this.label48.Location = new System.Drawing.Point(34, 332);
this.label48.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label48.Name = "label48";
this.label48.Size = new System.Drawing.Size(68, 13);
this.label48.Size = new System.Drawing.Size(99, 20);
this.label48.TabIndex = 32;
this.label48.Text = "Project Path:";
//
@ -109,18 +114,20 @@
//
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(97, 213);
this.YndProjectPathTextBox.Location = new System.Drawing.Point(146, 328);
this.YndProjectPathTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.YndProjectPathTextBox.Name = "YndProjectPathTextBox";
this.YndProjectPathTextBox.ReadOnly = true;
this.YndProjectPathTextBox.Size = new System.Drawing.Size(450, 20);
this.YndProjectPathTextBox.Size = new System.Drawing.Size(673, 26);
this.YndProjectPathTextBox.TabIndex = 31;
//
// label46
//
this.label46.AutoSize = true;
this.label46.Location = new System.Drawing.Point(23, 190);
this.label46.Location = new System.Drawing.Point(34, 292);
this.label46.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label46.Name = "label46";
this.label46.Size = new System.Drawing.Size(51, 13);
this.label46.Size = new System.Drawing.Size(75, 20);
this.label46.TabIndex = 30;
this.label46.Text = "File Path:";
//
@ -128,89 +135,100 @@
//
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(97, 187);
this.YndFilePathTextBox.Location = new System.Drawing.Point(146, 288);
this.YndFilePathTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.YndFilePathTextBox.Name = "YndFilePathTextBox";
this.YndFilePathTextBox.ReadOnly = true;
this.YndFilePathTextBox.Size = new System.Drawing.Size(450, 20);
this.YndFilePathTextBox.Size = new System.Drawing.Size(673, 26);
this.YndFilePathTextBox.TabIndex = 29;
//
// label47
//
this.label47.AutoSize = true;
this.label47.Location = new System.Drawing.Point(23, 164);
this.label47.Location = new System.Drawing.Point(34, 252);
this.label47.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label47.Name = "label47";
this.label47.Size = new System.Drawing.Size(52, 13);
this.label47.Size = new System.Drawing.Size(76, 20);
this.label47.TabIndex = 28;
this.label47.Text = "Rpf Path:";
//
// YndTotalNodesLabel
//
this.YndTotalNodesLabel.AutoSize = true;
this.YndTotalNodesLabel.Location = new System.Drawing.Point(23, 59);
this.YndTotalNodesLabel.Location = new System.Drawing.Point(34, 91);
this.YndTotalNodesLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.YndTotalNodesLabel.Name = "YndTotalNodesLabel";
this.YndTotalNodesLabel.Size = new System.Drawing.Size(77, 13);
this.YndTotalNodesLabel.Size = new System.Drawing.Size(111, 20);
this.YndTotalNodesLabel.TabIndex = 27;
this.YndTotalNodesLabel.Text = "Total Nodes: 0";
//
// YndPedNodesUpDown
//
this.YndPedNodesUpDown.Location = new System.Drawing.Point(377, 57);
this.YndPedNodesUpDown.Enabled = false;
this.YndPedNodesUpDown.Location = new System.Drawing.Point(566, 88);
this.YndPedNodesUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
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.Size = new System.Drawing.Size(111, 26);
this.YndPedNodesUpDown.TabIndex = 26;
this.YndPedNodesUpDown.ValueChanged += new System.EventHandler(this.YndPedNodesUpDown_ValueChanged);
//
// label45
//
this.label45.AutoSize = true;
this.label45.Location = new System.Drawing.Point(308, 59);
this.label45.Location = new System.Drawing.Point(462, 91);
this.label45.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label45.Name = "label45";
this.label45.Size = new System.Drawing.Size(63, 13);
this.label45.Size = new System.Drawing.Size(91, 20);
this.label45.TabIndex = 25;
this.label45.Text = "Ped Nodes:";
//
// YndVehicleNodesUpDown
//
this.YndVehicleNodesUpDown.Location = new System.Drawing.Point(206, 57);
this.YndVehicleNodesUpDown.Enabled = false;
this.YndVehicleNodesUpDown.Location = new System.Drawing.Point(309, 88);
this.YndVehicleNodesUpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
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.Size = new System.Drawing.Size(111, 26);
this.YndVehicleNodesUpDown.TabIndex = 24;
this.YndVehicleNodesUpDown.ValueChanged += new System.EventHandler(this.YndVehicleNodesUpDown_ValueChanged);
//
// label40
//
this.label40.AutoSize = true;
this.label40.Location = new System.Drawing.Point(121, 59);
this.label40.Location = new System.Drawing.Point(182, 91);
this.label40.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label40.Name = "label40";
this.label40.Size = new System.Drawing.Size(79, 13);
this.label40.Size = new System.Drawing.Size(115, 20);
this.label40.TabIndex = 23;
this.label40.Text = "Vehicle Nodes:";
//
// YndAreaIDInfoLabel
//
this.YndAreaIDInfoLabel.AutoSize = true;
this.YndAreaIDInfoLabel.Location = new System.Drawing.Point(271, 20);
this.YndAreaIDInfoLabel.Location = new System.Drawing.Point(406, 31);
this.YndAreaIDInfoLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.YndAreaIDInfoLabel.Name = "YndAreaIDInfoLabel";
this.YndAreaIDInfoLabel.Size = new System.Drawing.Size(30, 13);
this.YndAreaIDInfoLabel.Size = new System.Drawing.Size(43, 20);
this.YndAreaIDInfoLabel.TabIndex = 22;
this.YndAreaIDInfoLabel.Text = "ID: 0";
//
// label33
//
this.label33.AutoSize = true;
this.label33.Location = new System.Drawing.Point(45, 20);
this.label33.Location = new System.Drawing.Point(68, 31);
this.label33.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label33.Name = "label33";
this.label33.Size = new System.Drawing.Size(46, 13);
this.label33.Size = new System.Drawing.Size(68, 20);
this.label33.TabIndex = 21;
this.label33.Text = "Area ID:";
//
@ -218,17 +236,18 @@
//
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(97, 161);
this.YndRpfPathTextBox.Location = new System.Drawing.Point(146, 248);
this.YndRpfPathTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.YndRpfPathTextBox.Name = "YndRpfPathTextBox";
this.YndRpfPathTextBox.ReadOnly = true;
this.YndRpfPathTextBox.Size = new System.Drawing.Size(450, 20);
this.YndRpfPathTextBox.Size = new System.Drawing.Size(673, 26);
this.YndRpfPathTextBox.TabIndex = 20;
//
// EditYndPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(574, 499);
this.ClientSize = new System.Drawing.Size(861, 768);
this.Controls.Add(this.label88);
this.Controls.Add(this.YndAreaIDYUpDown);
this.Controls.Add(this.label87);
@ -247,6 +266,7 @@
this.Controls.Add(this.label33);
this.Controls.Add(this.YndRpfPathTextBox);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.Name = "EditYndPanel";
this.Text = "Edit Ynd";
((System.ComponentModel.ISupportInitialize)(this.YndAreaIDYUpDown)).EndInit();

View File

@ -101,14 +101,19 @@ namespace CodeWalker.Project.Panels
int y = (int)YndAreaIDYUpDown.Value;
lock (ProjectForm.ProjectSyncRoot)
{
var areaid = y * 32 + x;
if (Ynd.AreaID != areaid)
if (ProjectForm.WorldForm == null)
{
Ynd.AreaID = areaid;
Ynd.Name = "nodes" + areaid.ToString() + ".ynd";
YndAreaIDInfoLabel.Text = "ID: " + areaid.ToString();
ProjectForm.SetYndHasChanged(true);
MessageBox.Show("You can only do this while in full CodeWalker", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
ProjectForm.WorldForm.Space.MoveYndArea(Ynd, x, y);
ProjectForm.SetYndHasChanged(Ynd, true);
// Take the updated information
YndAreaIDInfoLabel.Text = Ynd.AreaID.ToString();
YndAreaIDXUpDown.Value = Ynd.CellX;
YndAreaIDYUpDown.Value = Ynd.CellY;
}
UpdateFormTitleYndChanged();
}

View File

@ -792,7 +792,7 @@ namespace CodeWalker.Project
}
}
var multisel = MapSelection.FromProjectObject(arr); //convert to MapSelection array
var multisel = MapSelection.FromProjectObject(WorldForm, arr); //convert to MapSelection array
item = multisel.MultipleSelectionItems;
}
@ -4622,16 +4622,6 @@ namespace CodeWalker.Project
if ((CurrentYndFile == null) && (CurrentPathNode != null)) CurrentYndFile = CurrentPathNode.Ynd;
if (CurrentYndFile == null) return;
// Check that vehicle nodes and ped nodes add up to total nodes
if (CurrentYndFile.NodeDictionary != null && (CurrentYndFile.NodeDictionary.NodesCountPed + CurrentYndFile.NodeDictionary.NodesCountVehicle != CurrentYndFile.NodeDictionary.NodesCount))
{
var result = MessageBox.Show($"YND Area {CurrentYndFile.AreaID}: The total number of nodes ({CurrentYndFile.NodeDictionary.NodesCount}) does not match the total number of ped ({CurrentYndFile.NodeDictionary.NodesCountPed}) and vehicle ({CurrentYndFile.NodeDictionary.NodesCountVehicle}) nodes. You should manually adjust the number of nodes on the YND screen.\n\nDo you want to continue saving the YND file? Some of your nodes may not work in game.", $"Node count mismatch in Area {CurrentYndFile.AreaID}", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
if (result == DialogResult.Cancel)
{
return;
}
}
string yndname = CurrentYndFile.Name;
string filepath = CurrentYndFile.FilePath;
if (string.IsNullOrEmpty(filepath))
@ -4662,7 +4652,7 @@ namespace CodeWalker.Project
CurrentYndFile.Name = CurrentYndFile.RpfFileEntry.Name;
}
WorldForm.Space.RecalculateAllYndIndices();
data = CurrentYndFile.Save();
}
@ -4733,25 +4723,32 @@ namespace CodeWalker.Project
{
if (CurrentYndFile == null) return null;
var n = CurrentYndFile.AddNode();
var areaid = n.AreaID;
var nodeid = n.NodeID;
var n = CurrentYndFile.AddYndNode(WorldForm.Space, out var affectedFiles);
AddYndToProject(CurrentYndFile);
foreach (var affectedFile in affectedFiles)
{
AddYndToProject(affectedFile);
SetYndHasChanged(affectedFile, true);
}
if (copy == null)
{
copy = CurrentPathNode;
}
if (copy != null)
{
n.Init(CurrentYndFile, copy.RawData);
n.Flags0 = copy.Flags0;
n.Flags1 = copy.Flags1;
n.Flags2 = copy.Flags2;
n.Flags3 = copy.Flags3;
n.Flags4 = copy.Flags4;
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);
n.SetYndNodePosition(WorldForm.Space, pos, out _);
if (copy != null)
{
@ -4777,6 +4774,9 @@ namespace CodeWalker.Project
}
}
n.CheckIfJunction();
copy?.CheckIfJunction();
CurrentYndFile.UpdateAllNodePositions(); //for the graphics...
CurrentYndFile.BuildBVH();
@ -4811,20 +4811,22 @@ namespace CodeWalker.Project
//}
bool res = false;
YndFile[] affectedFiles = new YndFile[0];
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
res = CurrentYndFile.RemoveNode(CurrentPathNode);
res = CurrentYndFile.RemoveYndNode(WorldForm.Space, CurrentPathNode, true, out affectedFiles);
//WorldForm.SelectItem(null, null, null);
}
}
else
{
res = CurrentYndFile.RemoveNode(CurrentPathNode);
}
if (!res)
//{
// res = CurrentYndFile.RemoveNode(CurrentPathNode);
//}
//if (!res)
{
MessageBox.Show("Unable to delete the path node. This shouldn't happen!");
}
@ -4832,7 +4834,7 @@ namespace CodeWalker.Project
var delnode = CurrentPathNode;
ProjectExplorer?.RemovePathNodeTreeNode(CurrentPathNode);
ProjectExplorer?.SetYndHasChanged(CurrentYndFile, true);
SetYndHasChanged(CurrentYndFile, true);
ClosePanel((EditYndNodePanel p) => { return p.Tag == delnode; });
@ -4841,6 +4843,15 @@ namespace CodeWalker.Project
if (WorldForm != null)
{
WorldForm.UpdatePathYndGraphics(CurrentYndFile, false);
AddYndToProject(CurrentYndFile);
foreach (var affectedFile in affectedFiles)
{
WorldForm.UpdatePathYndGraphics(affectedFile, false);
AddYndToProject(affectedFile);
SetYndHasChanged(affectedFile, true, true);
}
WorldForm.SelectItem(null);
}
@ -7082,7 +7093,9 @@ namespace CodeWalker.Project
lock (projectsyncroot)
{
if (renderitems && (CurrentProjectFile != null))
if (CurrentProjectFile == null) return;
var hasymapytyp = ((CurrentProjectFile.YmapFiles.Count > 0) || (CurrentProjectFile.YtypFiles.Count > 0));
if (renderitems && hasymapytyp)
{
for (int i = 0; i < CurrentProjectFile.YmapFiles.Count; i++)
{
@ -7100,12 +7113,12 @@ namespace CodeWalker.Project
}
visiblemloentities.Clear();
foreach (var kvp in ymaps)
foreach (var kvp in ymaps)//TODO: improve performance
{
var ymap = kvp.Value;
if (ymap.AllEntities != null)
if (ymap.AllEntities != null)//THIS IS TERRIBLE! EATING ALL FPS
{
foreach (var ent in ymap.AllEntities)
foreach (var ent in ymap.AllEntities)//WHYYYY - maybe only do this after loading/editing ytyp!
{
Archetype arch = GameFileCache.GetArchetype(ent._CEntityDef.archetypeName);
if ((arch != null) && (ent.Archetype != arch))
@ -8431,16 +8444,21 @@ namespace CodeWalker.Project
PromoteIfPreviewPanelActive();
}
public void SetYndHasChanged(bool changed)
public void SetYndHasChanged(bool changed, bool force = false)
{
if (CurrentYndFile == null) return;
SetYndHasChanged(CurrentYndFile, changed, force);
}
public void SetYndHasChanged(YndFile yndFile, bool changed, bool force = false)
{
if (yndFile == null) return;
bool changechange = changed != CurrentYndFile.HasChanged;
if (!changechange) return;
bool changechange = changed != yndFile.HasChanged;
if (!force && !changechange) return;
CurrentYndFile.HasChanged = changed;
yndFile.HasChanged = changed;
ProjectExplorer?.SetYndHasChanged(CurrentYndFile, changed);
ProjectExplorer?.SetYndHasChanged(yndFile, changed);
PromoteIfPreviewPanelActive();
}
@ -8609,10 +8627,25 @@ namespace CodeWalker.Project
byte[] data = File.ReadAllBytes(filename);
ynd.Load(data);
WorldForm.Space.PatchYndFile(ynd);
if (WorldForm != null)
{
WorldForm.UpdatePathYndGraphics(ynd, true); //links don't get drawn until something changes otherwise
// TODO: Wasteful -- be smarter about this
foreach (var file in CurrentProjectFile.YndFiles)
{
foreach (var affected in WorldForm.Space.GetYndFilesThatDependOnYndFile(file))
{
if (CurrentProjectFile.ContainsYnd(affected))
{
continue;
}
WorldForm.UpdatePathYndGraphics(affected, true);
}
WorldForm.UpdatePathYndGraphics(file, true); //links don't get drawn until something changes otherwise
}
//note: this is actually necessary to properly populate junctions data........
}
}

View File

@ -1286,7 +1286,8 @@ namespace CodeWalker.Project
private void Update(WorldForm wf, ref MapSelection sel, Vector3 p)
{
PathNode?.SetPosition(p);
//TODO: Support migrating back!
PathNode.SetYndNodePosition(wf.Space, p, out _);
if (PathNode != sel.PathNode)
{

View File

@ -45,6 +45,7 @@ namespace CodeWalker
[TypeConverter(typeof(ExpandableObjectConverter))]
public struct MapSelection
{
public WorldForm WorldForm { get; set; }
public YmapEntityDef EntityDef { get; set; }
public Archetype Archetype { get; set; }
public DrawableBase Drawable { get; set; }
@ -1062,7 +1063,11 @@ namespace CodeWalker
}
else if (PathNode != null)
{
PathNode.SetPosition(newpos);
PathNode.SetYndNodePosition(WorldForm.Space, newpos, out var affectedFiles);
foreach (var affectedFile in affectedFiles)
{
WorldForm.UpdatePathYndGraphics(affectedFile, false);
}
}
else if (NavPoly != null)
{
@ -1491,16 +1496,17 @@ namespace CodeWalker
return null;
}
public static MapSelection FromProjectObject(object o, object parent = null)
public static MapSelection FromProjectObject(WorldForm worldForm, object o, object parent = null)
{
const float nrad = 0.5f;
var ms = new MapSelection();
ms.WorldForm = worldForm;
if (o is object[] arr)
{
var multi = new MapSelection[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
multi[i] = FromProjectObject(arr[i]);
multi[i] = FromProjectObject(worldForm, arr[i]);
}
ms.SetMultipleSelectionItems(multi);
}

View File

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Linq;
using SharpDX;
using SharpDX.XInput;
using Device = SharpDX.Direct3D11.Device;
@ -221,6 +222,10 @@ namespace CodeWalker
weather = Renderer.weather;
clouds = Renderer.clouds;
CurMouseHit.WorldForm = this;
LastMouseHit.WorldForm = this;
PrevMouseHit.WorldForm = this;
initedOk = Renderer.Init();
}
@ -1865,6 +1870,15 @@ namespace CodeWalker
public void UpdatePathYndGraphics(YndFile ynd, bool fullupdate)
{
if (ynd == null)
{
return;
}
var selection = SelectedItem.PathNode != null
? new[] { SelectedItem.PathNode }
: null;
if (fullupdate)
{
ynd.UpdateAllNodePositions();
@ -1875,7 +1889,7 @@ namespace CodeWalker
else
{
ynd.UpdateAllNodePositions();
space.BuildYndVerts(ynd);
space.BuildYndVerts(ynd, selection);
}
//lock (Renderer.RenderSyncRoot)
{
@ -3140,7 +3154,7 @@ namespace CodeWalker
MapBox mb = new MapBox();
int lanestot = ln.LaneCountForward + ln.LaneCountBackward;
float lanewidth = n.IsPedNode ? 0.5f : 5.5f;
float lanewidth = ln.GetLaneWidth();
float inner = ln.LaneOffset * lanewidth;// 0.0f;
float outer = inner + Math.Max(lanewidth * ln.LaneCountForward, 0.5f);
float totwidth = lanestot * lanewidth;
@ -3416,7 +3430,7 @@ namespace CodeWalker
}
else
{
var ms = MapSelection.FromProjectObject(obj, parent);
var ms = MapSelection.FromProjectObject(this, obj, parent);
if (!ms.HasValue)
{
SelectItem(null, addSelection);
@ -3446,7 +3460,7 @@ namespace CodeWalker
mhitv.Drawable = gameFileCache.TryGetDrawable(mhitv.Archetype); //no drawable given.. try to get it from the cache.. if it's not there, drawable info won't display...
}
var oldnode = SelectedItem.PathNode;
bool change = false;
if (mhit != null)
{
@ -3594,6 +3608,19 @@ namespace CodeWalker
{
ProjectForm.OnWorldSelectionChanged(SelectedItem);
}
var newnode = SelectedItem.PathNode;
if (newnode != oldnode)//this is to allow junction heightmaps to be displayed when selecting a junction node
{
UpdatePathYndGraphics(oldnode?.Ynd, false);
UpdatePathYndGraphics(newnode?.Ynd, false);
}
if (change)
{
// If an item has been selected the user is likely to use a keybind. We need focus!
Focus();
}
}
public void SelectMulti(MapSelection[] items, bool addSelection = false, bool notifyProject = true)
{
@ -5213,16 +5240,27 @@ namespace CodeWalker
private void DeletePathNode(YndNode pathnode)
{
if (pathnode == null) return;
if (pathnode.Ynd == null) return;
//project not open, or cargen not selected there, just remove the cargen from the ymap...
//project not open, or node not selected there, just remove the node from the ynd...
var ynd = pathnode.Ynd;
if (!ynd.RemoveNode(pathnode))
if (!ynd.RemoveYndNode(Space, pathnode, true, out var affectedFiles))
{
MessageBox.Show("Unable to remove path node.");
}
else
{
UpdatePathNodeGraphics(pathnode, false);
ProjectForm?.AddYndToProject(ynd);
foreach (var affectedFile in affectedFiles)
{
UpdatePathYndGraphics(affectedFile, false);
ProjectForm?.AddYndToProject(affectedFile);
affectedFile.HasChanged = true;
}
SelectItem(null);
}
}
@ -5798,6 +5836,82 @@ namespace CodeWalker
private void TryCreateNodeLink()//TODO: move this to project window
{
if (SelectionMode != MapSelectionMode.Path)
{
return;
}
var selection = SelectedItem.MultipleSelectionItems;
if (selection?.Length != 2)
{
MessageBox.Show("Please select 2 nodes to perform this action",
"Join Failed.",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var n1 = selection[0].PathNode;
var n2 = selection[1].PathNode;
if (n1 != null && n2 != null)
{
var link = n1.AddLink(n2);
if (link == null)
{
MessageBox.Show("Failed to join nodes. The nodes are likely too far away!", "Join Failed.", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var copy = n1.Links.FirstOrDefault();
link.SetForwardLanesBidirectionally(copy?.LaneCountBackward ?? 1);
link.SetBackwardLanesBidirectionally(copy?.LaneCountForward ?? 1);
UpdatePathYndGraphics(n1.Ynd, false);
UpdatePathYndGraphics(n2.Ynd, false);
}
}
private void TryCreateNodeShortcut()//TODO: move this to project window
{
if (SelectionMode != MapSelectionMode.Path)
{
return;
}
var selection = SelectedItem.MultipleSelectionItems;
if (selection?.Length != 2)
{
MessageBox.Show("Please select 2 nodes to perform this action",
"Join Failed.",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var n1 = selection[0].PathNode;
var n2 = selection[1].PathNode;
if (n1 != null && n2 != null)
{
var link = n1.AddLink(n2);
if (link == null)
{
MessageBox.Show("Failed to join nodes. The nodes are likely too far away!", "Join Failed.", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
link.SetForwardLanesBidirectionally(1);
link.Shortcut = true;
if (n2.TryGetLinkForNode(n1, out var backLink))
{
backLink.Shortcut = true;
}
UpdatePathYndGraphics(n1.Ynd, false);
UpdatePathYndGraphics(n2.Ynd, false);
}
}
@ -6209,6 +6323,17 @@ namespace CodeWalker
{
DeleteItem();
}
if (SelectionMode == MapSelectionMode.Path)
{
if (k == Keys.J)
{
TryCreateNodeLink();
}
if (k == Keys.K)
{
TryCreateNodeShortcut();
}
}
}
else
{