2020-01-08 21:44:35 +08:00
|
|
|
|
using CodeWalker.GameFiles;
|
|
|
|
|
using CodeWalker.Project;
|
|
|
|
|
using CodeWalker.World;
|
|
|
|
|
using SharpDX;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace CodeWalker
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
Audio = 16,
|
|
|
|
|
Occlusion = 17,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
|
|
|
|
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 YmapBoxOccluder BoxOccluder { get; set; }
|
|
|
|
|
public YmapOccludeModel OccludeModel { get; set; }
|
|
|
|
|
public YmapEntityDef MloEntityDef { get; set; }
|
|
|
|
|
public MCMloRoomDef MloRoomDef { get; set; }
|
|
|
|
|
public WaterQuad WaterQuad { get; set; }
|
|
|
|
|
public Bounds CollisionBounds { get; set; }
|
|
|
|
|
public BoundPolygon CollisionPoly { get; set; }
|
|
|
|
|
public BoundVertex CollisionVertex { get; set; }
|
|
|
|
|
public YnvPoly NavPoly { get; set; }
|
|
|
|
|
public YnvPoint NavPoint { get; set; }
|
|
|
|
|
public YnvPortal NavPortal { 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 AudioPlacement Audio { get; set; }
|
|
|
|
|
|
2020-01-09 23:12:16 +08:00
|
|
|
|
public MapSelection[] MultipleSelectionItems { get; private set; }
|
2020-01-08 21:44:35 +08:00
|
|
|
|
public Vector3 MultipleSelectionCenter { get; set; }
|
|
|
|
|
public Quaternion MultipleSelectionRotation { get; set; }
|
|
|
|
|
public Vector3 MultipleSelectionScale { get; set; }
|
2020-01-09 23:12:16 +08:00
|
|
|
|
public BoundVertex[] GatheredCollisionVerts { get; private set; } //for collision polys, need to move all the individual vertices instead
|
2020-01-08 21:44:35 +08:00
|
|
|
|
|
|
|
|
|
public Vector3 BBOffset { get; set; }
|
|
|
|
|
public Quaternion BBOrientation { get; set; }
|
|
|
|
|
public BoundingBox AABB { get; set; }
|
|
|
|
|
public BoundingSphere BSphere { 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) ||
|
|
|
|
|
(CollisionPoly != null) ||
|
|
|
|
|
(CollisionVertex != null) ||
|
|
|
|
|
(NavPoly != null) ||
|
|
|
|
|
(NavPoint != null) ||
|
|
|
|
|
(NavPortal != null) ||
|
|
|
|
|
(PathNode != null) ||
|
|
|
|
|
(TrainTrackNode != null) ||
|
|
|
|
|
(DistantLodLights != null) ||
|
|
|
|
|
(BoxOccluder != null) ||
|
|
|
|
|
(OccludeModel != null) ||
|
|
|
|
|
(MloEntityDef != null) ||
|
|
|
|
|
(ScenarioNode != null) ||
|
|
|
|
|
(Audio != null) ||
|
|
|
|
|
(MloRoomDef != null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool HasHit
|
|
|
|
|
{
|
|
|
|
|
get { return (HitDist != float.MaxValue); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public bool CheckForChanges(MapSelection mhit)
|
|
|
|
|
{
|
|
|
|
|
return (EntityDef != mhit.EntityDef)
|
|
|
|
|
|| (Archetype != mhit.Archetype)
|
|
|
|
|
|| (Drawable != mhit.Drawable)
|
|
|
|
|
|| (TimeCycleModifier != mhit.TimeCycleModifier)
|
|
|
|
|
|| (ArchetypeExtension != mhit.ArchetypeExtension)
|
|
|
|
|
|| (EntityExtension != mhit.EntityExtension)
|
|
|
|
|
|| (CarGenerator != mhit.CarGenerator)
|
|
|
|
|
|| (MloEntityDef != mhit.MloEntityDef)
|
|
|
|
|
|| (DistantLodLights != mhit.DistantLodLights)
|
|
|
|
|
|| (GrassBatch != mhit.GrassBatch)
|
|
|
|
|
|| (BoxOccluder != mhit.BoxOccluder)
|
|
|
|
|
|| (OccludeModel != mhit.OccludeModel)
|
|
|
|
|
|| (WaterQuad != mhit.WaterQuad)
|
|
|
|
|
|| (CollisionBounds != mhit.CollisionBounds)
|
|
|
|
|
|| (CollisionPoly != mhit.CollisionPoly)
|
|
|
|
|
|| (CollisionVertex != mhit.CollisionVertex)
|
|
|
|
|
|| (NavPoly != mhit.NavPoly)
|
|
|
|
|
|| (NavPoint != mhit.NavPoint)
|
|
|
|
|
|| (NavPortal != mhit.NavPortal)
|
|
|
|
|
|| (PathNode != mhit.PathNode)
|
|
|
|
|
|| (TrainTrackNode != mhit.TrainTrackNode)
|
|
|
|
|
|| (ScenarioNode != mhit.ScenarioNode)
|
|
|
|
|
|| (Audio != mhit.Audio)
|
|
|
|
|
|| (MloRoomDef != mhit.MloRoomDef);
|
|
|
|
|
}
|
|
|
|
|
public bool CheckForChanges()
|
|
|
|
|
{
|
|
|
|
|
return (EntityDef != null)
|
|
|
|
|
|| (Archetype != null)
|
|
|
|
|
|| (Drawable != null)
|
|
|
|
|
|| (TimeCycleModifier != null)
|
|
|
|
|
|| (ArchetypeExtension != null)
|
|
|
|
|
|| (EntityExtension != null)
|
|
|
|
|
|| (CarGenerator != null)
|
|
|
|
|
|| (MloEntityDef != null)
|
|
|
|
|
|| (DistantLodLights != null)
|
|
|
|
|
|| (GrassBatch != null)
|
|
|
|
|
|| (BoxOccluder != null)
|
|
|
|
|
|| (OccludeModel != null)
|
|
|
|
|
|| (WaterQuad != null)
|
|
|
|
|
|| (CollisionBounds != null)
|
|
|
|
|
|| (CollisionPoly != null)
|
|
|
|
|
|| (CollisionVertex != null)
|
|
|
|
|
|| (NavPoly != null)
|
|
|
|
|
|| (NavPoint != null)
|
|
|
|
|
|| (NavPortal != null)
|
|
|
|
|
|| (PathNode != null)
|
|
|
|
|
|| (PathLink != null)
|
|
|
|
|
|| (TrainTrackNode != null)
|
|
|
|
|
|| (ScenarioNode != null)
|
|
|
|
|
|| (Audio != null)
|
|
|
|
|
|| (MloRoomDef != null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Clear()
|
|
|
|
|
{
|
|
|
|
|
EntityDef = null;
|
|
|
|
|
Archetype = null;
|
|
|
|
|
Drawable = null;
|
|
|
|
|
Geometry = null;
|
|
|
|
|
EntityExtension = null;
|
|
|
|
|
ArchetypeExtension = null;
|
|
|
|
|
TimeCycleModifier = null;
|
|
|
|
|
CarGenerator = null;
|
|
|
|
|
GrassBatch = null;
|
|
|
|
|
BoxOccluder = null;
|
|
|
|
|
OccludeModel = null;
|
|
|
|
|
WaterQuad = null;
|
|
|
|
|
CollisionBounds = null;
|
|
|
|
|
CollisionPoly = null;
|
|
|
|
|
CollisionVertex = null;
|
|
|
|
|
NavPoly = null;
|
|
|
|
|
NavPoint = null;
|
|
|
|
|
NavPortal = null;
|
|
|
|
|
PathNode = null;
|
|
|
|
|
PathLink = null;
|
|
|
|
|
TrainTrackNode = null;
|
|
|
|
|
DistantLodLights = null;
|
|
|
|
|
MloEntityDef = null;
|
|
|
|
|
ScenarioNode = null;
|
|
|
|
|
ScenarioEdge = null;
|
|
|
|
|
Audio = null;
|
|
|
|
|
MultipleSelectionItems = null;
|
|
|
|
|
MultipleSelectionCenter = Vector3.Zero;
|
|
|
|
|
MultipleSelectionRotation = Quaternion.Identity;
|
|
|
|
|
MultipleSelectionScale = Vector3.One;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
GatheredCollisionVerts = null;
|
2020-01-08 21:44:35 +08:00
|
|
|
|
AABB = new BoundingBox();
|
|
|
|
|
GeometryIndex = 0;
|
|
|
|
|
CamRel = Vector3.Zero;
|
|
|
|
|
HitDist = float.MaxValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetNameString(string defval)
|
|
|
|
|
{
|
|
|
|
|
string name = defval;
|
2020-01-13 20:31:27 +08:00
|
|
|
|
var ename = (EntityDef != null) ? EntityDef._CEntityDef.archetypeName.ToString() : string.Empty;
|
|
|
|
|
var enamec = ename + ((!string.IsNullOrEmpty(ename)) ? ": " : "");
|
2020-01-08 21:44:35 +08:00
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
name = "Multiple items";
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
|
|
|
|
name = enamec + "Vertex " + CollisionVertex.Index.ToString() + ((CollisionBounds != null) ? (": " + CollisionBounds.GetName()) : string.Empty);
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
name = enamec + "Poly " + CollisionPoly.Index.ToString() + ((CollisionBounds != null) ? (": " + CollisionBounds.GetName()) : string.Empty);
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
name = enamec + CollisionBounds.GetName();
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
2020-01-13 20:31:27 +08:00
|
|
|
|
name = ename;
|
2020-01-08 21:44:35 +08:00
|
|
|
|
}
|
|
|
|
|
else if (Archetype != null)
|
|
|
|
|
{
|
|
|
|
|
name = Archetype.Hash.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (TimeCycleModifier != null)
|
|
|
|
|
{
|
|
|
|
|
name = TimeCycleModifier.CTimeCycleModifier.name.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
name = (CarGenerator.Ymap?.Name ?? "") + ": " + CarGenerator.NameString();
|
|
|
|
|
}
|
|
|
|
|
else if (GrassBatch != null)
|
|
|
|
|
{
|
|
|
|
|
name = (GrassBatch.Ymap?.Name ?? "") + ": " + GrassBatch.Archetype?.Name ?? "";
|
|
|
|
|
}
|
|
|
|
|
else if (DistantLodLights != null)
|
|
|
|
|
{
|
|
|
|
|
name = DistantLodLights.Ymap?.Name ?? "";
|
|
|
|
|
}
|
|
|
|
|
else if (BoxOccluder != null)
|
|
|
|
|
{
|
|
|
|
|
name = "BoxOccluder " + (BoxOccluder.Ymap?.Name ?? "") + ": " + BoxOccluder.Index.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (OccludeModel != null)
|
|
|
|
|
{
|
|
|
|
|
name = "OccludeModel " + (OccludeModel.Ymap?.Name ?? "") + ": " + OccludeModel.Index.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (WaterQuad != null)
|
|
|
|
|
{
|
|
|
|
|
name = "WaterQuad " + WaterQuad.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
name = "NavPoly " + NavPoly.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
name = "NavPoint " + NavPoint.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
name = "NavPortal " + NavPortal.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
name = "PathNode " + PathNode.AreaID.ToString() + "." + PathNode.NodeID.ToString(); //+ FloatUtil.GetVector3String(PathNode.Position);
|
|
|
|
|
}
|
|
|
|
|
else if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
name = "TrainTrackNode " + FloatUtil.GetVector3String(TrainTrackNode.Position);
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
name = ScenarioNode.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
name = Audio.ShortTypeName + " " + Audio.GetNameString();// FloatUtil.GetVector3String(Audio.InnerPos);
|
|
|
|
|
}
|
|
|
|
|
if (MloRoomDef != null)
|
|
|
|
|
{
|
|
|
|
|
name = "MloRoomDef " + MloRoomDef.RoomName;
|
|
|
|
|
}
|
|
|
|
|
if (EntityExtension != null)
|
|
|
|
|
{
|
|
|
|
|
name += ": " + EntityExtension.Name;
|
|
|
|
|
}
|
|
|
|
|
if (ArchetypeExtension != null)
|
|
|
|
|
{
|
|
|
|
|
name += ": " + ArchetypeExtension.Name;
|
|
|
|
|
}
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string GetFullNameString(string defval)
|
|
|
|
|
{
|
|
|
|
|
string name = GetNameString(defval);
|
|
|
|
|
if (Geometry != null)
|
|
|
|
|
{
|
|
|
|
|
name += " (" + GeometryIndex.ToString() + ")";
|
|
|
|
|
}
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public bool CanMarkUndo()
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null) return true;
|
|
|
|
|
if (EntityDef != null) return true;
|
|
|
|
|
if (CarGenerator != null) return true;
|
|
|
|
|
if (CollisionBounds != null) return true;
|
|
|
|
|
if (CollisionPoly != null) return true;
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (CollisionVertex != null) return true;
|
2020-01-08 21:44:35 +08:00
|
|
|
|
if (PathNode != null) return true;
|
|
|
|
|
//if (NavPoly != null) return true;
|
|
|
|
|
if (NavPoint != null) return true;
|
|
|
|
|
if (NavPortal != null) return true;
|
|
|
|
|
if (TrainTrackNode != null) return true;
|
|
|
|
|
if (ScenarioNode != null) return true;
|
|
|
|
|
if (Audio != null) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
public UndoStep CreateUndoStep(WidgetMode mode, Vector3 startPos, Quaternion startRot, Vector3 startScale, WorldForm wf, bool editPivot)
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new MultiPositionUndoStep(this, startPos, wf);
|
|
|
|
|
case WidgetMode.Rotation: return new MultiRotationUndoStep(this, startRot, wf);
|
|
|
|
|
case WidgetMode.Scale: return new MultiScaleUndoStep(this, startScale, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new CollisionVertexPositionUndoStep(CollisionVertex, EntityDef, startPos, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new CollisionPolyPositionUndoStep(CollisionPoly, EntityDef, startPos, wf);
|
|
|
|
|
case WidgetMode.Rotation: return new CollisionPolyRotationUndoStep(CollisionPoly, EntityDef, startRot, wf);
|
|
|
|
|
case WidgetMode.Scale: return new CollisionPolyScaleUndoStep(CollisionPoly, startScale, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new CollisionPositionUndoStep(CollisionBounds, EntityDef, startPos, wf);
|
|
|
|
|
case WidgetMode.Rotation: return new CollisionRotationUndoStep(CollisionBounds, EntityDef, startRot, wf);
|
|
|
|
|
case WidgetMode.Scale: return new CollisionScaleUndoStep(CollisionBounds, startScale, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
if (editPivot)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new EntityPivotPositionUndoStep(EntityDef, startPos);
|
|
|
|
|
case WidgetMode.Rotation: return new EntityPivotRotationUndoStep(EntityDef, startRot);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new EntityPositionUndoStep(EntityDef, startPos);
|
|
|
|
|
case WidgetMode.Rotation: return new EntityRotationUndoStep(EntityDef, startRot);
|
|
|
|
|
case WidgetMode.Scale: return new EntityScaleUndoStep(EntityDef, startScale);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new CarGenPositionUndoStep(CarGenerator, startPos);
|
|
|
|
|
case WidgetMode.Rotation: return new CarGenRotationUndoStep(CarGenerator, startRot);
|
|
|
|
|
case WidgetMode.Scale: return new CarGenScaleUndoStep(CarGenerator, startScale);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new PathNodePositionUndoStep(PathNode, startPos, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
//todo...
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new NavPointPositionUndoStep(NavPoint, startPos, wf);
|
|
|
|
|
case WidgetMode.Rotation: return new NavPointRotationUndoStep(NavPoint, startRot, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new NavPortalPositionUndoStep(NavPortal, startPos, wf);
|
|
|
|
|
case WidgetMode.Rotation: return new NavPortalRotationUndoStep(NavPortal, startRot, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new TrainTrackNodePositionUndoStep(TrainTrackNode, startPos, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new ScenarioNodePositionUndoStep(ScenarioNode, startPos, wf);
|
|
|
|
|
case WidgetMode.Rotation: return new ScenarioNodeRotationUndoStep(ScenarioNode, startRot, wf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case WidgetMode.Position: return new AudioPositionUndoStep(Audio, startPos);
|
|
|
|
|
case WidgetMode.Rotation: return new AudioRotationUndoStep(Audio, startRot);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool CanShowWidget
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
bool res = false;
|
|
|
|
|
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
res = true;
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public Vector3 WidgetPosition
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
return MultipleSelectionCenter;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (EntityDef != null) return EntityDef.Position + EntityDef.Orientation.Multiply(CollisionVertex.Position);
|
2020-01-08 21:44:35 +08:00
|
|
|
|
return CollisionVertex.Position;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (EntityDef != null) return EntityDef.Position + EntityDef.Orientation.Multiply(CollisionPoly.Position);
|
2020-01-08 21:44:35 +08:00
|
|
|
|
return CollisionPoly.Position;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (EntityDef != null) return EntityDef.Position + EntityDef.Orientation.Multiply(CollisionBounds.Position);
|
2020-01-08 21:44:35 +08:00
|
|
|
|
return CollisionBounds.Position;
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
return EntityDef.WidgetPosition;
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
return CarGenerator.Position;
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
return NavPoly.Position;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
return NavPoint.Position;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
return NavPortal.Position;
|
|
|
|
|
}
|
|
|
|
|
else if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
return PathNode.Position;
|
|
|
|
|
}
|
|
|
|
|
else if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
return TrainTrackNode.Position;
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
return ScenarioNode.Position;
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
return Audio.InnerPos;
|
|
|
|
|
}
|
|
|
|
|
return Vector3.Zero;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public Quaternion WidgetRotation
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
return MultipleSelectionRotation;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (EntityDef != null) return EntityDef.Orientation;
|
2020-01-08 21:44:35 +08:00
|
|
|
|
return Quaternion.Identity;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (EntityDef != null) return CollisionPoly.Orientation * EntityDef.Orientation;
|
2020-01-08 21:44:35 +08:00
|
|
|
|
return CollisionPoly.Orientation;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (EntityDef != null) return CollisionBounds.Orientation * EntityDef.Orientation;
|
2020-01-08 21:44:35 +08:00
|
|
|
|
return CollisionBounds.Orientation;
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
return EntityDef.WidgetOrientation;
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
return CarGenerator.Orientation;
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
return Quaternion.Identity;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
return NavPoint.Orientation;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
return NavPortal.Orientation;
|
|
|
|
|
}
|
|
|
|
|
else if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
return Quaternion.Identity;
|
|
|
|
|
}
|
|
|
|
|
else if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
return Quaternion.Identity;
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
return ScenarioNode.Orientation;
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
return Audio.Orientation;
|
|
|
|
|
}
|
|
|
|
|
return Quaternion.Identity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public WidgetAxis WidgetRotationAxes
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.XYZ;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.None;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.XYZ;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.XYZ;
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.XYZ;
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.Z;
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.XYZ;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.Z;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.Z;
|
|
|
|
|
}
|
|
|
|
|
else if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.None;
|
|
|
|
|
}
|
|
|
|
|
else if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.None;
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.Z;
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
return WidgetAxis.Z;
|
|
|
|
|
}
|
|
|
|
|
return WidgetAxis.None;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public Vector3 WidgetScale
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
return MultipleSelectionScale;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
return CollisionPoly.Scale;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
return CollisionBounds.Scale;
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
return EntityDef.Scale;
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
return new Vector3(CarGenerator.CCarGen.perpendicularLength);
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
else if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
else if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
return Vector3.One;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public bool WidgetScaleLockXY
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2020-01-09 23:12:16 +08:00
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < MultipleSelectionItems.Length; i++)
|
|
|
|
|
{
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if ((MultipleSelectionItems[i].EntityDef != null) && (MultipleSelectionItems[i].CollisionBounds == null)) return true;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-12 16:25:41 +08:00
|
|
|
|
public bool CanCopyPaste
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < MultipleSelectionItems.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems[i].CanCopyPaste) return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (CollisionVertex != null) return false;//can't copy just a vertex..
|
|
|
|
|
else if (CollisionPoly != null) return true;
|
|
|
|
|
else if (CollisionBounds != null) return true;
|
2020-01-12 16:25:41 +08:00
|
|
|
|
else if (EntityDef != null) return true;
|
|
|
|
|
else if (CarGenerator != null) return true;
|
|
|
|
|
else if (PathNode != null) return true;
|
|
|
|
|
else if (NavPoly != null) return true;
|
|
|
|
|
else if (NavPoint != null) return true;
|
|
|
|
|
else if (NavPortal != null) return true;
|
|
|
|
|
else if (TrainTrackNode != null) return true;
|
|
|
|
|
else if (ScenarioNode != null) return true;
|
|
|
|
|
else if (Audio?.AudioZone != null) return true;
|
|
|
|
|
else if (Audio?.AudioEmitter != null) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
|
|
|
|
|
|
2020-01-09 23:12:16 +08:00
|
|
|
|
public void SetMultipleSelectionItems(MapSelection[] items)
|
|
|
|
|
{
|
|
|
|
|
if ((items != null) && (items.Length == 0)) items = null;
|
|
|
|
|
MultipleSelectionItems = items;
|
|
|
|
|
GatheredCollisionVerts = null;
|
|
|
|
|
var center = Vector3.Zero;
|
|
|
|
|
if (items != null)
|
|
|
|
|
{
|
|
|
|
|
Dictionary<BoundVertex, int> collVerts = null;
|
|
|
|
|
for (int i = 0; i < items.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
center += items[i].WidgetPosition;
|
2020-01-14 10:52:22 +08:00
|
|
|
|
var collVert = items[i].CollisionVertex;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
var collPoly = items[i].CollisionPoly;
|
2020-01-14 10:52:22 +08:00
|
|
|
|
if (collVert != null)
|
|
|
|
|
{
|
|
|
|
|
if (collVerts == null) collVerts = new Dictionary<BoundVertex, int>();
|
|
|
|
|
collVerts[collVert] = collVert.Index;
|
|
|
|
|
}
|
|
|
|
|
else if (collPoly != null)
|
2020-01-09 23:12:16 +08:00
|
|
|
|
{
|
|
|
|
|
if (collVerts == null) collVerts = new Dictionary<BoundVertex, int>();
|
|
|
|
|
collPoly.GatherVertices(collVerts);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (collVerts != null)
|
|
|
|
|
{
|
|
|
|
|
GatheredCollisionVerts = collVerts.Keys.ToArray();
|
|
|
|
|
}
|
|
|
|
|
if (items.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
center *= (1.0f / items.Length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MultipleSelectionCenter = center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-01-08 21:44:35 +08:00
|
|
|
|
public void SetPosition(Vector3 newpos, bool editPivot)
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
if (editPivot)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var dpos = newpos - MultipleSelectionCenter;// oldpos;
|
|
|
|
|
if (dpos == Vector3.Zero) return; //nothing moved.. (probably due to snap)
|
2020-01-13 20:31:27 +08:00
|
|
|
|
YmapEntityDef ent = null;//hack to use an entity for multple selections... buggy if entities mismatch!!!
|
2020-01-08 21:44:35 +08:00
|
|
|
|
for (int i = 0; i < MultipleSelectionItems.Length; i++)
|
|
|
|
|
{
|
2020-01-14 10:52:22 +08:00
|
|
|
|
var collVert = MultipleSelectionItems[i].CollisionVertex;
|
|
|
|
|
var collPoly = MultipleSelectionItems[i].CollisionPoly;
|
|
|
|
|
if ((collVert == null) && (collPoly == null))//skip polys, they use gathered verts
|
2020-01-09 23:12:16 +08:00
|
|
|
|
{
|
|
|
|
|
var refpos = MultipleSelectionItems[i].WidgetPosition;
|
|
|
|
|
MultipleSelectionItems[i].SetPosition(refpos + dpos, false);
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
ent = MultipleSelectionItems[i].EntityDef ?? ent;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (ent != null) dpos = Quaternion.Invert(ent.Orientation).Multiply(dpos);
|
2020-01-09 23:12:16 +08:00
|
|
|
|
if (GatheredCollisionVerts != null)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < GatheredCollisionVerts.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var refpos = GatheredCollisionVerts[i].Position;
|
2020-01-13 20:31:27 +08:00
|
|
|
|
var vnewpos = refpos + dpos;
|
|
|
|
|
GatheredCollisionVerts[i].Position = vnewpos;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
}
|
|
|
|
|
MultipleSelectionCenter = newpos;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
|
|
|
|
if (EntityDef != null) newpos = Quaternion.Invert(EntityDef.Orientation).Multiply(newpos - EntityDef.Position);
|
|
|
|
|
CollisionVertex.Position = newpos;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
if (EntityDef != null) newpos = Quaternion.Invert(EntityDef.Orientation).Multiply(newpos - EntityDef.Position);
|
|
|
|
|
CollisionPoly.Position = newpos;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
if (EntityDef != null) newpos = Quaternion.Invert(EntityDef.Orientation).Multiply(newpos - EntityDef.Position);
|
|
|
|
|
CollisionBounds.Position = newpos;
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
if (editPivot)
|
|
|
|
|
{
|
|
|
|
|
EntityDef.SetPivotPositionFromWidget(newpos);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
EntityDef.SetPositionFromWidget(newpos);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
CarGenerator.SetPosition(newpos);
|
|
|
|
|
}
|
|
|
|
|
else if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
PathNode.SetPosition(newpos);
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
NavPoly.SetPosition(newpos);
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
NavPoint.SetPosition(newpos);
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
NavPortal.SetPosition(newpos);
|
|
|
|
|
}
|
|
|
|
|
else if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
TrainTrackNode.SetPosition(newpos);
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
ScenarioNode.SetPosition(newpos);
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
Audio.SetPosition(newpos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public void SetRotation(Quaternion newrot, bool editPivot)
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
if (editPivot)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var cen = MultipleSelectionCenter;
|
|
|
|
|
var orinv = Quaternion.Invert(MultipleSelectionRotation);
|
|
|
|
|
var trans = newrot * orinv;
|
2020-01-13 20:31:27 +08:00
|
|
|
|
YmapEntityDef ent = null;//hack to use an entity for multple selections... buggy if entities mismatch!!!
|
2020-01-08 21:44:35 +08:00
|
|
|
|
for (int i = 0; i < MultipleSelectionItems.Length; i++)
|
|
|
|
|
{
|
2020-01-14 10:52:22 +08:00
|
|
|
|
var collVert = MultipleSelectionItems[i].CollisionVertex;
|
|
|
|
|
var collPoly = MultipleSelectionItems[i].CollisionPoly;
|
|
|
|
|
if ((collVert == null) && (collPoly == null))//skip polys, they use gathered verts
|
2020-01-09 23:12:16 +08:00
|
|
|
|
{
|
|
|
|
|
var refpos = MultipleSelectionItems[i].WidgetPosition;
|
|
|
|
|
var relpos = refpos - cen;
|
|
|
|
|
var newpos = trans.Multiply(relpos) + cen;
|
|
|
|
|
var refori = MultipleSelectionItems[i].WidgetRotation;
|
|
|
|
|
var newori = trans * refori;
|
|
|
|
|
MultipleSelectionItems[i].SetPosition(newpos, false);
|
|
|
|
|
MultipleSelectionItems[i].SetRotation(newori, false);
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
ent = MultipleSelectionItems[i].EntityDef ?? ent;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
var eorinv = (ent != null) ? Quaternion.Invert(ent.Orientation) : Quaternion.Identity;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
if (GatheredCollisionVerts != null)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < GatheredCollisionVerts.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var refpos = GatheredCollisionVerts[i].Position;
|
|
|
|
|
var relpos = refpos - cen;
|
|
|
|
|
var newpos = trans.Multiply(relpos) + cen;
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (ent != null)
|
|
|
|
|
{
|
|
|
|
|
refpos = ent.Position + ent.Orientation.Multiply(refpos);
|
|
|
|
|
relpos = refpos - cen;
|
|
|
|
|
newpos = eorinv.Multiply(trans.Multiply(relpos) + cen - ent.Position);
|
|
|
|
|
}
|
2020-01-09 23:12:16 +08:00
|
|
|
|
GatheredCollisionVerts[i].Position = newpos;
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
}
|
|
|
|
|
MultipleSelectionRotation = newrot;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
|
|
|
|
//do nothing, but stop any poly from being rotated also
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
if (EntityDef != null) newrot = Quaternion.Normalize(Quaternion.Invert(EntityDef.Orientation) * newrot);
|
|
|
|
|
CollisionPoly.Orientation = newrot;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
if (EntityDef != null) newrot = Quaternion.Normalize(Quaternion.Invert(EntityDef.Orientation) * newrot);
|
|
|
|
|
CollisionBounds.Orientation = newrot;
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
if (editPivot)
|
|
|
|
|
{
|
|
|
|
|
EntityDef.SetPivotOrientationFromWidget(newrot);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
EntityDef.SetOrientationFromWidget(newrot);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
CarGenerator.SetOrientation(newrot);
|
|
|
|
|
}
|
|
|
|
|
else if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
ScenarioNode.SetOrientation(newrot);
|
|
|
|
|
}
|
|
|
|
|
else if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
NavPoint.SetOrientation(newrot);
|
|
|
|
|
}
|
|
|
|
|
else if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
NavPortal.SetOrientation(newrot);
|
|
|
|
|
}
|
|
|
|
|
else if (Audio != null)
|
|
|
|
|
{
|
|
|
|
|
Audio.SetOrientation(newrot);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void SetScale(Vector3 newscale, bool editPivot)
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
if (editPivot)
|
|
|
|
|
{//editing pivot scale is sort of meaningless..
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var cen = MultipleSelectionCenter;
|
|
|
|
|
var ori = MultipleSelectionRotation;
|
|
|
|
|
var orinv = Quaternion.Invert(ori);
|
|
|
|
|
var rsca = newscale / MultipleSelectionScale;
|
2020-01-13 20:31:27 +08:00
|
|
|
|
YmapEntityDef ent = null;//hack to use an entity for multple selections... buggy if entities mismatch!!!
|
2020-01-08 21:44:35 +08:00
|
|
|
|
for (int i = 0; i < MultipleSelectionItems.Length; i++)
|
|
|
|
|
{
|
2020-01-14 10:52:22 +08:00
|
|
|
|
var collVert = MultipleSelectionItems[i].CollisionVertex;
|
|
|
|
|
var collPoly = MultipleSelectionItems[i].CollisionPoly;
|
|
|
|
|
if ((collVert == null) && (collPoly == null))//skip polys, they use gathered verts
|
2020-01-09 23:12:16 +08:00
|
|
|
|
{
|
|
|
|
|
var refpos = MultipleSelectionItems[i].WidgetPosition;
|
|
|
|
|
var relpos = refpos - cen;
|
|
|
|
|
var newpos = ori.Multiply(orinv.Multiply(relpos) * rsca) + cen;
|
|
|
|
|
MultipleSelectionItems[i].SetPosition(newpos, false);
|
|
|
|
|
MultipleSelectionItems[i].SetScale(newscale, false);
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
ent = MultipleSelectionItems[i].EntityDef ?? ent;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
var eorinv = (ent != null) ? Quaternion.Invert(ent.Orientation) : Quaternion.Identity;
|
2020-01-09 23:12:16 +08:00
|
|
|
|
if (GatheredCollisionVerts != null)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < GatheredCollisionVerts.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var refpos = GatheredCollisionVerts[i].Position;
|
|
|
|
|
var relpos = refpos - cen;
|
|
|
|
|
var newpos = ori.Multiply(orinv.Multiply(relpos) * rsca) + cen;
|
2020-01-13 20:31:27 +08:00
|
|
|
|
if (ent != null)
|
|
|
|
|
{
|
|
|
|
|
refpos = ent.Position + ent.Orientation.Multiply(refpos);
|
|
|
|
|
relpos = refpos - cen;
|
|
|
|
|
newpos = ori.Multiply(orinv.Multiply(relpos) * rsca) + cen;
|
|
|
|
|
newpos = eorinv.Multiply(newpos - ent.Position);
|
|
|
|
|
}
|
2020-01-09 23:12:16 +08:00
|
|
|
|
GatheredCollisionVerts[i].Position = newpos;
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
}
|
|
|
|
|
MultipleSelectionScale = newscale;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-09 23:12:16 +08:00
|
|
|
|
else if (CollisionVertex != null)
|
|
|
|
|
{
|
|
|
|
|
//do nothing, but stop any poly from being scaled also
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
else if (CollisionPoly != null)
|
|
|
|
|
{
|
|
|
|
|
CollisionPoly.Scale = newscale;
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
CollisionBounds.Scale = newscale;
|
|
|
|
|
}
|
2020-01-13 20:31:27 +08:00
|
|
|
|
else if (EntityDef != null)
|
|
|
|
|
{
|
|
|
|
|
EntityDef.SetScale(newscale);
|
|
|
|
|
}
|
|
|
|
|
else if (CarGenerator != null)
|
|
|
|
|
{
|
|
|
|
|
CarGenerator.SetScale(newscale);
|
|
|
|
|
AABB = new BoundingBox(CarGenerator.BBMin, CarGenerator.BBMax);
|
|
|
|
|
}
|
2020-01-08 21:44:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-01-10 20:41:58 +08:00
|
|
|
|
|
|
|
|
|
public void UpdateCollisionFromRayHit(ref SpaceRayIntersectResult hit, Camera camera)
|
|
|
|
|
{
|
|
|
|
|
var position = hit.HitEntity?.Position ?? Vector3.Zero;
|
|
|
|
|
var orientation = hit.HitEntity?.Orientation ?? Quaternion.Identity;
|
|
|
|
|
var scale = hit.HitEntity?.Scale ?? Vector3.One;
|
|
|
|
|
var camrel = position - camera.Position;
|
|
|
|
|
var trans = hit.HitBounds?.Transform.TranslationVector ?? Vector3.Zero;
|
|
|
|
|
|
|
|
|
|
CollisionPoly = hit.HitPolygon;
|
|
|
|
|
CollisionBounds = hit.HitBounds;
|
|
|
|
|
EntityDef = hit.HitEntity;
|
|
|
|
|
Archetype = hit.HitEntity?.Archetype;
|
|
|
|
|
HitDist = hit.HitDist;
|
|
|
|
|
CamRel = camrel + orientation.Multiply(trans);
|
|
|
|
|
BBOffset = trans;
|
|
|
|
|
BBOrientation = hit.HitBounds?.Transform.ToQuaternion() ?? Quaternion.Identity;
|
|
|
|
|
AABB = new BoundingBox(hit.HitBounds?.BoxMin ?? Vector3.Zero, hit.HitBounds?.BoxMax ?? Vector3.Zero);
|
|
|
|
|
|
|
|
|
|
float vertexDist = 0.1f;
|
|
|
|
|
if ((hit.HitVertex.Distance < vertexDist) && (hit.HitBounds is BoundGeometry bgeom))
|
|
|
|
|
{
|
|
|
|
|
CollisionVertex = bgeom.GetVertexObject(hit.HitVertex.Index);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CollisionVertex = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-01-14 10:26:38 +08:00
|
|
|
|
|
|
|
|
|
public void UpdateGraphics(WorldForm wf)
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null)
|
|
|
|
|
{
|
|
|
|
|
Dictionary<YndFile, int> pathYnds = new Dictionary<YndFile, int>();
|
|
|
|
|
Dictionary<YnvFile, int> navYnvs = new Dictionary<YnvFile, int>();
|
|
|
|
|
Dictionary<TrainTrack, int> trainTracks = new Dictionary<TrainTrack, int>();
|
|
|
|
|
Dictionary<YmtFile, int> scenarioYmts = new Dictionary<YmtFile, int>();
|
|
|
|
|
Dictionary<Bounds, int> bounds = new Dictionary<Bounds, int>();
|
|
|
|
|
|
|
|
|
|
foreach (var item in MultipleSelectionItems)
|
|
|
|
|
{
|
|
|
|
|
if (item.PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
pathYnds[item.PathNode.Ynd] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (item.NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
navYnvs[item.NavPoly.Ynv] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (item.NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
navYnvs[item.NavPoint.Ynv] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (item.NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
navYnvs[item.NavPortal.Ynv] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (item.TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
trainTracks[item.TrainTrackNode.Track] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (item.ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
scenarioYmts[item.ScenarioNode.Ymt] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (item.CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
bounds[item.CollisionBounds] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (item.CollisionPoly?.Owner != null)
|
|
|
|
|
{
|
|
|
|
|
bounds[item.CollisionPoly.Owner] = 1;
|
|
|
|
|
}
|
|
|
|
|
if (item.CollisionVertex?.Owner != null)
|
|
|
|
|
{
|
|
|
|
|
bounds[item.CollisionVertex.Owner] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
foreach (var kvp in bounds)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateCollisionBoundsGraphics(kvp.Key);
|
|
|
|
|
}
|
|
|
|
|
foreach (var kvp in pathYnds)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdatePathYndGraphics(kvp.Key, true);
|
|
|
|
|
}
|
|
|
|
|
foreach (var kvp in navYnvs)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateNavYnvGraphics(kvp.Key, true);
|
|
|
|
|
}
|
|
|
|
|
foreach (var kvp in trainTracks)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateTrainTrackGraphics(kvp.Key, false);
|
|
|
|
|
}
|
|
|
|
|
foreach (var kvp in scenarioYmts)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateScenarioGraphics(kvp.Key, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (PathNode != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdatePathYndGraphics(PathNode.Ynd, true);
|
|
|
|
|
}
|
|
|
|
|
if (NavPoly != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateNavYnvGraphics(NavPoly.Ynv, true);
|
|
|
|
|
}
|
|
|
|
|
if (NavPoint != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateNavYnvGraphics(NavPoint.Ynv, true);
|
|
|
|
|
}
|
|
|
|
|
if (NavPortal != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateNavYnvGraphics(NavPortal.Ynv, true);
|
|
|
|
|
}
|
|
|
|
|
if (TrainTrackNode != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateTrainTrackGraphics(TrainTrackNode.Track, false);
|
|
|
|
|
}
|
|
|
|
|
if (ScenarioNode != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateScenarioGraphics(ScenarioNode.Ymt, false);
|
|
|
|
|
}
|
|
|
|
|
if (CollisionVertex?.Owner != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateCollisionBoundsGraphics(CollisionVertex.Owner);
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionPoly?.Owner != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateCollisionBoundsGraphics(CollisionPoly.Owner);
|
|
|
|
|
}
|
|
|
|
|
else if (CollisionBounds != null)
|
|
|
|
|
{
|
|
|
|
|
wf.UpdateCollisionBoundsGraphics(CollisionBounds);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-01-14 14:56:11 +08:00
|
|
|
|
public object GetProjectObject()
|
|
|
|
|
{
|
|
|
|
|
if (MultipleSelectionItems != null) return MultipleSelectionItems;
|
|
|
|
|
else if (CollisionVertex != null) return CollisionVertex;
|
|
|
|
|
else if (CollisionPoly != null) return CollisionPoly;
|
|
|
|
|
else if (CollisionBounds != null) return CollisionBounds;
|
|
|
|
|
else if (EntityDef != null) return EntityDef;
|
|
|
|
|
else if (CarGenerator != null) return CarGenerator;
|
|
|
|
|
else if (PathNode != null) return PathNode;
|
|
|
|
|
else if (NavPoly != null) return NavPoly;
|
|
|
|
|
else if (NavPoint != null) return NavPoint;
|
|
|
|
|
else if (NavPortal != null) return NavPortal;
|
|
|
|
|
else if (TrainTrackNode != null) return TrainTrackNode;
|
|
|
|
|
else if (ScenarioNode != null) return ScenarioNode;
|
|
|
|
|
else if (Audio?.AudioZone != null) return Audio;
|
|
|
|
|
else if (Audio?.AudioEmitter != null) return Audio;
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-15 14:48:27 +08:00
|
|
|
|
public static MapSelection FromProjectObject(object o, object parent = null)
|
|
|
|
|
{
|
|
|
|
|
const float nrad = 0.5f;
|
|
|
|
|
var ms = new MapSelection();
|
2020-01-15 16:00:19 +08:00
|
|
|
|
if (o is object[] arr)
|
|
|
|
|
{
|
|
|
|
|
var multi = new MapSelection[arr.Length];
|
|
|
|
|
for (int i = 0; i < arr.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
multi[i] = FromProjectObject(arr[i]);
|
|
|
|
|
}
|
|
|
|
|
ms.SetMultipleSelectionItems(multi);
|
|
|
|
|
}
|
|
|
|
|
else if (o is YmapEntityDef entity)
|
2020-01-15 14:48:27 +08:00
|
|
|
|
{
|
|
|
|
|
ms.EntityDef = entity;
|
|
|
|
|
ms.Archetype = entity?.Archetype;
|
|
|
|
|
ms.AABB = new BoundingBox(entity.BBMin, entity.BBMax);
|
|
|
|
|
if (entity.MloInstance != null)
|
|
|
|
|
{
|
|
|
|
|
ms.MloEntityDef = entity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (o is YmapCarGen cargen)
|
|
|
|
|
{
|
|
|
|
|
ms.CarGenerator = cargen;
|
|
|
|
|
ms.AABB = new BoundingBox(cargen.BBMin, cargen.BBMax);
|
|
|
|
|
}
|
|
|
|
|
else if (o is YmapGrassInstanceBatch batch)
|
|
|
|
|
{
|
|
|
|
|
ms.GrassBatch = batch;
|
|
|
|
|
ms.AABB = new BoundingBox(batch.AABBMin, batch.AABBMax);
|
|
|
|
|
}
|
|
|
|
|
else if (o is MCMloRoomDef room)
|
|
|
|
|
{
|
|
|
|
|
if (parent is MloInstanceData instance)
|
|
|
|
|
{
|
|
|
|
|
ms.MloRoomDef = room;
|
|
|
|
|
ms.AABB = new BoundingBox(room.BBMin_CW, room.BBMax_CW);
|
|
|
|
|
ms.BBOffset = instance.Owner.Position;
|
|
|
|
|
ms.BBOrientation = instance.Owner.Orientation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (o is Bounds b)
|
|
|
|
|
{
|
|
|
|
|
ms.CollisionBounds = b;
|
|
|
|
|
ms.AABB = new BoundingBox(b.BoxMin, b.BoxMax);
|
|
|
|
|
}
|
|
|
|
|
else if (o is BoundPolygon p)
|
|
|
|
|
{
|
|
|
|
|
ms.CollisionPoly = p;
|
|
|
|
|
//ms.AABB = new BoundingBox(p.BoundingBoxMin, p.BoundingBoxMax);
|
|
|
|
|
}
|
|
|
|
|
else if (o is BoundVertex v)
|
|
|
|
|
{
|
|
|
|
|
ms.CollisionVertex = v;
|
|
|
|
|
//ms.AABB = new BoundingBox(p.BoundingBoxMin, p.BoundingBoxMax);
|
|
|
|
|
}
|
|
|
|
|
else if (o is YnvPoly poly)
|
|
|
|
|
{
|
|
|
|
|
var cellaabb = poly._RawData.CellAABB;
|
|
|
|
|
var sect = poly.Ynv?.Nav?.SectorTree;
|
|
|
|
|
ms.NavPoly = poly;
|
|
|
|
|
ms.AABB = new BoundingBox(cellaabb.Min, cellaabb.Max);
|
|
|
|
|
//if (sect != null)
|
|
|
|
|
//{
|
|
|
|
|
// ms.AABB = new BoundingBox(sect.AABBMin.XYZ(), sect.AABBMax.XYZ());
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
else if (o is YnvPoint point)
|
|
|
|
|
{
|
|
|
|
|
ms.NavPoint = point;
|
|
|
|
|
ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad));
|
|
|
|
|
}
|
|
|
|
|
else if (o is YnvPortal portal)
|
|
|
|
|
{
|
|
|
|
|
ms.NavPortal = portal;
|
|
|
|
|
ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad));
|
|
|
|
|
}
|
|
|
|
|
else if (o is YndNode node)
|
|
|
|
|
{
|
|
|
|
|
ms.PathNode = node;
|
|
|
|
|
ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad));
|
|
|
|
|
}
|
|
|
|
|
else if (o is YndLink link)
|
|
|
|
|
{
|
|
|
|
|
ms.PathNode = link.Node1;
|
|
|
|
|
ms.PathLink = link;
|
|
|
|
|
ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad));
|
|
|
|
|
}
|
|
|
|
|
else if (o is TrainTrackNode tnode)
|
|
|
|
|
{
|
|
|
|
|
ms.TrainTrackNode = tnode;
|
|
|
|
|
ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad));
|
|
|
|
|
}
|
|
|
|
|
else if (o is ScenarioNode snode)
|
|
|
|
|
{
|
|
|
|
|
ms.ScenarioNode = snode;
|
|
|
|
|
ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad));
|
|
|
|
|
}
|
|
|
|
|
else if (o is MCScenarioChainingEdge sedge)
|
|
|
|
|
{
|
|
|
|
|
if (parent is ScenarioNode enode)
|
|
|
|
|
{
|
|
|
|
|
ms.ScenarioNode = enode;
|
|
|
|
|
ms.ScenarioEdge = sedge;
|
|
|
|
|
ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (o is AudioPlacement audio)
|
|
|
|
|
{
|
|
|
|
|
ms.Audio = audio;
|
|
|
|
|
ms.AABB = new BoundingBox(audio.HitboxMin, audio.HitboxMax);
|
|
|
|
|
ms.BSphere = new BoundingSphere(audio.Position, audio.HitSphereRad);
|
|
|
|
|
}
|
|
|
|
|
return ms;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-14 10:26:38 +08:00
|
|
|
|
|
|
|
|
|
|
2020-01-08 21:44:35 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return GetFullNameString("[Empty]");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|