TwinMotion Dynamic Link Export Fbx Automatically

TwinMotion Dynamic Link Export Fbx Automatically

Anonymous
2,779 Views
7 Replies
Message 1 of 8

TwinMotion Dynamic Link Export Fbx Automatically

Anonymous
Not applicable

 

Hi, I have been trying to export fbx using TwinMotion Dynamic Link. I would like to export fbx files from many revit files, so I would like to know how I can use PostCommand and then operate windows forms on the export panel. I tried to use "SendKeys" but I couldn't make it. 

 

using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace TwinMotion
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    [Autodesk.Revit.DB.Macros.AddInId("1D1D7C97-4450-43CA-A675-22C2FCC465D5")]
	public partial class ThisApplication
	{
    	
		private void Module_Startup(object sender, EventArgs e)
		{

		}

		private void Module_Shutdown(object sender, EventArgs e)
		{

		}
		

		#region Revit Macros generated code
		private void InternalStartup()
		{
			this.Startup += new System.EventHandler(Module_Startup);
			this.Shutdown += new System.EventHandler(Module_Shutdown);
		}
		#endregion

		void OnDialogBoxShowing(object sender, DialogBoxShowingEventArgs args )
		{
			//DialogBoxShowingEventArgs args
			TaskDialogShowingEventArgs e2 = args as TaskDialogShowingEventArgs;
		
			e2.OverrideResult((int)TaskDialogResult.Ok);

		}

		
		public void myMacro()
		{
			Document doc = this.ActiveUIDocument.Document;   
            //Application app = doc.Application;

            //UIApplication uiapp = new UIApplication(app);
            UIApplication uiapp = new UIApplication(Application);
            
            try
            {
            	
            	
                //RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.ViewRange);
                RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.PlaceAComponent);
                string name = "CustomCtrl_%CustomCtrl_%Twinmotion 2020%Twinmotion Direct Link%ExportButton";
				RevitCommandId id_addin = RevitCommandId.LookupCommandId(name);
                if (id_addin != null)
                    {
                    //TaskDialog.Show("Test", "Found ID");
                    
                    uiapp.DialogBoxShowing += new EventHandler<DialogBoxShowingEventArgs>(OnDialogBoxShowing );
                    uiapp.PostCommand(id_addin);

                    
                    }
            }
 
             
            catch
            {
                TaskDialog.Show("Test", "error");
            }
            finally{
            	
            	
            	uiapp.DialogBoxShowing -= new EventHandler<DialogBoxShowingEventArgs>(OnDialogBoxShowing );
    			
            }

		}

	}
}

 

0 Likes
Accepted solutions (1)
2,780 Views
7 Replies
Replies (7)
Message 2 of 8

Anonymous
Not applicable

I am a very new on Revit API forum. Any advice would be greatly appreciated! 🙂 

0 Likes
Message 3 of 8

jeremytammik
Autodesk
Autodesk
Accepted solution

Welcome to the Revit API.

 

Unfortunately, the Revit API provides no support for the scenario you describe.

 

The native Windows API does provide all the required functionality to simulate any user input you like.

 

Therefore, you can use the Windows API to drive the required workflow.

 

I used such a mechanism to implement a simple Windows form clicker:

 

https://github.com/jeremytammik/JtClicker

 

You can try to implement something similar for your requirements.

 

However, as said, that has nothing whatsoever to do with the Revit API.

  

I hope this helps.

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 4 of 8

Anonymous
Not applicable

Hi Jeremy,

 

Thank you for your reply! I am able to export automatically by Windows API as you showed me the example! 

 

