using Editor.MapEditor;
using NativeMapDoc;
using System;
using System.ComponentModel.DataAnnotations;
namespace Editor.MapDoc;
internal enum MapNodeGetRootDocument
{
///
/// Will return null if the root document is still being loaded
///
MustBeLoaded = 0,
///
/// Will return the root document even if it is not completely loaded
///
MayBeLoading = 1
};
///
/// A common class used for all objects in the world object tree.
///
[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;
}
///
/// A new node has been added to the world - does not happen when loaded from file
///
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 )
{
}
///
/// User specified name of this node
///
public string Name
{
get => native.GetName();
set
{
Assert.NotNull( value );
native.SetName( value );
}
}
///
/// Native C++ type name for this map node (nice for debug, might disappear at some point)
///
public string TypeString => native.GetTypeString();
///
/// World position of this map node.
///
public Vector3 Position
{
get => native.GetOrigin();
set => native.SetOrigin( value );
}
///
/// Euler angles of this map node.
///
public Angles Angles
{
get => native.GetAngles();
set => native.SetAngles( value );
}
///
/// Non-uniform scalar for this map node.
///
public Vector3 Scale
{
get => native.GetScales();
set => native.SetScales( value );
}
///
/// The parent node, at the top level this will be the
///
public MapNode Parent
{
get => native.GetParent();
set => native.SetParent( value );
}
///
/// Each MapNode can have many children. Children usually transform with their parents, etc.
///
public IEnumerable Children
{
get
{
// TODO: Ideally we'd have a List 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 );
}
}
}
///
/// Visibility of this MapNode, e.g if it's been hidden by the user
///
public bool Visible
{
get => native.IsVisible();
set => native.SetVisible( value );
}
///
/// The world this map node belongs to.
///
public MapWorld World
{
get => native.GetParentWorld();
}
///
/// Map node types implement this to describe themselves and their children.
/// e.g CMapEntity returns "Entity: entity_name" or CMapMesh returns "Mesh (2 faces)"
///
public override string ToString()
{
return $"MapNode: {native.GetDescription()}";
}
///
/// Creates a copy of this map node.
///
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 );
}
///
/// Does this map node generate models to use?
///
public bool GeneratesEntityModelGeometry => native.GeneratesEntityModelGeometry();
}