Quantcast
Channel: Manufacturing DevBlog
Viewing all 531 articles
Browse latest View live

Fusion API: Default Paths to Load Add-In

$
0
0

By Xiaodong Liang

Question:

Will Fusion 360 load an add-in from the path (%AppData%) only? Is there any other paths I can configure?

Solution:

A couple of other paths are available for Fusion to look for the add-in. This is missed in the API help.

%programfiles%\Autodesk\ApplicationPlugins
%programdata%\Autodesk\ApplicationPlugins
%appdata%\Roaming\Autodesk\ApplicationPlugins
%appdata%\Roaming\Autodesk\Autodesk Fusion 360\API\AddIns


Fusion API: Manage Participant Bodies

$
0
0

By Xiaodong Liang

This is mainly quoted from Fusion 360 help document:

In the recent update in Jan, Fusion added the ability to choose which bodies will be affected when creating certain features; extrude, hole, loft, revolve, and sweep. The input objects for each of those features and the feature objects themselves all now support a "participantBodies" property that lets you specify the set of bodies that will participate in the feature. The default is that all visible bodies that intersect the feature will be used, which was also the previous default so existing programs shouldn't see any change of behavior.

The codes below is a simple sample on how this new property works. It creates some bodies, then creates a cut feature. With participantBodies, only some of the bodies are cut. 

Screen Shot 2017-01-23 at 6.14.14 PM

 

Python:

 


#Author-
#Description-

import adsk.core, adsk.fusion, adsk.cam, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        #crreate a document
        doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
        
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        
        #get the root component of the active design
        rootComp = design.rootComponent
        
        # create a sketch
        sketches = rootComp.sketches
        sketch = sketches.add(rootComp.xZConstructionPlane)
        sketchCircles = sketch.sketchCurves.sketchCircles
        centerPoint = adsk.core.Point3D.create(0, 0, 0)
        sketchCircles.addByCenterRadius(centerPoint, 3.0)

        # Get the profile defined by the circle.
        prof = sketch.profiles.item(0)

	  # Create sketch for Cut
        sketchForCut = sketches.add(rootComp.xZConstructionPlane)
        sketchForCutCircles = sketchForCut.sketchCurves.sketchCircles
        sketchForCutCircles.addByCenterRadius(centerPoint, 1.5)

        # Get the profile defined by the circle.
        profForCut = sketchForCut.profiles.item(0)

        # Create an extrusion input
        extrudes = rootComp.features.extrudeFeatures
        extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)

        # Define that the extent is a distance extent of 5 cm.
        distance = adsk.core.ValueInput.createByReal(5)
        extInput.setDistanceExtent(False, distance)

        # Create the extrusion.
        ext = extrudes.add(extInput)

        # Get the body created by extrusion
        body = ext.bodies.item(0)

        # Create input entities for rectangular pattern
        inputEntites = adsk.core.ObjectCollection.create()
        inputEntites.add(body)

        # Get x and y axes for rectangular pattern
        xAxis = rootComp.xConstructionAxis
        yAxis = rootComp.yConstructionAxis

        # Quantity and distance
        quantityOne = adsk.core.ValueInput.createByString('0')
        distanceOne = adsk.core.ValueInput.createByString('0 cm')
        quantityTwo = adsk.core.ValueInput.createByString('6')
        distanceTwo = adsk.core.ValueInput.createByString('15 cm')

        # Create the input for rectangular pattern
        rectangularPatterns = rootComp.features.rectangularPatternFeatures
        rectangularPatternInput = rectangularPatterns.createInput(inputEntites, xAxis, \
            quantityOne, distanceOne, adsk.fusion.PatternDistanceType.SpacingPatternDistanceType)

        # Set the data for second direction
        rectangularPatternInput.setDirectionTwo(yAxis, quantityTwo, distanceTwo)

        # Create the rectangular pattern
        rectangularFeature = rectangularPatterns.add(rectangularPatternInput)

        patBodies = rectangularFeature.bodies

        body0 = patBodies.item(0)
        face0 = body0.faces.item(0)

        extCutInput = extrudes.createInput(profForCut, adsk.fusion.FeatureOperations.CutFeatureOperation)

	  # Set the extrude input
        distanceForCut = adsk.core.ValueInput.createByString('90 cm')
        extCutInput.setDistanceExtent(False, distanceForCut)

        # set bodies to participate
        extCutInput.participantBodies = [patBodies.item(0), patBodies.item(2), patBodies.item(4)]

        extrudes.add(extCutInput)        
        

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

JavaScipt:

 


function run(context) {"use strict";
    if (adsk.debug === true) {
        /*jslint debug: true*/
        debugger;
        /*jslint debug: false*/
    }

    var ui;
    try {
        var app = adsk.core.Application.get();
        ui = app.userInterface;

        // Create a document.
        var doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType);

        var product = app.activeProduct;
        var design = adsk.fusion.Design(product);

        // Get the root component of the active design.
        var rootComp = design.rootComponent;

        // Create sketch
        var sketches = rootComp.sketches;
        var sketch = sketches.add(rootComp.xZConstructionPlane);
        var sketchCircles = sketch.sketchCurves.sketchCircles;
        var centerPoint = adsk.core.Point3D.create(0, 0, 0);
        sketchCircles.addByCenterRadius(centerPoint, 3.0);

        // Get the profile defined by the circle.
        var prof = sketch.profiles.item(0);

		// Create sketch for Cut
        var sketchForCut = sketches.add(rootComp.xZConstructionPlane);
        var sketchForCutCircles = sketchForCut.sketchCurves.sketchCircles;
        sketchForCutCircles.addByCenterRadius(centerPoint, 1.5);

        // Get the profile defined by the circle.
        var profForCut = sketchForCut.profiles.item(0);

        // Create an extrusion input
        var extrudes = rootComp.features.extrudeFeatures;
        var extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation);

        // Define that the extent is a distance extent of 5 cm.
        var distance = adsk.core.ValueInput.createByReal(5);
        extInput.setDistanceExtent(false, distance);

        // Create the extrusion.
        var ext = extrudes.add(extInput);

        // Get the body created by extrusion
        var body = ext.bodies.item(0);

        // Create input entities for rectangular pattern
        var inputEntites = adsk.core.ObjectCollection.create();
        inputEntites.add(body);

        // Get x and y axes for rectangular pattern
        var xAxis = rootComp.xConstructionAxis;
        var yAxis = rootComp.yConstructionAxis;

        // Quantity and distance
        var quantityOne = adsk.core.ValueInput.createByString('0');
        var distanceOne = adsk.core.ValueInput.createByString('0 cm');
        var quantityTwo = adsk.core.ValueInput.createByString('6');
        var distanceTwo = adsk.core.ValueInput.createByString('15 cm');

        // Create the input for rectangular pattern
        var rectangularPatterns = rootComp.features.rectangularPatternFeatures;
        var rectangularPatternInput = rectangularPatterns.createInput(inputEntites, xAxis,
            quantityOne, distanceOne, adsk.fusion.PatternDistanceType.SpacingPatternDistanceType);

        // Set the data for second direction
        rectangularPatternInput.setDirectionTwo(yAxis, quantityTwo, distanceTwo);

        // Create the rectangular pattern
        var rectangularFeature = rectangularPatterns.add(rectangularPatternInput);

		var patBodies = rectangularFeature.bodies;

        var body0 = patBodies.item(0);
        var face0 = body0.faces.item(0);

		var extCutInput = extrudes.createInput(profForCut, adsk.fusion.FeatureOperations.CutFeatureOperation);

		// Set the extrude input
        var distanceForCut = adsk.core.ValueInput.createByString('90 cm');
        extCutInput.setDistanceExtent(false, distanceForCut);

        //set bodies to participate
        extCutInput.participantBodies = [patBodies.item(0), patBodies.item(2), patBodies.item(4)];

		extrudes.add(extCutInput);

    }
    catch (e) {
        if (ui) {
            ui.messageBox('Failed : ' + (e.description ? e.description : e));
        }
    }

    adsk.terminate();
}

