Files
sbox-public/engine/Sandbox.Tools/MapEditor/MapDoc/Nodes/MapNode.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

225 lines
4.6 KiB
C#

using Editor.MapEditor;
using NativeMapDoc;
using System;
using System.ComponentModel.DataAnnotations;
namespace Editor.MapDoc;
internal enum MapNodeGetRootDocument
{
/// <summary>
/// Will return null if the root document is still being loaded
/// </summary>
MustBeLoaded = 0,
/// <summary>
/// Will return the root document even if it is not completely loaded
/// </summary>
MayBeLoading = 1
};
/// <summary>
/// A common class used for all objects in the world object tree.
/// </summary>
[Display( Name = "Node" ), Icon( "help_outline" )]
public class MapNode : IHandle
{
#region IHandle
//
// A pointer to the actual native object
//
internal CMapNode native;
//
// IHandle implementation
//
void IHandle.HandleInit( IntPtr ptr ) => OnNativeInit( ptr );
void IHandle.HandleDestroy() => OnNativeDestroy();
bool IHandle.HandleValid() => !native.IsNull;
#endregion
internal MapNode() { }
internal MapNode( HandleCreationData _ ) { }
internal string GizmoId;
internal virtual void OnNativeInit( CMapNode ptr )
{
native = ptr;
GizmoId = Guid.NewGuid().ToString( "N" )[0..8];
}
internal virtual void OnNativeDestroy()
{
native = IntPtr.Zero;
}
/// <summary>
/// A new node has been added to the world - does not happen when loaded from file
/// </summary>
internal virtual void OnAddedToWorld( MapWorld world )
{
}
internal virtual void OnRemovedFromWorld( MapWorld world )
{
}
internal virtual void PreSaveToFile()
{
}
internal virtual void PostLoadFromFile()
{
}
internal virtual void OnNativeTransformChanged( Vector3 position, Angles angle, Vector3 scale )
{
}
internal virtual void OnSetEnabled( bool enabled )
{
}
internal virtual void GetMimeData( DragData data )
{
}
internal virtual void OnCopyFrom( MapNode copyFrom, int flags )
{
}
internal virtual void OnParentChanged( MapNode parent )
{
}
/// <summary>
/// User specified name of this node
/// </summary>
public string Name
{
get => native.GetName();
set
{
Assert.NotNull( value );
native.SetName( value );
}
}
/// <summary>
/// Native C++ type name for this map node (nice for debug, might disappear at some point)
/// </summary>
public string TypeString => native.GetTypeString();
/// <summary>
/// World position of this map node.
/// </summary>
public Vector3 Position
{
get => native.GetOrigin();
set => native.SetOrigin( value );
}
/// <summary>
/// Euler angles of this map node.
/// </summary>
public Angles Angles
{
get => native.GetAngles();
set => native.SetAngles( value );
}
/// <summary>
/// Non-uniform scalar for this map node.
/// </summary>
public Vector3 Scale
{
get => native.GetScales();
set => native.SetScales( value );
}
/// <summary>
/// The parent node, at the top level this will be the <see cref="MapWorld"/>
/// </summary>
public MapNode Parent
{
get => native.GetParent();
set => native.SetParent( value );
}
/// <summary>
/// Each MapNode can have many children. Children usually transform with their parents, etc.
/// </summary>
public IEnumerable<MapNode> Children
{
get
{
// TODO: Ideally we'd have a List<MapNode> in managed that gets updated from hooks, but getting that from mapdoclib is a huge pain.
for ( int i = 0; i < native.GetChildCount(); i++ )
{
yield return native.GetChild( i );
}
}
}
/// <summary>
/// Visibility of this MapNode, e.g if it's been hidden by the user
/// </summary>
public bool Visible
{
get => native.IsVisible();
set => native.SetVisible( value );
}
/// <summary>
/// The world this map node belongs to.
/// </summary>
public MapWorld World
{
get => native.GetParentWorld();
}
/// <summary>
/// Map node types implement this to describe themselves and their children.
/// e.g CMapEntity returns "Entity: entity_name" or CMapMesh returns "Mesh (2 faces)"
/// </summary>
public override string ToString()
{
return $"MapNode: {native.GetDescription()}";
}
/// <summary>
/// Creates a copy of this map node.
/// </summary>
public MapNode Copy()
{
var copy = native.Copy();
if ( !copy.IsValid() ) return null;
// Automatically add it to the current mapdoc, we don't really deal with them outside of a mapdoc for now
Hammer.ActiveMap.native.AddObjectToDocument( copy, native.GetParent() );
return copy;
}
public void Remove()
{
var doc = World.worldNative.GetRootDocument( MapNodeGetRootDocument.MayBeLoading );
doc.DeleteNode( this );
}
/// <summary>
/// Does this map node generate models to use?
/// </summary>
public bool GeneratesEntityModelGeometry => native.GeneratesEntityModelGeometry();
}