Revision Difference
Hammer_API#549170
<cat>Code.Editor</cat>
<title>Hammer API</title>
<note>This stuff isn't as mature as our games API, so this stuff will end up changing a fair amount as we figure out the best way to do things.</note>
# Hammer API
Tool addons can extend the capabilities of Hammer by using these APIs, you can interact with selected [map nodes](https://asset.party/api/Tools.MapDoc.MapNode) or procedurally create new map nodes. These nodes can be a [MapMesh](https://asset.party/api/Tools.MapDoc.MapMesh) which can procedurally create a mesh, [MapEntity](https://asset.party/api/Tools.MapDoc.MapEntity) for placing map entities and setting key values, or more.
Tool addons can extend the capabilities of Hammer by using these APIs, you can interact with selected [map nodes](https://asset.party/api/Editor.MapDoc.MapNode) or procedurally create new map nodes. These nodes can be a [MapMesh](https://asset.party/api/Editor.MapDoc.MapMesh) which can procedurally create a mesh, [MapEntity](https://asset.party/api/Editor.MapDoc.MapEntity) for placing map entities and setting key values, or more.
## Map Nodes
Map nodes can be created in the current map simply by calling their constructors.
```csharp
// Create new map entity
MapEntity entity = new();
entity.ClassName = "info_player_start";
entity.Position = Vector3.Up * 32.0f;
```
## Selection
You can get all the selected map nodes, or set the selection with the [Selection](https://asset.party/api/Tools.MapEditor.Selection) static class.
You can get all the selected map nodes, or set the selection with the [Selection](https://asset.party/api/Editor.MapEditor.Selection) static class.
```csharp
// Get the first selected map node
MapNode node = Selection.All.FirstOrDefault();
// You can pattern match MapNodes
if ( node is MapMesh mesh )
{
// ...
}
// Create a new entity and add it to the selection
Selection.Add( new MapEntity() );
```
## Traces
The [Trace](https://asset.party/api/Tools.Trace) API lets you ray cast within map worlds, there's options to only hit meshes or skip tools materials. This primarily has usage for pickers, but could be used to snap things down or some crazy procedural stuff.
The [Trace](https://asset.party/api/Editor.Trace) API lets you ray cast within map worlds, there's options to only hit meshes or skip tools materials. This primarily has usage for pickers, but could be used to snap things down or some crazy procedural stuff.
```csharp
view.BuildRay( out Vector3 rayStart, out Vector3 rayEnd );
var tr = Trace.Ray( rayStart, rayEnd ).Run( view.MapDoc.World );
var entity = new MapEntity();
entity.ClassName = classname;
entity.Position = tr.HitPosition;
Selection.Set( entity );
```
## Map View Context Menu
You can extend the context menu in Hammer with the `hammer.mapview.contextmenu` event.
```csharp
[Event( "hammer.mapview.contextmenu" )]
static void OnMapViewContextMenu( Menu menu, MapView view )
{
menu.AddSeparator();
var submenu = menu.AddMenu( "Create Point Entity" );
// ...
}
```
<upload src="a5727/8daba681b65ea31.png" size="182702" name="image.png" />
## Adding Menu Bar
Menus can be added to the menu bar in Hammer the same as other tools
```csharp
[Menu( "Hammer", "My Cool Stuff/Log Selected", "info" )]
public static void LogSelected()
{
Log.Info( Selection.All.First() );
}
```
## Primitive Builders
You can add new primitives to the block tool.
```csharp
[Title( "Rect" ), Icon( "rectangle" )]
class RectPrimitive : PrimitiveBuilder
{
[Browsable( false )]
public BBox BBox { get; set; }
public override void SetFromBox( BBox box ) => BBox = box;
public override void Build( PolygonMesh mesh )
{
var mins = BBox.Mins;
var maxs = BBox.Maxs;
mesh.AddFace(
new Vector3( mins.x, mins.y, maxs.z ),
new Vector3( maxs.x, mins.y, maxs.z ),
new Vector3( maxs.x, maxs.y, maxs.z ),
new Vector3( mins.x, maxs.y, maxs.z )
);
}
}
```
## Map Drop Targets
Map drop targets enable you to create handlers for your own asset types.
Here's how we enable you to drop soundscapes into maps:
```csharp
[CanDrop( "sndscape" )]
class SoundscapeDropTarget : IMapViewDropTarget
{
MapEntity SoundEntity { get; set; }
public void DragEnter( Asset asset, MapView view )
{
SoundEntity = new MapEntity();
SoundEntity.ClassName = "snd_soundscape";
SoundEntity.SetKeyValue( "soundscape", asset.Path );
}
public void DragMove( MapView view )
{
view.BuildRay( out Vector3 rayStart, out Vector3 rayEnd );
var tr = Trace.Ray( rayStart, rayEnd ).Run( view.MapDoc.World );
SoundEntity.Position = tr.HitPosition;
}
}
```