Fusion API: Add Simple Extrude Feature and Add by Input

$
0
0

By Xiaodong Liang

In the past, when creating the extrude feature, we will need to create an ExtrudeInput firstly, then add the extrude feature with the input. The input is like a definition of the feature, with which, some parameters of the feature can be defined. One of the benefits is the ExtrudeFeatures.Add method would not be changed for long term. When any new parameter of creating feature is appended, the API specifies can only add more properties withExtrudeInput. 

However, quoted from the latest news of Fusion 360 API: With the recent changes to the Extrude feature the API to create extrusions got quite a bit more complicated. However, we recognized that even though the feature is more powerful and provides a lot more capabilities, the majority of the time people still create simple finite extrusions. To make this more common workflow easier, we've added a new addSimple. method to the ExtrudeFeatures collection. This makes creating an extrusion much simpler than it ever was before with a single API call.

So, you could decide to use the previous way or the simple way based on your requirement. The following is a code snippets from the API sample on the two scenarios. 

Python


#Author-
#Description-

import adsk.core, adsk.fusion, adsk.cam, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        #crreate a document
        doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
        
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        
        #get the root component of the active design
        rootComp = design.rootComponent
        
        # Get extrude features
        extrudes = rootComp.features.extrudeFeatures  
        
        # create a sketch
        sketches = rootComp.sketches
        sketch1 = sketches.add(rootComp.xZConstructionPlane)
        sketchCircles = sketch1.sketchCurves.sketchCircles
        centerPoint = adsk.core.Point3D.create(0, 0, 0)
        sketchCircles.addByCenterRadius(centerPoint, 3.0)

        # Get the profile defined by the circle.
        prof_simple = sketch1.profiles.item(0) 
        
        # Extrude Sample 1: A simple way of creating typical extrusions (extrusion that goes from the profile plane the specified distance).
        # Define a distance extent of 5 cm
        distance = adsk.core.ValueInput.createByReal(5) 
        extrude_simple = extrudes.addSimple(prof_simple, distance, adsk.fusion.FeatureOperations.NewBodyFeatureOperation) 
        # Get the extrusion body
        body_simple = extrude_simple.bodies.item(0) 
        body_simple.name = "simple extrude feature" 
        #Create another sketch
        sketch2 = sketches.add(rootComp.xZConstructionPlane) 
        sketchCircles2 = sketch2.sketchCurves.sketchCircles 
        sketchCircles2.addByCenterRadius(centerPoint, 13.0) 
        sketchCircles2.addByCenterRadius(centerPoint, 15.0) 
        prof_for_input = sketch2.profiles.item(1) 
        # Create taper angle value inputs
        deg0 = adsk.core.ValueInput.createByString('0 deg') 
        deg2 = adsk.core.ValueInput.createByString('2 deg') 
        deg5 = adsk.core.ValueInput.createByString('5 deg') 
        #Create distance value inputs
        mm10 = adsk.core.ValueInput.createByString('10 mm') 
        mm100 = adsk.core.ValueInput.createByString('100 mm') 

        # Extrude Sample 2: Create an extrusion that goes from the profile plane with one side distance extent
        extrudeInput = extrudes.createInput(prof_for_input, adsk.fusion.FeatureOperations.NewBodyFeatureOperation) 
        # Create a distance extent definition
        extent_distance = adsk.fusion.DistanceExtentDefinition.create(mm100) 
        extrudeInput.setOneSideExtent(extent_distance, adsk.fusion.ExtentDirections.PositiveExtentDirection) 
        # Create the extrusion
        extrude_by_input = extrudes.add(extrudeInput) 
        # Get the body of extrusion
        body_by_input = extrude_by_input.bodies.item(0) 
        body_by_input.name = "extrude feature by input" 

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

JavaScript


function run(context) {"use strict";
    if (adsk.debug === true) {
        /*jslint debug: true*/
        debugger;
        /*jslint debug: false*/
    }
    var ui;
    try {
        var app = adsk.core.Application.get();
        ui = app.userInterface;
        // Create a document.
        var doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType);
        var product = app.activeProduct;
        var design = adsk.fusion.Design(product);

        // Get the root component of the active design
        var rootComp = design.rootComponent;
        
        // Get extrude features
        var extrudes = rootComp.features.extrudeFeatures; 
        
        // Create sketch
        var sketches = rootComp.sketches;
        
        var sketch1 = sketches.add(rootComp.xZConstructionPlane);
        var sketchCircles = sketch1.sketchCurves.sketchCircles;
        var centerPoint = adsk.core.Point3D.create(0, 0, 0);
        var circle = sketchCircles.addByCenterRadius(centerPoint, 5.0);
        
        // Get the profile defined by the circle
        var prof_simple = sketch1.profiles.item(0);
        
        // Extrude Sample 1: A simple way of creating typical extrusions (extrusion that goes from the profile plane the specified distance).
        // Define a distance extent of 5 cm
        var distance = adsk.core.ValueInput.createByReal(5);
        var extrude_simple = extrudes.addSimple(prof_simple, distance, adsk.fusion.FeatureOperations.NewBodyFeatureOperation);
        // Get the extrusion body
        var body_simple = extrude_simple.bodies.item(0);
        body_simple.name = "simple extrude feature";
       // Create another sketch
        var sketch2 = sketches.add(rootComp.xZConstructionPlane);
        var sketchCircles2 = sketch2.sketchCurves.sketchCircles;
        sketchCircles2.addByCenterRadius(centerPoint, 13.0);
        sketchCircles2.addByCenterRadius(centerPoint, 15.0);
        var prof_for_input = sketch2.profiles.item(1);
        // Create taper angle value inputs
        var deg0 = adsk.core.ValueInput.createByString('0 deg');
        var deg2 = adsk.core.ValueInput.createByString('2 deg');
        var deg5 = adsk.core.ValueInput.createByString('5 deg');
        // Create distance value inputs
        var mm10 = adsk.core.ValueInput.createByString('10 mm');
        var mm100 = adsk.core.ValueInput.createByString('100 mm');

        // Extrude Sample 2: Create an extrusion that goes from the profile plane with one side distance extent
        var extrudeInput = extrudes.createInput(prof_for_input, adsk.fusion.FeatureOperations.NewBodyFeatureOperation);
        // Create a distance extent definition
        var extent_distance = adsk.fusion.DistanceExtentDefinition.create(mm100);
        extrudeInput.setOneSideExtent(extent_distance, adsk.fusion.ExtentDirections.PositiveExtentDirection);
        // Create the extrusion
        var extrude_by_input = extrudes.add(extrudeInput);
        // Get the body of extrusion
        var body_by_input = extrude_by_input.bodies.item(0);
        body_by_input.name = "extrude feature by input";

        
    } 
    catch (e) {
        if (ui) {
            ui.messageBox('Failed : ' + (e.description ? e.description : e));
        }
    }

    adsk.terminate(); 
}
 

 

 

