Lest deep dive in Autodesk NavisWorks api.
First, we need a tool plugin with mouse down Interceptor:
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;
[Plugin("PickModelPointPlugin", "ADSK")]
class PickModelPointPlugin : ToolPlugin
{
public override bool MouseDown(View view, KeyModifiers modifiers,
ushort button, int x, int y,
double timeOffset)
{
// get current selection
PickItemResult pickedResult = view.PickItemFromPoint(x, y);
if (pickedResult != null)
{
Autodesk.Navisworks.Api.Point3D clickedPoint =
pickedResult.Point;
// Sent to static exchange, to make click result available
// for Addin Plugins in namespace
// convert to custom Point, to reduce coupling.
StaticExchange.PickedPoint = new cPoint(clickedPoint.X,
clickedPoint.Y,
clickedPoint.Z);
}
return base.MouseDown(view, modifiers, button, x, y,
timeOffset);
}
}First, we need a tool plugin with mouse down Interceptor:
class StaticExchange
{
public static event PointDelegate PointUpdate;
public delegate void PointDelegate(PointEventArgs e);
private static cPoint point;
public static cPoint PickedPoint
{
get {
return point;
}
set {
point = value;
PointUpdate?.Invoke(new PointEventArgs(point));
}
}
}Obviously, we may need to do some actions as soon as user click on something. That`s why event delegate has been presented in StaticExchange.
Finally, in our Addin we call A plugin and await for result. In my case it’s a form with buttons, so on a button I bind click handler:
private async void btnPickNavisPoint_Click(object sender, EventArgs e)
{
try {
//search for plugin availability
ToolPluginRecord toolPluginRecord =
(ToolPluginRecord)ANA.Application.Plugins
.FindPlugin("PickModelPointPlugin.ADSK");
//set Plugin for execution
ANA.Application.MainDocument.Tool
.SetCustomToolPlugin(toolPluginRecord.LoadPlugin());
//Subscribe on event
StaticExchange.PointUpdate += onPointUpdate;
//Patiently wait for result
Point3D result = await WaitForUserChoiceAsync();
MessageBox.Show(
"Point: "+
"X:" + result.X.ToString("0.##") + " " +
"Y:" + result.Y.ToString("0.##") + " " +
"Z:" + result.Z.ToString("0.##") + " ");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
//Unsubscribe and switch back to Tool.Select
StaticExchange.PointUpdate -= onPointUpdate;
ANA.Application.MainDocument.Tool.Value = Tool.Select;
}
}And now final peace – where magic is live.
- Declare TaskCompletionSource,
- Wrap it into WaitUserChoice.
- In event handler call Source and pass argument.
private TaskCompletionSource<Point3D> _userChoiceTcs;
private async Task<Point3D> WaitForUserChoiceAsync()
{
// Create a new TaskCompletionSource for this operation
_userChoiceTcs = new TaskCompletionSource<Point3D>();
try
{
Point3D result = await _userChoiceTcs.Task;
return result;
}
finally
{
// Clean up
_userChoiceTcs = null;
}
}
private void onPointUpdate(PointEventArgs p)
{
//Here come the user click result
_userChoiceTcs?.TrySetResult(new Point3D(p.Point.X,
p.Point.Y,
p.Point.Z));
}As a result we got message with coordinates of clicked points, as soon as user click on some object.
Leave a Reply