void OnDialogBoxShowing(object sender, DialogBoxShowingEventArgs args )
		{
			//DialogBoxShowingEventArgs args
			TaskDialogShowingEventArgs e2 = args as TaskDialogShowingEventArgs;
		
			e2.OverrideResult((int)TaskDialogResult.Ok);

		}

		static async void RunCommands(UIApplication uiapp,RevitCommandId id_addin){
			uiapp.PostCommand(id_addin);
			await Task.Delay(400);
			SendKeys.Send("{ENTER}");
			await Task.Delay(400);
			SendKeys.Send("{ENTER}");
			await Task.Delay(400);
			SendKeys.Send("{ENTER}");
			await Task.Delay(400);
			SendKeys.Send("{ESCAPE}");
			await Task.Delay(400);
			SendKeys.Send("{ESCAPE}");
			
		}
		public void myMacro()
		{
			Document doc = this.ActiveUIDocument.Document;   
            //Application app = doc.Application;

            //UIApplication uiapp = new UIApplication(app);
            UIApplication uiapp = new UIApplication(Application);
            
            try
            {
            	
            	
                //RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.ViewRange);
                RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.PlaceAComponent);
                string name = "CustomCtrl_%CustomCtrl_%Twinmotion 2020%Twinmotion Direct Link%ExportButton";
				RevitCommandId id_addin = RevitCommandId.LookupCommandId(name);
                if (id_addin != null)
                    {
                    //TaskDialog.Show("Test", "Found ID");
                    
                    uiapp.DialogBoxShowing += new EventHandler<DialogBoxShowingEventArgs>(OnDialogBoxShowing );
                    //uiapp.PostCommand(id_addin);

                    RunCommands(uiapp, id_addin);
                    }
            }
 
             
            catch
            {
                TaskDialog.Show("Test", "error");
            }
            finally{
            	
            	
            	uiapp.DialogBoxShowing -= new EventHandler<DialogBoxShowingEventArgs>(OnDialogBoxShowing );
    			
            }

		}

Best,

 

Yuko 

Message 5 of 8

jeremy_tammik
Autodesk
Autodesk

Congratulations on solving this, and thank you very much for your appreciation and above all for sharing your nice clean solution!

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 6 of 8

patrickmR&N
Enthusiast
Enthusiast

Any thoughts on how to do this with Python?

I just can't seem to get Send Keys to function.  Where are you getting SendKeys from?

0 Likes
Message 7 of 8

onurerMY3Q8
Explorer
Explorer
I found out that SendKeys class is in System.Windows.Forms namespace. You need to add the assembly with the same name to your project if you haven't done so.
0 Likes
Message 8 of 8

onurerMY3Q8
Explorer
Explorer

Thank you for sharing your solution. It saved me unbelievable amount of time, maybe days or weeks. Thank you VERY VERY MUCH!!!

 

I cleaned the code and made it more readable in case someone needs it. My own Revit plugin calls this Twinmotion macro automatically after Revit starts up.

 

using System.Threading.Tasks;
using Autodesk.Revit.UI;
using System.Windows.Forms;
using Autodesk.Revit.UI.Events;

namespace YourNamespaceHere
{
    public class Class2 : IExternalApplication
    {
        UIControlledApplication UIControlledApplication;

        public Result OnStartup(UIControlledApplication Application)
        {
            UIControlledApplication = Application;
            UIControlledApplication.Idling += Application_Idling;

            return Result.Succeeded;
        }

        public Result OnShutdown(UIControlledApplication Application) => Result.Succeeded;

        void Application_Idling(object Sender, IdlingEventArgs E)
        {
            UIControlledApplication.Idling -= Application_Idling;

            var UIApplication = (UIApplication)Sender;

            MyMacro(UIApplication);

            //TaskDialog.Show("Application_Idling", Sender.GetType().FullName);
        }

        void OnDialogBoxShowing(object Sender, DialogBoxShowingEventArgs Args) => ((TaskDialogShowingEventArgs)Args).OverrideResult((int)TaskDialogResult.Ok);

        static async void RunCommands(UIApplication UIapp, RevitCommandId Id_Addin)
        {
            UIapp.PostCommand(Id_Addin);
            await Task.Delay(400);
            SendKeys.Send("{ENTER}");
            await Task.Delay(400);
            SendKeys.Send("{ENTER}");
            await Task.Delay(400);
            SendKeys.Send("{ENTER}");
            await Task.Delay(400);
            SendKeys.Send("{ESCAPE}");
            await Task.Delay(400);
            SendKeys.Send("{ESCAPE}");
        }

        void MyMacro(UIApplication UIapp)
        {
            try
            {
                var Name = "CustomCtrl_%CustomCtrl_%Twinmotion 2020%Twinmotion Direct Link%ExportButton";
                var Id_Addin = RevitCommandId.LookupCommandId(Name);
                
                if (Id_Addin != null)
                {
                    UIapp.DialogBoxShowing += OnDialogBoxShowing;

                    RunCommands(UIapp, Id_Addin);
                }
            }
            catch
            {
                TaskDialog.Show("Test", "error");
            }
            finally
            {
                UIapp.DialogBoxShowing -= OnDialogBoxShowing;
            }
        }
    }
}

 

0 Likes