Fusion API: Manage Participant Bodies

$
0
0

By Xiaodong Liang

This is mainly quoted from Fusion 360 help document:

In the recent update in Jan, Fusion added the ability to choose which bodies will be affected when creating certain features; extrude, hole, loft, revolve, and sweep. The input objects for each of those features and the feature objects themselves all now support a "participantBodies" property that lets you specify the set of bodies that will participate in the feature. The default is that all visible bodies that intersect the feature will be used, which was also the previous default so existing programs shouldn't see any change of behavior.

The codes below is a simple sample on how this new property works. It creates some bodies, then creates a cut feature. With participantBodies, only some of the bodies are cut. 

Screen Shot 2017-01-23 at 6.14.14 PM

 

Python:

 


#Author-
#Description-

import adsk.core, adsk.fusion, adsk.cam, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        #crreate a document
        doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
        
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        
        #get the root component of the active design
        rootComp = design.rootComponent
        
        # create a sketch
        sketches = rootComp.sketches
        sketch = sketches.add(rootComp.xZConstructionPlane)
        sketchCircles = sketch.sketchCurves.sketchCircles
        centerPoint = adsk.core.Point3D.create(0, 0, 0)
        sketchCircles.addByCenterRadius(centerPoint, 3.0)

        # Get the profile defined by the circle.
        prof = sketch.profiles.item(0)

	  # Create sketch for Cut
        sketchForCut = sketches.add(rootComp.xZConstructionPlane)
        sketchForCutCircles = sketchForCut.sketchCurves.sketchCircles
        sketchForCutCircles.addByCenterRadius(centerPoint, 1.5)

        # Get the profile defined by the circle.
        profForCut = sketchForCut.profiles.item(0)

        # Create an extrusion input
        extrudes = rootComp.features.extrudeFeatures
        extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)

        # Define that the extent is a distance extent of 5 cm.
        distance = adsk.core.ValueInput.createByReal(5)
        extInput.setDistanceExtent(False, distance)

        # Create the extrusion.
        ext = extrudes.add(extInput)

        # Get the body created by extrusion
        body = ext.bodies.item(0)

        # Create input entities for rectangular pattern
        inputEntites = adsk.core.ObjectCollection.create()
        inputEntites.add(body)

        # Get x and y axes for rectangular pattern
        xAxis = rootComp.xConstructionAxis
        yAxis = rootComp.yConstructionAxis

        # Quantity and distance
        quantityOne = adsk.core.ValueInput.createByString('0')
        distanceOne = adsk.core.ValueInput.createByString('0 cm')
        quantityTwo = adsk.core.ValueInput.createByString('6')
        distanceTwo = adsk.core.ValueInput.createByString('15 cm')

        # Create the input for rectangular pattern
        rectangularPatterns = rootComp.features.rectangularPatternFeatures
        rectangularPatternInput = rectangularPatterns.createInput(inputEntites, xAxis, \
            quantityOne, distanceOne, adsk.fusion.PatternDistanceType.SpacingPatternDistanceType)

        # Set the data for second direction
        rectangularPatternInput.setDirectionTwo(yAxis, quantityTwo, distanceTwo)

        # Create the rectangular pattern
        rectangularFeature = rectangularPatterns.add(rectangularPatternInput)

        patBodies = rectangularFeature.bodies

        body0 = patBodies.item(0)
        face0 = body0.faces.item(0)

        extCutInput = extrudes.createInput(profForCut, adsk.fusion.FeatureOperations.CutFeatureOperation)

	  # Set the extrude input
        distanceForCut = adsk.core.ValueInput.createByString('90 cm')
        extCutInput.setDistanceExtent(False, distanceForCut)

        # set bodies to participate
        extCutInput.participantBodies = [patBodies.item(0), patBodies.item(2), patBodies.item(4)]

        extrudes.add(extCutInput)        
        

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

JavaScipt:

 


function run(context) {"use strict";
    if (adsk.debug === true) {
        /*jslint debug: true*/
        debugger;
        /*jslint debug: false*/
    }

    var ui;
    try {
        var app = adsk.core.Application.get();
        ui = app.userInterface;

        // Create a document.
        var doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType);

        var product = app.activeProduct;
        var design = adsk.fusion.Design(product);

        // Get the root component of the active design.
        var rootComp = design.rootComponent;

        // Create sketch
        var sketches = rootComp.sketches;
        var sketch = sketches.add(rootComp.xZConstructionPlane);
        var sketchCircles = sketch.sketchCurves.sketchCircles;
        var centerPoint = adsk.core.Point3D.create(0, 0, 0);
        sketchCircles.addByCenterRadius(centerPoint, 3.0);

        // Get the profile defined by the circle.
        var prof = sketch.profiles.item(0);

		// Create sketch for Cut
        var sketchForCut = sketches.add(rootComp.xZConstructionPlane);
        var sketchForCutCircles = sketchForCut.sketchCurves.sketchCircles;
        sketchForCutCircles.addByCenterRadius(centerPoint, 1.5);

        // Get the profile defined by the circle.
        var profForCut = sketchForCut.profiles.item(0);

        // Create an extrusion input
        var extrudes = rootComp.features.extrudeFeatures;
        var extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation);

        // Define that the extent is a distance extent of 5 cm.
        var distance = adsk.core.ValueInput.createByReal(5);
        extInput.setDistanceExtent(false, distance);

        // Create the extrusion.
        var ext = extrudes.add(extInput);

        // Get the body created by extrusion
        var body = ext.bodies.item(0);

        // Create input entities for rectangular pattern
        var inputEntites = adsk.core.ObjectCollection.create();
        inputEntites.add(body);

        // Get x and y axes for rectangular pattern
        var xAxis = rootComp.xConstructionAxis;
        var yAxis = rootComp.yConstructionAxis;

        // Quantity and distance
        var quantityOne = adsk.core.ValueInput.createByString('0');
        var distanceOne = adsk.core.ValueInput.createByString('0 cm');
        var quantityTwo = adsk.core.ValueInput.createByString('6');
        var distanceTwo = adsk.core.ValueInput.createByString('15 cm');

        // Create the input for rectangular pattern
        var rectangularPatterns = rootComp.features.rectangularPatternFeatures;
        var rectangularPatternInput = rectangularPatterns.createInput(inputEntites, xAxis,
            quantityOne, distanceOne, adsk.fusion.PatternDistanceType.SpacingPatternDistanceType);

        // Set the data for second direction
        rectangularPatternInput.setDirectionTwo(yAxis, quantityTwo, distanceTwo);

        // Create the rectangular pattern
        var rectangularFeature = rectangularPatterns.add(rectangularPatternInput);

		var patBodies = rectangularFeature.bodies;

        var body0 = patBodies.item(0);
        var face0 = body0.faces.item(0);

		var extCutInput = extrudes.createInput(profForCut, adsk.fusion.FeatureOperations.CutFeatureOperation);

		// Set the extrude input
        var distanceForCut = adsk.core.ValueInput.createByString('90 cm');
        extCutInput.setDistanceExtent(false, distanceForCut);

        //set bodies to participate
        extCutInput.participantBodies = [patBodies.item(0), patBodies.item(2), patBodies.item(4)];

		extrudes.add(extCutInput);

    }
    catch (e) {
        if (ui) {
            ui.messageBox('Failed : ' + (e.description ? e.description : e));
        }
    }

    adsk.terminate();
}

