mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 11:28:19 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
159 lines
3.9 KiB
C#
159 lines
3.9 KiB
C#
using Editor.MapDoc;
|
|
using NativeHammer;
|
|
|
|
namespace Editor.MapEditor;
|
|
|
|
// [CanDrop( "vmat" )] // We can do this and stomp the native stuff once face selection works
|
|
[CanDrop( "material" )]
|
|
[Expose]
|
|
class MaterialDropTarget : IMapViewDropTarget
|
|
{
|
|
MapMesh MapMesh { get; set; }
|
|
Material Material { get; set; }
|
|
CSavedObjects SavedObjects { get; set; }
|
|
|
|
MapDocument doc;
|
|
|
|
MapNode PlacedNode { get; set; }
|
|
|
|
public void DragEnter( Package package, MapView view )
|
|
{
|
|
doc = view.MapDoc;
|
|
|
|
// Start fetching the material, what we could maybe do is make a fake material from the thumbnail
|
|
_ = GetMaterialFromPackage( package );
|
|
|
|
SavedObjects = CSavedObjects.Create();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate the angles required to align the entity to the plane perpendicular to the given normal
|
|
/// Now rotate the angle 90 degrees so that it matches the orientation of the texture as it is authored
|
|
/// </summary>
|
|
private static Angles DeriveOverlayAnglesFromNormal( Vector3 hitNormal )
|
|
{
|
|
return (Rotation.From( hitNormal.EulerAngles - Vector3.Up.EulerAngles ) *
|
|
Rotation.FromAxis( Vector3.Up, 90.0f )).Angles();
|
|
}
|
|
|
|
public void DragMove( MapView view )
|
|
{
|
|
// Pointless for us to do any "iterative" work on a pending material
|
|
if ( Material == null )
|
|
return;
|
|
|
|
if ( PlacedNode.IsValid() )
|
|
{
|
|
view.BuildRay( out Vector3 rayStart, out Vector3 rayEnd );
|
|
var tr = Trace.Ray( rayStart, rayEnd ).SkipToolsMaterials().MeshesOnly().Run( view.MapDoc.World );
|
|
|
|
PlacedNode.Position = tr.HitPosition;
|
|
PlacedNode.Angles = DeriveOverlayAnglesFromNormal( tr.Normal );
|
|
}
|
|
else
|
|
{
|
|
view.BuildRay( out Vector3 rayStart, out Vector3 rayEnd );
|
|
var tr = Trace.Ray( rayStart, rayEnd ).Run( view.MapDoc.World );
|
|
|
|
RevertIterativeDragWork();
|
|
|
|
if ( tr.MapNode is MapMesh mesh )
|
|
{
|
|
MapMesh = mesh;
|
|
SavedObjects.SaveObject( mesh );
|
|
mesh.SetMaterial( Material );
|
|
}
|
|
else
|
|
{
|
|
MapMesh = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void DragLeave( MapView view )
|
|
{
|
|
doc = null;
|
|
|
|
if ( PlacedNode.IsValid() )
|
|
{
|
|
view.MapDoc.DeleteNode( PlacedNode );
|
|
}
|
|
|
|
RevertIterativeDragWork();
|
|
}
|
|
|
|
public void DragDropped( MapView view )
|
|
{
|
|
if ( PlacedNode.IsValid() )
|
|
{
|
|
History.MarkUndoPosition( $"Drop {PlacedNode}" );
|
|
History.KeepNew( PlacedNode );
|
|
return;
|
|
}
|
|
|
|
RevertIterativeDragWork();
|
|
|
|
if ( MapMesh == null || Material == null )
|
|
return;
|
|
|
|
History.MarkUndoPosition( "Drop material" );
|
|
History.Keep( MapMesh );
|
|
|
|
// This doesn't work in faces mode, which sucks - probably needs glue
|
|
MapMesh.SetMaterial( Material );
|
|
|
|
SavedObjects.DeleteThis();
|
|
}
|
|
|
|
private void RevertIterativeDragWork()
|
|
{
|
|
if ( !SavedObjects.IsValid )
|
|
return;
|
|
|
|
SavedObjects.RestoreObjects();
|
|
SavedObjects.RemoveAll();
|
|
}
|
|
|
|
async Task GetMaterialFromPackage( Package package )
|
|
{
|
|
// Install our package ( Do we need any sort of loading indicator, it's gonna be fast surely )
|
|
var asset = await AssetSystem.InstallAsync( package );
|
|
Material = Material.Load( asset.Path );
|
|
|
|
CreateNode();
|
|
}
|
|
|
|
public void CreateNode()
|
|
{
|
|
if ( !doc.IsValid() ) return;
|
|
|
|
// This fucking stupid shit is defined from shaders wtf
|
|
if ( Material.Attributes.GetInt( "decal", 0 ) == 1 )
|
|
{
|
|
var overlayEnt = new MapEntity( doc );
|
|
overlayEnt.ClassName = "info_overlay";
|
|
overlayEnt.SetKeyValue( "material", Material.ResourcePath );
|
|
|
|
PlacedNode = overlayEnt;
|
|
}
|
|
else if ( Material.Attributes.GetInt( "overlay", 0 ) == 1 )
|
|
{
|
|
var width = NativeHammer.Global.MaterialGetMappingWidth( Material.native );
|
|
var height = NativeHammer.Global.MaterialGetMappingHeight( Material.native );
|
|
|
|
var staticOverlay = new MapStaticOverlay( doc );
|
|
staticOverlay.CreateCenteredQuad( new Vector2( width, height ), Material );
|
|
|
|
PlacedNode = staticOverlay;
|
|
}
|
|
else if ( Material.Attributes.GetInt( "sky", 0 ) == 1 )
|
|
{
|
|
var skyEnt = new MapEntity( doc );
|
|
skyEnt.ClassName = "env_sky";
|
|
skyEnt.SetKeyValue( "skyname", Material.ResourcePath );
|
|
|
|
PlacedNode = skyEnt;
|
|
}
|
|
}
|
|
}
|