How to reference the AutoCAD COM API in an iLogic rule

$
0
0

By Wayne Brill

You can use AddReference to reference the AutoCAD COM Interops. Below is an iLogic rule to test this. (It just Dims a couple of types) iLogic needs to be able to find the AutoCAD Interop dlls. The path where it looks for the interop dlls is set in the Advanced iLogic Configuration. (tools tab Options). You can copy Autodesk.AutoCAD.Interop.dll and Autodesk.AutoCAD.Interop.Common.dll to the “iLogic AddIn DLLs directory” to avoid the error with the AddReference line of code. This screenshot shows the path where iLogic will look for the interop DLLs. 

iLogic_Configuration_WB

 

Here is the iLogic rule that references the AutoCAD Interops. It shows declaring types from the AutoCAD COM API. AcadBlockReference and AcadCircle. It also creates or gets a running session of AutoCAD.

AddReference "Autodesk.AutoCAD.Interop"
AddReference "Autodesk.AutoCAD.Interop.Common"

Imports Autodesk.AutoCAD.Interop.Common
Imports Autodesk.AutoCAD.Interop

Sub Main
Dim oAcadApp As AcadApplication
oAcadApp = CreateObject("AutoCAD.Application")
'If AutoCAD is already running use GetObject
'oAcadApp = GetObject(,"AutoCAD.Application")
oAcadApp.Visible = True

Dim myBlockRef As AcadBlockReference
Dim oAcadCircl as AcadCircle

MessageBox.Show(oAcadApp.Caption, "Title")

End Sub

Export to 3D PDF C++ Example

$
0
0

By Sajith Subramanian

There is a VBA example available in the Inventor API help file. Here is an example in C++.

One of the easier ways to test the below code, would be to replace the code in the SimpleExe SDK example.

The SimpleExe example is located on my system at: “C:\Users\Public\Documents\Autodesk\Inventor 2017\SDK\DeveloperTools\Samples\VC++\Standalone Applications\Inventor”.

// SimpleExe.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"

// Forward declarations
static HRESULT PublishPDF();

// Main. Note that all COM related activity (including the automatic 'release' within smart
// pointers) MUST take place BEFORE CoUnitialize(). Hence the function 'block' within which
// the smart-pointers construct and destruct (and AddRef and Release) keeping the CoUnitialize
// safely out of the way.

int _tmain(int argc, _TCHAR* argv[])
{
	HRESULT Result = NOERROR;

	Result = CoInitialize(NULL);

	if (SUCCEEDED(Result))
		Result = PublishPDF();

	CoUninitialize();

	return 0;
}

static HRESULT PublishPDF()
{
	HRESULT Result = NOERROR;

	CLSID InvAppClsid;
	Result = CLSIDFromProgID(L"Inventor.Application", &InvAppClsid);
	if (FAILED(Result)) return Result;

	/*Try and get hold of the running inventor app*/
	CComPtr pInvAppUnk;
	Result = ::GetActiveObject(InvAppClsid, NULL, &pInvAppUnk);
	if (FAILED(Result))
	{
		_tprintf_s(_T("*** Could not get hold of an active Inventor application ***\n"));
		return Result;
	}
	CComPtr pInvApp;
	Result = pInvAppUnk->QueryInterface(__uuidof(Application), (void **)&pInvApp);
	if (FAILED(Result)) return Result;

	/*Get the active document*/
	CComPtr pDoc;
	Result = pInvApp->get_ActiveDocument(&pDoc);
	if (FAILED(Result)) return Result;
	/*Output path of the pdf*/
	char filename[50];
	sprintf_s(filename, "c:\\temp\\test.pdf");
	/*Populate required options*/
	CComPtr oOptions = NULL;
	pInvApp->TransientObjects->CreateNameValueMap(&oOptions);
	oOptions->put_Value(CComBSTR("FileOutputLocation"), CComVariant(filename));
	oOptions->put_Value(CComBSTR("VisualizationQuality"), CComVariant((long)kHigh));

	CComSafeArray sDesignViews;
	sDesignViews.Add(CComBSTR("Master"));
	oOptions->put_Value(CComBSTR("ExportDesignViewRepresentations"), CComVariant(sDesignViews));


	/* Get the Add-Ins*/
	CComPtr pAddIns;
	Result = pInvApp->get_ApplicationAddIns(&pAddIns);

	
	/*Try and get hold of the 3D PDF addin*/
	CComBSTR clsidAnarkAddin = CComBSTR(_T("{3EE52B28-D6E0-4EA4-8AA6-C2A266DEBB88}"));
	CComPtr pAnarkAddin = nullptr;
	CComVariant vRes;
	Result = pAddIns->get_ItemById(clsidAnarkAddin, &pAnarkAddin);
	if (pAnarkAddin) {
		CComPtr pAnarkAPI;
		pAnarkAddin->get_Automation(&pAnarkAPI);
		if (pAnarkAPI) {
			DISPID dispid;
			OLECHAR* name(OLESTR("Publish"));
			Result = pAnarkAPI->GetIDsOfNames(IID_NULL, &name, 1,
LOCALE_SYSTEM_DEFAULT, &dispid); if (SUCCEEDED(Result)) { CComVariant vars[2]; vars[1] = pDoc; vars[0] = oOptions; DISPPARAMS params = { &vars[0], NULL, 2, 0 }; Result = pAnarkAPI->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &params, &vRes,
NULL, NULL); } } } return Result; }

Using Vault from Java

$
0
0

The other day someone asked about accessing Vault from Java. We already had an article written on that topic long ago, which I hope is still relevant, but it does not have the sample project anymore, unfortunately :(

Still, the article itself could be useful enough: Download Vault5_0_client_from_java_v1.0

Vault

Activate ActiveX based BrowserPane

$
0
0

In Inventor 2018 custom browser panes got their own dockable window so that they can be moved around by the user.

As a result your old code that was creating your new ActiveX based BrowserPane and was trying to activate it does not work anymore.
You need to find the DockableWindow that was created for your BrowserPane and make that visible - this action will also make it active:

Public Sub BrowserTest()
  Dim partDoc As PartDocument
  Set partDoc = ThisApplication.ActiveDocument
  Dim myBrowserPane As BrowserPane
  Set myBrowserPane = partDoc.BrowserPanes.Add("Test", "WMPlayer.OCX")' First you have to make its container visible
  Dim uiMgr As UserInterfaceManager
  Set uiMgr = ThisApplication.UserInterfaceManager
  Dim dockWindow As DockableWindow
  Set dockWindow = uiMgr.DockableWindows(myBrowserPane.Name)' This will also activate it
  dockWindow.Visible = True
End Sub

This will achieve the same as clicking the + button in the UI and selecting your browser pane that way:

Browserpane

 


Entitlement API in Inventor 2018

$
0
0

By Chandra shekar Gopal

Entitlement API are used in getting Autodesk 360 users account information. It also helps in determining genuinely of users. Whether the user is downloaded from App Store or copied from somewhere else.

In previous version of Inventor (2016 & 2017), Entitlement API is provided by AdWebServices.dll and is in C++. It is explained in this post.

In Inventor 2018, Entitlement API is provided by a .net Wrapper called "AddinNETFramework.AdWebServicesWrapper.dll"

The .net Wrapper is available at installed location (C:\Program Files\Autodesk\Inventor 2018\Bin)

So, in order to access Entitlement API, AddReference "AddinNETFramework.AdWebServicesWrapper.dll" from installed location to the application.

Sample C# code.

using Autodesk.WebServices;


CWebServicesManager mgr = new CWebServicesManager();

bool isInitialize = mgr.Initialize();

if (isInitialize == true)
{

   string userId = "";

   mgr.GetUserId(ref userId);

   string username = "";

   mgr.GetLoginUserName(ref username);

}

Sample VB.net code.

Imports Autodesk.WebServices


Dim webServiceMgr As CWebServicesManager

webServiceMgr = New CWebServicesManager()

Dim isWebServiceInitialized As Boolean

isWebServiceInitialized = webServiceMgr.Initialize()

If isWebServiceInitialized = True Then


    Dim userId As String = "" webService

    Mgr.GetUserId(userId)

    Dim userName As String = "" webService

    Mgr.GetLoginUserName(userName)


End If

Fusion 360 API: Customized Export Dialog

$
0
0

By Xiaodong Liang

This is a solution described in the forum post. The blog is basically for making the related codes be more searchable. 

The built-in dialog of [Export] is not customizable currently. While the API provides an object FileDialog that can be a workaround. i.e. make your own Export dialog and specify the parameters you would like to have such as file path and file type. This dialog is still a traditional type. I will write another blog on how to make an HTML dialog like the same style of built-in Export dialog.

Screen Shot 2017-08-21 at 2.49.43 PM

 

 

 


import adsk.core, adsk.fusion, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        filedlg = ui.createFileDialog()
        filedlg.initialDirectory = '/Users'
        filedlg.filter = '*.f3d'
        if filedlg.showSave() == adsk.core.DialogResults.DialogOK:
            design = adsk.fusion.Design.cast(app.activeProduct)
            option = design.exportManager.createFusionArchiveExportOptions(filedlg.filename, design.rootComponent)
            design.exportManager.execute(option)
    except:
      if ui:
          ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Fusion 360 API: Transform Component

$
0
0

By Xiaodong Liang

There are some posts on Autodesk forum about translating or rotating component in the assembly. This blog is mainly for sort them out. 

The object Occurrence.transform manages the transformation this component locates relatively to the space of assembly. It is  Matrix3D which is a standard math object. you could either make static method to build the translation, transformBy a matrix (Matrix3D.transformBy, or edit the cells (Matrix3D.setCell). Calling the transform property of the Occurrence object creates a new matrix that contains the current transform information of the occurrence and returns this matrix.  The matrix doesn't have any relationship back to the occurrence so changing information in the matrix has not affect on the occurrence.  So, the correct way to update the transformation is to get the existing transform as a matrix, change data within the matrix and then assign it back to the occurrence.  The matrix being assigned back to the occurrence can come from anywhere.  The assignment then update the internal transform of the occurrence.

The following is a code snippet on translating one component, and rotate another component. It shows a couple ways to update transformation. The comments enclosed explain the corresponding methods. 

Another trick in this demo is: to make an animation of the transforming, you will need to call doEvents after each transformation updates.  doEvents function temporarily halts the execution of the add-in or script and gives Fusion 360 a chance to handle any queued up messages.  

 

 


#Author-
#Description-


import adsk.core, adsk.fusion, adsk.cam, traceback,threading
import math
import time



times = 0


def eachMove():
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface


        #get product        
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        if not design:
            ui.messageBox('No active Fusion design', 'No Design')
            return


        # Get the root component of the active design.
        rootComp = design.rootComponent
        #get array of occurrences
        occurrences = rootComp.occurrences.asList
        
        #get first component
        occurrence_first = occurrences.item(0)
        
         #get second component
        occurrence_second= occurrences.item(1)
        
        #get thrid component
        occurrence_third= occurrences.item(2)
        
       
        while (times < 20):           
            #translate the first component by updating [translation] property

            #wrong way: occurrence.transform will clone and return a matrix
            #so any change on this cloned matrix does not take effect on the 
            #update of component
            #offsetVector = adsk.core.Vector3D.create(5.0, 0, 0)
            #occurrence.transform.translation.add( offsetVector )
        
            # Get the current transform of the first occurrence
            transform = occurrence_first.transform
            
            if times <10:
                # Change the transform data by moving 5.0cm on X+ axis
                transform.translation = adsk.core.Vector3D.create( transform.translation.x +  5.0, 0, 0)
            else:
                # Change the transform data by moving 5.0cm on X- axis
                transform.translation = adsk.core.Vector3D.create( transform.translation.x -  5.0, 0, 0)
            # Set the tranform data back to the occurrence
            occurrence_first.transform = transform
            # Get the current transform of the second occurrence
            transform = occurrence_second.transform
            rotX = adsk.core.Matrix3D.create()
            # Change the transform data by rotating around Z+ axis

            rotX.setToRotation(math.pi/4, adsk.core.Vector3D.create(0,0,1), adsk.core.Point3D.create(0,0,0))
            transform.transformBy(rotX)
            
             # Set the tranform data back to the occurrence
            occurrence_second.transform = transform
            
             # Get the current transform of the third occurrence
            transform = occurrence_third.transform
            
            if times <10:
                # Change the transform data by moving 5.0cm on Y+ axis
                transform.setCell(1,3,transform.getCell(1,3) + 5.0)
            else:
                # Change the transform data by moving 5.0cm on Y- axis
                transform.setCell(1,3,transform.getCell(1,3) - 5.0)

            #rotate around Z+ axis
            rotZSin = math.sin(math.pi/4 * times)
            rotZCos = math.cos(math.pi/4 * times)
            
            #change the cells value 
            transform.setCell(0,0,rotZCos)
            transform.setCell(0,1,rotZSin)
            transform.setCell(1,0,-rotZSin)
            transform.setCell(1,1,rotZCos) 
            
             # Set the tranform data back to the occurrence
            occurrence_third.transform = transform
            
            
            global times
            times =times +1 
            time.sleep( 0.1 )

            #Calling doEvents gives it a chance to catch up each time the components are transformed. 
            adsk.doEvents() 

       
        
       
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def run(context): 
    global times
    times = 0
    eachMove() 
   

click the picture to see the gif.

Transform

Connecting Microsoft Access via Inventor iLogic

$
0
0

by Chandra shekar Gopal

If you want to connect Microsoft Access Database through Inventor iLogic, a data connectivity driver called “2007 Office System Driver : Data Connectivity Components” is required to install in system. It can be downloaded from this link.

After successful installation of driver,the following iLogic code can be used to access Microsoft Access database in Inventor 2017

AddReference "System.Data"
AddReference "System.Core"
AddReference "System.Xml"

Imports System.Data.OleDb
Imports System.Data
Imports System.Xml


Sub Main()

	Dim Table_ As String = "EmployeeInfo"
	Dim query As String = "SELECT * FROM " & Table_
	Dim MDBConnString_ As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Temp\EmployeeInfo.accdb;Persist Security Info=False;"
	Dim ds As New DataSet
	Dim cnn As OleDbConnection = New OleDbConnection(MDBConnString_)
	cnn.Open()
	Dim cmd As New OleDbCommand(query, cnn)
	Dim da As New OleDbDataAdapter(cmd)
	da.Fill(ds, Table_)
	cnn.Close()
	Dim t1 As DataTable = ds.Tables(Table_)
	Dim row As DataRow
	Dim Item(2) As String
	For Each row In t1.Rows
		MessageBox.Show("EID : " & row(0) & " and Employee Name : " & row(1)
	Next
End Sub

To demonstrate code, a sample database (EmployeeInfo.accdb) is created and that would like as shown below.

Sample_Database

Sample database can be downloaded from here. After downloading database to desire location, path of database should be updated in the above iLogic code.

Result:

123456

Fusion 360 API: Work with Custom Palette

$
0
0

By Xiaodong Liang

I played with custom palette these days. I am sharing some practices. 

Firstly, the API help sample is a very good tutorial for us to get started with. Basically, the skeleton of palette is HTML, auxiliary js , css (except the js libraries of Fusion 360), the corresponding Fusion code (Python/C++) that consumes the HTML. 

When I was playing, I happened to hit an issue. The HTML elements were not shown up. It was only a white page. After checking with engineer team, it is addressed as a problem: current API does not encode the path of the local html which contains invalid character(such as space). This fix will be available soon. If you are testing right now, please put the dataset on a path without invalid character.

As said above, the skeleton of palette can include auxiliary js , css, which means we could apply with some nicer UI such as Bootstrap and the frameworks such as Jquery. The usage is simply like what you do in other web application. 

After the HTML is ready, I'd strongly suggest you open it to test it. It will be more easier to find out some problems. e.g. check the basic behavior of buttons, dropdown, checkbox, the workflows. The only that cannot test are the calls of Fusion 360., however you could at least check the parameters that are for communications with Fusion. In my test, I wanted to make a custom Export dialog. I have not made it work with [Choose Path] . The chooser does not show up.  In addition, I am working to add the workflow  [save to cloud]. 

 

Screen Shot 2017-09-01 at 5.56.20 PM

When the HTML and its workflow are ready, load the add-in to Fusion. If you do not want to debug, you could still view the HTML source or inspect element exactly like we program in web page. The browser engine Fusion uses is Chrome on Windows OS, Safari on Mac. 

Screen Shot 2017-09-01 at 6.04.45 PM

  Screen Shot 2017-09-01 at 6.08.18 PM

 

 

 

 

HTML and Js code

Fusion Add-In code

ADN team is hiring DevTech engineer (C++,NET) in Bangalore

$
0
0

By Virupaksha Aithal

ADN team is hiring an DevTech engineer (C++, .NET) - based in Bangalore office. Main responsibility is to work directly with third party developers to help them solve their problems using AutoCAD or Inventor or Revit API.

Requirement: Strong programming experience (C++/.NET). Knowledge of developing applications for AutoCAD or Revit or Inventor.

Location: Bangalore, India

If interested, send your resumes to Virupaksha Aithal

Get Specific Table Row of Content Center Family

$
0
0

By Xiaodong Liang

In general, we call ContentFamily.CreateMember to create the instance of a content family row by inputting index of this row. However, sometimes, we would need to pick one row which has specific cell value such as diameter, radius, length etc. I do not find a direct way to get specific table row. while we could still iterate the table rows and find out the specific item by the cell value(s).

In the other blog, my colleague Adam shared a code demo on how to get specific family. I produced another code based on that. The code tries to get the table row with one column: 'radius is 0.25". 

Note: the method ContentTableRow.GetCellValue accepts the column index, or its internal name. e.g. in this case, the internal name of column 'radius' is 'RR'. In addition,  in this demo code, I input one column only, however obviously, in family 'Bolt GB/T 35', there are many rows whose radius is also '0.25'.  So you would need to input other columns and cell values, in order to get the unique row.

One more thing: if you have known the member id of a row, you could also get ContentTableRow by a direct method:ContentCenter.GetContentObject. In the blog, my colleague Wayne introduced it. 

 


Public Function GetFamily( _
name As String, node As ContentTreeViewNode) _
As ContentFamily
  Dim cc As ContentCenter
  Set cc = ThisApplication.ContentCenter
  If node Is Nothing Then Set node = cc.TreeViewTopNode
  Dim cf As ContentFamily
  For Each cf In node.Families
    If cf.DisplayName = name Then
      Set GetFamily = cf
      Exit Function
    End If
  Next
  Dim child As ContentTreeViewNode
  For Each child In node.ChildNodes
    Set cf = GetFamily(name, child)
    If Not cf Is Nothing Then
      Set GetFamily = cf
      Exit Function
    End If
  Next
End Function'input: specific content family'       internal name of specific ContentTableColumn (ContentTableColumn.internalName)'       the cell value of this column'Note: you would need to input other columns and cell values, in order to get the unique row.
Public Function GetSpecificRow(cf As ContentFamily, colInternalName As String, cellValue As Variant)

    Dim oRow As ContentTableRow
    Dim oCol As ContentTableColumn
    
    Dim oFound As Boolean
    oFound = False
    For Each oRow In cf.TableRows

        'check the cell value of the specific column
        Dim oCellV As String
        oCellV = oRow.GetCellValue(colInternalName)
        If oCellV = cellValue Then
            oFound = True
            Exit For
        End If
    Next

    If oFound Then
      Set GetSpecificRow = oRow
    Else
      Set GetSpecificRow = Nothing
    End If
    
    
End Function

Public Sub CcTest()
   Dim asm As AssemblyDocument
   Set asm = ThisApplication.ActiveDocument
    
   'get specific family
   Dim cf As ContentFamily
   Set cf = GetFamily("Bolt GB/T 35", Nothing)'get specific table row
   Dim oOneTableRow As ContentTableRow
   Set oOneTableRow = GetSpecificRow(cf, "RR", "0.25")'create this member
   Dim member As String
   Dim ee As MemberManagerErrorsEnum
   member = cf.CreateMember(oOneTableRow, ee, "Problem")
   Dim tg As TransientGeometry
   Set tg = ThisApplication.TransientGeometry'inser the member to the assembly
   Call asm.ComponentDefinition.Occurrences.Add( _
    member, tg.CreateMatrix())
End Sub

3 million downloads from the Autodesk App Store

$
0
0

3million

Wow! What a great milestone for the Autodesk App Store! :)

Thanks to all the developers who created solutions for our customers and made them available on our store! :)

Remove OLE Links using ReferencedOLEFileDescriptor

$
0
0

By Xiaodong Liang

A few years ago, my colleague Wayne composed a blog on how to remove missing OLE links. Recently, a customer wanted to remove any OLE links when checking in to Vault. Ideally, he needs an iLogic code. So I refactored a little with the code Wayne demoed in VBA and iLogic:


Sub Main()
    Dim oDoc As Document
    oDoc = ThisApplication.ActiveDocument
    If TypeOf oDoc Is AssemblyDocument Then
            Call compositeDoc(oDoc)
    ElseIf TypeOf oDoc Is PartDocument Then
             Call singleDoc(oDoc)
    ElseIf TypeOf oDoc Is DrawingDocument Then
             Call singleDoc(oDoc)
    Else
    	Call MsgBox("wrong file type!") 
    End If
    Call oDoc.Update2(True)
End Sub

Sub singleDoc(doc)
        
    Dim oEachOLEDesc As ReferencedOLEFileDescriptor
    For Each oEachOLEDesc In doc.ReferencedOLEFileDescriptors
        oEachOLEDesc.Delete
        doc.Dirty = True
    Next
     
   
End Sub
 
Sub compositeDoc(parentAssDoc)
 
     'remove links of top document
     Call singleDoc(parentAssDoc)'remove links of sub document
     For Each oEachDesc In parentAssDoc.ReferencedDocumentDescriptors
        Dim doc As Document
        doc = oEachDesc.ReferencedDocument
        Dim oEachOLEDesc As ReferencedOLEFileDescriptor
        For Each oEachOLEDesc In doc.ReferencedOLEFileDescriptors
            oEachOLEDesc.Delete
            doc.Dirty = True
        Next
        If TypeOf doc Is AssemblyDocument Then
            Call compositeDoc(doc)
        End If
    Next
End Sub
The below code is written in VBA.

Sub breakLinks()
    Dim oDoc As Document
    Set oDoc = ThisApplication.ActiveDocument
    If TypeOf oDoc Is AssemblyDocument Then
            Call compositeDoc(oDoc)
    ElseIf TypeOf oDoc Is PartDocument Then
             Call singleDoc(oDoc)
    ElseIf TypeOf oDoc Is DrawingDocument Then
             Call singleDoc(oDoc)
    Else
        Call MsgBox("wrong file type!")
    End If
    Call oDoc.Update2(True)
End Sub

Sub singleDoc(doc)
        
    Dim oEachOLEDesc As ReferencedOLEFileDescriptor
    For Each oEachOLEDesc In doc.ReferencedOLEFileDescriptors
        oEachOLEDesc.Delete
        doc.Dirty = True
    Next
     
   
End Sub
 
Sub compositeDoc(parentAssDoc)
 
      'remove links of top document
     Call singleDoc(parentAssDoc)'remove links of sub document
     For Each oEachDesc In parentAssDoc.ReferencedDocumentDescriptors
        Dim doc As Document
        Set doc = oEachDesc.ReferencedDocument
        Dim oEachOLEDesc As ReferencedOLEFileDescriptor
        For Each oEachOLEDesc In doc.ReferencedOLEFileDescriptors
            oEachOLEDesc.Delete
            doc.Dirty = True
        Next
        If TypeOf doc Is AssemblyDocument Then
            Call compositeDoc(doc)
        End If
    Next
End Sub

Batch remove FEA links

$
0
0

By Xiaodong Liang

In the same time when I tested the code in the other blog, my colleague Henry Huang in product support team shared a code that can batch delete FEA OLE links. The code is provided by the engineer Paul Zeng. The code is well written. I believe it will be help many other customers. 

Thank you Paul, Henry!


Sub DeleteFEALinksForFolder()'add search paths
    Dim DicList
    Set DicList = CreateObject("Scripting.Dictionary")
    Const SearchPath = "C:\Users\zengp\Desktop\Inv_11229\" 'add more paths if you have
    DicList.Add SearchPath, ""'collect all folders
    Dim FileList, I
    Set FileList = CreateObject("Scripting.Dictionary")
    I = 0
    Do While I < DicList.Count
        Key = DicList.keys
        NowDic = Dir(Key(I), vbDirectory) 'start search folder
        Do While NowDic <> ""
            If (NowDic <> ".") And (NowDic <> "..") And (NowDic <> "OldVersions") Then
                If (GetAttr(Key(I) & NowDic) And vbDirectory) = vbDirectory Then 'find child folder
                    DicList.Add Key(I) & NowDic & "\", ""
                End If
            End If
            NowDic = Dir() 'continue searching
        Loop
        I = I + 1
    Loop'collect all part/assembly files
    For Each Key In DicList.keys
       NowFile = Dir(Key & "*.ipt")
       Do While NowFile <> ""
            FileList.Add Key & NowFile, "" 'Add(Key,Item)  FileList.Key=file name,FileList.Item=file path
            NowFile = Dir()
       Loop
    Next
    For Each Key In DicList.keys
       NowFile = Dir(Key & "*.iam")
       Do While NowFile <> ""
            FileList.Add Key & NowFile, "" 'Add(Key,Item)  FileList.Key=file name,FileList.Item=file path
            NowFile = Dir()
       Loop
    Next'delete FEA file links
    ThisApplication.SilentOperation = True
    For Each strFileName In FileList.keys
        DeleteFEALinksForSingleFile (strFileName)
    Next

    ThisApplication.SilentOperation = False
    
End Sub

Sub DeleteFEALinksForSingleFile(strFullFileName As String)

    Dim oDoc As Document
    Set oDoc = ThisApplication.Documents.Open(strFullFileName)
    
    Dim bHasFEALinksDeleted As Boolean
    bHasFEALinksDeleted = DeleteFEALinks(oDoc)
    If bHasFEALinksDeleted Then
        Call oDoc.Save
        Debug.Print strFullFileName
    End If
    
    Call oDoc.Close
End Sub


Function DeleteFEALinks(oDoc As Document) As Boolean 'if delete links
    DeleteFEALinks = False
    Dim oReferencedOLEFileDescriptors As ReferencedOLEFileDescriptors
    Set oReferencedOLEFileDescriptors = oDoc.ReferencedOLEFileDescriptors
    Dim oOLEFileDescriptor As ReferencedOLEFileDescriptor
    For Each oOLEFileDescriptor In oReferencedOLEFileDescriptors
        Dim strFileName As String
        strFileName = oOLEFileDescriptor.FullFileName
        If (IsFEAOLELinkFile(strFileName)) Then'Debug.Print "Break FEA OLE file link: " + strFileName
          DeleteFEALinks = True
          Call oOLEFileDescriptor.Delete
        End If
    Next
End Function

Function IsFEAOLELinkFile(strFileName As String) As Boolean
    IsFEAOLELinkFile = False

    Dim FEAFileExtArr() As Variant
    FEAFileExtArr = Array(".fins", ".fsat", ".ftes", ".fwiz", ".fmsh", ".fres")
    For Each strFileExt In FEAFileExtArr
      If (InStr(strFileName, strFileExt) > 0) Then
        IsFEAOLELinkFile = True
        Exit For
      End If
    Next

End Function

Inventor API: Detect a Content Center part is inserted as standard or custom

$
0
0

By Xiaodong Liang

When we place a part to the assembly, it could be a common part, or a part from content center yet as standard, or the content center part as custom. Sometimes we would need to know which type part is inserted. 

Screen Shot 2018-01-04 at 6.52.28 PM

To differentiate the UI >> [Place] or [Place from Content Center], the first I thought of is the event: UserInputEvents::OnActivateCommand. For UI>>[Place], it can tell a meaningful name, but for UI >> [Place from Content Center], it only tells a command "InteractionEvents"  which will also happen with some other UI operations. It cannot either tell as standard or as custom. In addition, the placing would be performed by an API code, the command name cannot over everything. 

So I turned to check the other event: AssemblyEvents::OnNewOccurrence. It can provide the final component definition after the part is inserted, by the definition, we could check if it is a content center part as standard by PartComponentDefinition::IsContentMember. As to the content center part as custom, it looks we have to check the properties of the document because a content center part will have some special property sets than the common part, even if it has been converted to as custom part. The other blog tells more. 

Based on the investigation, I produced a demo VBA code as below. Hope it helps.

Download TestProject

'module

Dim oClass As TestEvenClass
Sub startEvent()
    Set oClass = New TestEvenClass
    
    oClass.ini
    
    Do While True
        DoEvents
    Loop

End Sub

'event class
Public WithEvents oAssEvents As AssemblyEvents 

Public Sub ini()
  Set oAssEvents = ThisApplication.AssemblyEvents 
End Sub
  

Private Sub oAssEvents_OnNewOccurrence(ByVal DocumentObject As AssemblyDocument, ByVal Occurrence As ComponentOccurrence, ByVal BeforeOrAfter As EventTimingEnum, ByVal Context As NameValueMap, HandlingCode As HandlingCodeEnum)

If BeforeOrAfter = kAfter Then
    
    For Index = 1 To Context.Count

        Dim oContextName As String
        oContextName = Context.Name(Index)
            
        If oContextName = "ComponentDefinition" Then
            Dim oDef As ComponentDefinition
            Set oDef = Context.Value(Context.Name(Index))
            If TypeOf oDef Is PartComponentDefinition Then
                Dim oPartDef As PartComponentDefinition
                Set oPartDef = oDef
                If oPartDef.IsContentMember Then'this is a part from content center in standard way
                    Debug.Print "This is a part from Content Center "
                Else' check if it is common part of custom part of Content Center
                   Dim isCustomPart As Boolean
                   isCustomPart = False
                   Dim oPropertySets As PropertySets
                   Set oPropertySets = oPartDef.Document.PropertySets
                   Dim oEachProSet As PropertySet
                   Dim oEachP As Property

                    For i = 1 To oPropertySets.Count

                        ' use the 6th propertyset of [ContentCenter].' If it is a Custom part, there is only one property within this property set.' The name is “IsCustomPart”. While if it is a Standard CC part, there are some properties
                        ' to indicate the information of the CC such as family, member etc..'the internal name of this propertyset is not same across different content center part'so, it looks we have to use display name, which assumes no user defined property set with the same name.

                        Set oEachProSet = oPropertySets(i)
                        'If oEachProSet.InternalName = "{5E21919D-4082-492A-8A30-039424CD07B5}" Then
                        If oEachProSet.DisplayName = "ContentCenter" Then
                            For k = 1 To oEachProSet.Count
                                Set oEachP = oEachProSet(k)
                                If oEachP.Name = "IsCustomPart" Then
                                    Dim oValue As String
                                    oValue = oEachP.Value
                                    If oValue = "1" Then
                                        isCustomPart = True
                                        Exit For
                                    End If
                                End If
                            Next
                        End If
                        If isCustomPart Then
                            Exit For
                        End If
                    Next
                    If isCustomPart Then
                        Debug.Print "This is a custom part from content center"
                    Else
                        Debug.Print "This is a common part"
                    End If
                End If
            End If
        End If

    Next
    
End If

End Sub
 

Register now for Autodesk DevDays Online Webinars

$
0
0

Join us for the series of seven DevDays Webinars that begin on February 6th.  

 DevDays Online is the best way keep up to date with new and upcoming technology and features. After the introductory business-oriented session that will review Autodesk’s business growth curves—past, present and future, most of the webinars will focus on desktop application development, and additionally two on Forge and one on BIM 360 for cloud development. 

 As in previous DevDays events we have a theme: “The Journey Continues”.  In the first webinar—DevDays Keynotes—Jim Quanci, Senior Director, Software Partner Development, will cover the” journey” in-depth with a presentation on Autodesk’s strategic direction.  This will cover the move to subscription licenses, Forge strategy, the Autodesk App Store and more.  As he discusses the transition Autodesk is going through from a business and technical perspective Jim will also explain the opportunities this transition creates for software partners, including our plans to build a much larger customer base—accessible to you.

In the desktop software webinars, you will learn about the product and API changes and enhancements for AutoCAD, Revit, Civil 3D, InfraWorks, Inventor, Vault and Fusion.  These sessions will help you prepare for the upcoming Autodesk 2019 family of products so that you can be ready to delight our joint customers by having your applications compatible with the new releases. 

 In addition to making sure you stay current with Autodesk desktop technology now is the time to start investing in “what’s next”—the next wave in the journey.  Forge is Autodesk’s answer to “what’s next”.  Forge is the foundation cloud/web technology platform that Autodesk is building its next generation of tools on—and also making available to you. Forge is not an Autodesk “experiment”.  It’s your opportunity to catch the next wave—the shift to the cloud. Autodesk itself is the largest user of Forge in the world—with several hundred thousand users every day using BIM 360, Fusion 360, A360 and more. Join us—and, over a thousand companies that have built Forge into their apps/services already. Attend the two Forge webinars to learn how you too can deliver new capabilities to your customers.  Learn more about Forge.

DevDays Online Webinars

Register today for the webinar(s) of your choice:

DateTitleRegistration link    
Tues, Feb 6 2018DevDays Keynotes Register 
Wed, Feb 7 2018Forge Platform overview and Roadmap Register
Thu, Feb 8 2018Revit API, Civil 3D & InfraWorks updates Register
Tue, Feb 13 2018Forge API update (in detail) Register
Wed, Feb 14 2018Inventor, Vault and Fusion API updates Register
Thu, Feb 15 2018AutoCAD® and Design Automation for AutoCAD API updates Register
Tue, Feb 20 2018BIM 360 product and API update  Register
Viewing all 531 articles
Browse latest View live