A sample demonstrating how to create custom graphics entities.
To use the sample, create a new Python or C++ script and copy and paste this code, replacing the default code. You also need to unpack this zip file which contains a resource folder into the same folder where the source code file (.py or .cpp) is.
#include <Core/Utils.h> #include <Core/Application/Application.h> #include <Core/Application/Color.h> #include <Core/Application/Document.h> #include <Core/Application/ObjectCollection.h> #include <Core/Application/Product.h> #include <Core/Application/Products.h> #include <Core/Application/ValueInput.h> #include <Core/Geometry/Arc3D.h> #include <Core/Geometry/Circle3D.h> #include <Core/Geometry/BoundingBox3D.h> #include <Core/Geometry/Ellipse3D.h> #include <Core/Geometry/EllipticalArc3D.h> #include <Core/Geometry/Line3D.h> #include <Core/Geometry/NurbsCurve3D.h> #include <Core/Geometry/Point2D.h> #include <Core/Geometry/Point3D.h> #include <Core/Geometry/Vector2D.h> #include <Core/Geometry/Vector3D.h> #include <Core/Geometry/Matrix3D.h> #include <Core/Materials/Appearance.h> #include <Core/Materials/Appearances.h> #include <Core/Materials/MaterialLibraries.h> #include <Core/Materials/MaterialLibrary.h> #include <Core/UserInterface/UserInterface.h> #include <Core/UserInterface/CommandCreatedEventHandler.h> #include <Core/UserInterface/CommandCreatedEvent.h> #include <Core/UserInterface/CommandCreatedEventArgs.h> #include <Core/UserInterface/CommandEvent.h> #include <Core/UserInterface/CommandEventArgs.h> #include <Core/UserInterface/CommandEventHandler.h> #include <Core/UserInterface/InputChangedEvent.h> #include <Core/UserInterface/InputChangedEventArgs.h> #include <Core/UserInterface/InputChangedEventHandler.h> #include <Core/UserInterface/Command.h> #include <Core/UserInterface/CommandDefinition.h> #include <Core/UserInterface/CommandDefinitions.h> #include <Core/UserInterface/CommandInputs.h> #include <Core/UserInterface/ValueCommandInput.h> #include <Core/UserInterface/StringValueCommandInput.h> #include <Core/UserInterface/BoolValueCommandInput.h> #include <Core/UserInterface/ButtonRowCommandInput.h> #include <Core/UserInterface/DropDownCommandInput.h> #include <Core/UserInterface/Selection.h> #include <Core/UserInterface/SelectionCommandInput.h> #include <Core/UserInterface/FloatSliderCommandInput.h> #include <Core/UserInterface/IntegerSliderCommandInput.h> #include <Core/UserInterface/FloatSpinnerCommandInput.h> #include <Core/UserInterface/GroupCommandInput.h> #include <Core/UserInterface/IntegerSpinnerCommandInput.h> #include <Core/UserInterface/ListItems.h> #include <Core/UserInterface/ListItem.h> #include <Core/UserInterface/DistanceValueCommandInput.h> #include <Core/UserInterface/TableCommandInput.h> #include <CAM/CAM/CAM.h> #include <Fusion/BRep/BRepBody.h> #include <Fusion/Components/Component.h> #include <Fusion/Fusion/Design.h> // #include <Fusion/Graphics/CustomGraphicsEntity.h> #include <Fusion/Graphics/CustomGraphicsAppearanceColorEffect.h> #include <Fusion/Graphics/CustomGraphicsBasicMaterialColorEffect.h> #include <Fusion/Graphics/CustomGraphicsBillBoard.h> #include <Fusion/Graphics/CustomGraphicsSolidColorEffect.h> #include <Fusion/Graphics/CustomGraphicsVertexColorEffect.h> #include <Fusion/Graphics/CustomGraphicsViewPlacement.h> #include <Fusion/Graphics/CustomGraphicsViewScale.h> #include <Fusion/Graphics/CustomGraphicsBRepBody.h> #include <Fusion/Graphics/CustomGraphicsCoordinates.h> #include <Fusion/Graphics/CustomGraphicsCurve.h> #include <Fusion/Graphics/CustomGraphicsGroup.h> #include <Fusion/Graphics/CustomGraphicsGroups.h> #include <Fusion/Graphics/CustomGraphicsLines.h> #include <Fusion/Graphics/CustomGraphicsMesh.h> #include <Fusion/Graphics/CustomGraphicsText.h> #include <Fusion/Graphics/CustomGraphicsPointSet.h> #include <Fusion/Sketch/Sketch.h> #include <Fusion/Sketch/SketchArc.h> #include <Fusion/Sketch/SketchEllipticalArc.h> #include <Fusion/Sketch/SketchCircle.h> #include <Fusion/Sketch/SketchEllipse.h> #include <Fusion/Sketch/SketchFittedSpline.h> #include <Fusion/Sketch/SketchLine.h> #include <sstream> #include <map> #include <algorithm> #include <math.h> using namespace adsk::core; using namespace adsk::fusion; using namespace adsk::cam; namespace { const double pi = 4.0 * atan(1.0); } Ptr<Application> _app; Ptr<UserInterface> _ui; Ptr<Design> _des; Ptr<CustomGraphicsGroups> _cgGroups; Ptr<Point3D> _anchorPt; // Global const std::string _commandId = "CustomGraphicsSample_CPP"; const std::string _colorEffect_solid_id = "SolidColorEfect"; const std::string _colorEffect_basicMaterial_id = "BasicMaterialColorEffect"; const std::string _colorEffect_appearance_id = "AppearanceColorEffect"; const std::string _colorEffect_vertex_id = "VertexColorEffect"; const std::string _pointSetImage = "resources/16x16.png"; const std::string _solidLine_id = "Solid Line"; const std::string _centerLine_id = "Center Line"; const std::string _dashedLine_id = "Dashed Line"; const std::string _dotLine_id = "Dot Line"; const std::string _phantomLine_id = "Phantom Line"; const std::string _tracksLine_id = "Tracks Line"; const std::string _zigZagLine_id = "ZigZag Line"; int _numTeeth = 5; double _thickness = 0.5 * 2.54; double _scaleFactor = 10; // _scaleFactor is used to limit the size of pixel-scaled model // Global command inputs Ptr<DropDownCommandInput> _customGraphicsObj; Ptr<DropDownCommandInput> _colorEffects; Ptr<IntegerSliderCommandInput> _red; Ptr<IntegerSliderCommandInput> _green; Ptr<IntegerSliderCommandInput> _blue; Ptr<FloatSliderCommandInput> _opacity; Ptr<FloatSliderCommandInput> _glossiness; Ptr<SelectionCommandInput> _selection; Ptr<DistanceValueCommandInput> _transform; Ptr<DropDownCommandInput> _materialLibList; Ptr<DropDownCommandInput> _appearanceList; Ptr<StringValueCommandInput> _appearanceFilter; // Ptr<StringValueCommandInput> _text; Ptr<TableCommandInput> _coordTable; Ptr<BoolValueCommandInput> _add; Ptr<BoolValueCommandInput> _addStrip; Ptr<BoolValueCommandInput> _delete; Ptr<BoolValueCommandInput> _isLineStrip; Ptr<DropDownCommandInput> _lineStylePattern; Ptr<IntegerSliderCommandInput> _lineStyleWeight; Ptr<IntegerSliderCommandInput> _lineStyleScale; Ptr<GroupCommandInput> _viewPlacementGroup; Ptr<ButtonRowCommandInput> _viewCorner; Ptr<GroupCommandInput> _viewScaleGroup; Ptr<FloatSliderCommandInput> _pixelScale; Ptr<GroupCommandInput> _billboardingGroup; Ptr<ButtonRowCommandInput> _billboardingStyle; // Create the command definition. static Ptr<CommandDefinition> createCommandDefinition() { Ptr<CommandDefinitions> commandDefinitions = _ui->commandDefinitions(); if (!commandDefinitions) return nullptr; // Be fault tolerant in case the command is already added. Ptr<CommandDefinition> cmDef = commandDefinitions->itemById(_commandId); if (!cmDef) { cmDef = commandDefinitions->addButtonDefinition(_commandId, "CustomGraphicsSample", "Custom Graphics Sample"); } return cmDef; } // Add a row representing a coordinate (x, y, z) static void addRow(Ptr<TableCommandInput> tableInput) { if (!tableInput) return; static size_t rowNumber = 0; std::stringstream rowId; rowId << rowNumber; Ptr<CommandInputs> tableChildInputs = tableInput->commandInputs(); Ptr<CommandInput> xValueInput = tableChildInputs->addValueInput( tableInput->id() + "_x" + rowId.str(), "Value", "cm", ValueInput::createByReal(static_cast<double>(rowNumber))); Ptr<CommandInput> yValueInput = tableChildInputs->addValueInput( tableInput->id() + "_y" + rowId.str(), "Value", "cm", ValueInput::createByReal(static_cast<double>(rowNumber))); Ptr<CommandInput> zValueInput = tableChildInputs->addValueInput( tableInput->id() + "_z" + rowId.str(), "Value", "cm", ValueInput::createByReal(static_cast<double>(rowNumber))); int row = tableInput->rowCount(); tableInput->addCommandInput(xValueInput, row, 0); tableInput->addCommandInput(yValueInput, row, 1); tableInput->addCommandInput(zValueInput, row, 2); rowNumber = rowNumber + 1; } static void addLineStrip(Ptr<TableCommandInput> tableInput) { if (!tableInput) return; static size_t stripNumber = 0; std::stringstream stripId; stripId << stripNumber; Ptr<CommandInputs> tableChildInputs = tableInput->commandInputs(); Ptr<StringValueCommandInput> strInput = tableChildInputs->addStringValueInput( tableInput->id() + "_strip" + stripId.str(), "Line Strip", "-- Line Strip --"); if (!strInput) return; strInput->isReadOnly(true); int row = tableInput->rowCount(); tableInput->addCommandInput(strInput, row, 0, 0, 2); stripNumber = stripNumber + 1; } static void replaceItems(Ptr<DropDownCommandInput> cmdInput, std::vector<std::string> newItems) { if (!cmdInput) return; Ptr<ListItems> listItems = cmdInput->listItems(); if (!listItems) return; listItems->clear(); Ptr<ListItem> itemNone = listItems->add("None", true); if (!itemNone) return; itemNone->isSelected(true); if (newItems.size() > 0) { for (std::string str : newItems) { listItems->add(str, false); } if (listItems->count() > 1) { Ptr<ListItem> item1 = listItems->item(1); Ptr<ListItem> item0 = listItems->item(0); // item "None" if (!item1 || !item0) return; item1->isSelected(true); item0->deleteMe(); } } } static std::vector<std::string> getAppearancesFromLib(const std::string& libName, const std::string& filterExp) { std::vector<std::string> appearanceList; static std::map<std::string, std::vector<std::string>> appearanceMap; if (appearanceMap.find(libName) != appearanceMap.end()) { appearanceList = appearanceMap[libName]; } else { if (!_app) return std::vector<std::string>(); // get appearances according to libName Ptr<MaterialLibraries> matLibs = _app->materialLibraries(); if (!matLibs) return std::vector<std::string>(); Ptr<MaterialLibrary> matLib = matLibs->itemByName(libName); if (!matLib) return std::vector<std::string>(); Ptr<Appearances> appearances = matLib->appearances(); if (!appearances) return std::vector<std::string>(); for (int i = 0; i < appearances->count(); ++i) { if (Ptr<Appearance> appear = appearances->item(i)) appearanceList.push_back(appear->name()); } appearanceMap[libName] = appearanceList; } // apply filter std::string lowerFilterExp(filterExp); if (!filterExp.empty()) { std::transform(filterExp.begin(), filterExp.end(), lowerFilterExp.begin(), ::tolower); std::vector<std::string> filteredList; for (std::string appearanceName : appearanceList) { std::string lowerName(appearanceName); std::transform(appearanceName.begin(), appearanceName.end(), lowerName.begin(), ::tolower); if (lowerName.find(lowerFilterExp) != std::string::npos) { filteredList.push_back(appearanceName); } } appearanceList = filteredList; } return appearanceList; } static bool hasAppearance(Ptr<MaterialLibrary> lib) { if (!lib) return false; Ptr<Appearances> appearances = lib->appearances(); if (!appearances || appearances->count() == 0) return false; return true; } static std::vector<std::string> getMaterialLibNames() { if (!_app) return std::vector<std::string>(); Ptr<MaterialLibraries> libs = _app->materialLibraries(); if (!libs) return std::vector<std::string>(); std::vector<std::string> libNames; for (int i = 0; i < libs->count(); ++i) { if (Ptr<MaterialLibrary> lib = libs->item(i)) { if (hasAppearance(lib)) { libNames.push_back(lib->name()); } } } return libNames; } static Ptr<Appearance> getAppearance(const std::string& libName, const std::string& appearanceName) { if (appearanceName.empty() || appearanceName == "None" || !_app) return nullptr; if (!_des) return nullptr; Ptr<Appearances> appearances = _des->appearances(); if (appearances) { Ptr<Appearance> appearance = appearances->itemByName(appearanceName); if (appearance) return appearance; } Ptr<MaterialLibraries> libs = _app->materialLibraries(); if (!libs) return nullptr; Ptr<MaterialLibrary> lib = libs->itemByName(libName); if (!lib) return nullptr; appearances = lib->appearances(); if (!appearances) return nullptr; Ptr<Appearance> appearance = appearances->itemByName(appearanceName); return appearance; } static void applyLinesProperties(Ptr<CustomGraphicsLines> cgLines) { if (!cgLines) return; if (_lineStylePattern && _lineStylePattern->selectedItem()) { if (_lineStylePattern->selectedItem()->name() == _solidLine_id) cgLines->lineStylePattern(continuousLineStylePattern); else if (_lineStylePattern->selectedItem()->name() == _centerLine_id) cgLines->lineStylePattern(centerLineStylePattern); else if (_lineStylePattern->selectedItem()->name() == _dashedLine_id) cgLines->lineStylePattern(dashedLineStylePattern); else if (_lineStylePattern->selectedItem()->name() == _dotLine_id) cgLines->lineStylePattern(dotLineStylePattern); else if (_lineStylePattern->selectedItem()->name() == _dashedLine_id) cgLines->lineStylePattern(dashedLineStylePattern); else if (_lineStylePattern->selectedItem()->name() == _phantomLine_id) cgLines->lineStylePattern(phantomLineStylePattern); else if (_lineStylePattern->selectedItem()->name() == _tracksLine_id) cgLines->lineStylePattern(tracksLineStylePattern); else if (_lineStylePattern->selectedItem()->name() == _zigZagLine_id) cgLines->lineStylePattern(zigzagLineStylePattern); } if (_lineStyleWeight) cgLines->weight(static_cast<float>(_lineStyleWeight->valueOne())); if (_lineStyleScale) cgLines->lineStyleScale(static_cast<float>(_lineStyleScale->valueOne())); } static void applyColorEffect(Ptr<CustomGraphicsEntity> cgEnt) { if (!_des) return; if (!_colorEffects) return; Ptr<ListItem> selected = _colorEffects->selectedItem(); if (!selected) return; std::string colorEffectName = selected->name(); Ptr<CustomGraphicsColorEffect> colorEffect = nullptr; if (colorEffectName == _colorEffect_solid_id) { int red = 255, green = 0, blue = 0; if (_red) red = _red->valueOne(); if (_green) green = _green->valueOne(); if (_blue) blue = _blue->valueOne(); if (Ptr<Color> solidColor = Color::create(red, green, blue, 255)) { colorEffect = CustomGraphicsSolidColorEffect::create(solidColor); } } else if (colorEffectName == _colorEffect_basicMaterial_id) { Ptr<Color> diffuseColor = Color::create(0, 255, 0, 255); Ptr<Color> ambientColor = Color::create(255, 0, 0, 255); Ptr<Color> specularColor = Color::create(0, 0, 255, 255); Ptr<Color> emissiveColor = Color::create(0, 0, 0, 255); double glossiness = 5.0, opacity = 1.0; if (_glossiness) glossiness = _glossiness->valueOne(); if (_opacity) opacity = _opacity->valueOne(); if (diffuseColor && ambientColor && specularColor && emissiveColor) { colorEffect = CustomGraphicsBasicMaterialColorEffect::create( diffuseColor, ambientColor, specularColor, emissiveColor, glossiness, opacity); } } else if (colorEffectName == _colorEffect_appearance_id) { if (!_appearanceList || !_materialLibList) return; Ptr<ListItem> appearanceSelected = _appearanceList->selectedItem(); Ptr<ListItem> libSelected = _materialLibList->selectedItem(); if (!appearanceSelected || !libSelected) return; std::string appearanceName = appearanceSelected->name(); std::string libName = libSelected->name(); Ptr<Appearance> appearance = getAppearance(libName, appearanceName); if (appearance) { Ptr<Appearances> desAppearances = _des->appearances(); if (!desAppearances) return; if (!desAppearances->itemByName(appearanceName)) { appearance = desAppearances->addByCopy(appearance, appearanceName); } colorEffect = CustomGraphicsAppearanceColorEffect::create(appearance); } } else if (colorEffectName == _colorEffect_vertex_id) { colorEffect = CustomGraphicsVertexColorEffect::create(); } if (colorEffect && cgEnt) cgEnt->color(colorEffect); } static void getCoordinatesFromTable( Ptr<TableCommandInput> tableInput, std::vector<double>& vecCoords, std::vector<int>& vecStripLen) { vecCoords.clear(); vecStripLen.clear(); if (_coordTable) { int stripLen = 0; for (int i = 0; i < _coordTable->rowCount(); ++i) { if (Ptr<ValueCommandInput> xValueInput = tableInput->getInputAtPosition(i, 0)) { Ptr<ValueCommandInput> yValueInput = tableInput->getInputAtPosition(i, 1); Ptr<ValueCommandInput> zValueInput = tableInput->getInputAtPosition(i, 2); if (yValueInput && zValueInput) { vecCoords.push_back(xValueInput->value()); vecCoords.push_back(yValueInput->value()); vecCoords.push_back(zValueInput->value()); ++stripLen; } } else if (Ptr<StringValueCommandInput> lineStripInput = tableInput->getInputAtPosition(i, 0)) { vecStripLen.push_back(stripLen); stripLen = 0; } } vecStripLen.push_back(stripLen); } } static void changeColorEffectVisibility(const std::string& strColorEffectName) { if (_red) _red->isVisible(false); if (_green) _green->isVisible(false); if (_blue) _blue->isVisible(false); if (_opacity) _opacity->isVisible(false); if (_glossiness) _glossiness->isVisible(false); if (_appearanceList) _appearanceList->isVisible(false); if (_materialLibList) _materialLibList->isVisible(false); if (_appearanceFilter) _appearanceFilter->isVisible(false); if (strColorEffectName == _colorEffect_solid_id) { if (_red) _red->isVisible(true); if (_green) _green->isVisible(true); if (_blue) _blue->isVisible(true); } else if (strColorEffectName == _colorEffect_basicMaterial_id) { if (_opacity) _opacity->isVisible(true); if (_glossiness) _glossiness->isVisible(true); } else if (strColorEffectName == _colorEffect_appearance_id) { if (_appearanceList) _appearanceList->isVisible(true); if (_materialLibList) _materialLibList->isVisible(true); if (_appearanceFilter) _appearanceFilter->isVisible(true); } } static void changeLineStyleInputsVisibility(const std::string& patternName) { if (patternName == _solidLine_id) _lineStyleScale->isVisible(false); else _lineStyleScale->isVisible(true); } static void changeCGObjVisibility(const std::string& strObjName) { if (_colorEffects) { if (Ptr<ListItems> listItems = _colorEffects->listItems()) { listItems->clear(); listItems->add(_colorEffect_solid_id, true); listItems->add(_colorEffect_basicMaterial_id, false); listItems->add(_colorEffect_appearance_id, false); } _colorEffects->isVisible(false); } if (_selection) { _selection->clearSelection(); _selection->clearSelectionFilter(); _selection->setSelectionLimits(0, 0); _selection->isVisible(false); _selection->isEnabled(false); } // if (_text) // _text->isVisible(false); if (_coordTable) _coordTable->isVisible(false); if (_isLineStrip) _isLineStrip->isVisible(false); if (_lineStylePattern) _lineStylePattern->isVisible(false); if (_lineStyleWeight) _lineStyleWeight->isVisible(false); if (_lineStyleScale) _lineStyleScale->isVisible(false); changeColorEffectVisibility("None"); _viewPlacementGroup->isVisible(false); _viewScaleGroup->isVisible(false); _billboardingGroup->isVisible(false); if (strObjName == "Mesh") { if (_colorEffects) { _colorEffects->isVisible(true); if (Ptr<ListItems> listItems = _colorEffects->listItems()) { listItems->add(_colorEffect_vertex_id, false); } changeColorEffectVisibility(_colorEffect_solid_id); _viewPlacementGroup->isVisible(true); _viewScaleGroup->isVisible(true); _billboardingGroup->isVisible(true); } } else if (strObjName == "Lines") { changeColorEffectVisibility(_colorEffect_solid_id); _lineStylePattern->isVisible(true); _lineStyleWeight->isVisible(true); if (_lineStylePattern->selectedItem()->name() == _solidLine_id) { _lineStyleScale->isVisible(true); } _viewPlacementGroup->isVisible(true); _viewScaleGroup->isVisible(true); _billboardingGroup->isVisible(true); } else if (strObjName == "Curve") { if (_selection) { _selection->isVisible(true); _selection->isEnabled(true); _selection->tooltip("select a sketch curve"); _selection->commandPrompt("select a sketch curve"); _selection->addSelectionFilter("SketchCurve"); _selection->setSelectionLimits(1, 1); changeColorEffectVisibility(_colorEffect_solid_id); _lineStyleWeight->isVisible(true); } _viewPlacementGroup->isVisible(true); _viewScaleGroup->isVisible(true); _billboardingGroup->isVisible(true); } else if (strObjName == "BRep") { if (_colorEffects) _colorEffects->isVisible(true); if (_selection) { _selection->isVisible(true); _selection->isEnabled(true); _selection->tooltip("select a BRep body"); _selection->commandPrompt("select a BRep body"); _selection->addSelectionFilter("Bodies"); _selection->setSelectionLimits(1, 1); changeColorEffectVisibility(_colorEffect_solid_id); } _viewPlacementGroup->isVisible(true); _viewScaleGroup->isVisible(true); _billboardingGroup->isVisible(true); } // else if (strObjName == "Text") { // if (_text) // _text->isVisible(true); // changeColorEffectVisibility(_colorEffect_solid_id); // } else if (strObjName == "PointSet - Custom") { if (_coordTable) _coordTable->isVisible(true); if (_addStrip) _addStrip->isEnabled(false); } else if (strObjName == "Lines - Custom") { if (_coordTable) _coordTable->isVisible(true); if (_isLineStrip) _isLineStrip->isVisible(true); if (_addStrip) _addStrip->isEnabled(true); changeColorEffectVisibility(_colorEffect_solid_id); _lineStylePattern->isVisible(true); _lineStyleWeight->isVisible(true); if (_lineStylePattern->selectedItem()->name() == _solidLine_id) { _lineStyleScale->isVisible(true); } } } static Ptr<Vector2D> rotate2D(double rad, Ptr<Vector2D> vec) { if (!vec) return Vector2D::create(); double x = vec->x(); double y = vec->y(); double newX = x * cos(rad) - y * sin(rad); double newY = x * sin(rad) + y * cos(rad); return Vector2D::create(newX, newY); } static void calculateCoordinates( int numTeeth, /*out*/ std::vector<int>& rPts0, /*out*/ std::vector<int>& hPts0, /*out*/ std::vector<int>& pPts0, /*out*/ std::vector<int>& oPts0, /*out*/ std::vector<int>& rPts1, /*out*/ std::vector<int>& hPts1, /*out*/ std::vector<int>& pPts1, /*out*/ std::vector<int>& oPts1, /*out*/ std::vector<double>& vecCoords, /*out*/ std::vector<short>& vecColors) { if (numTeeth < 3) return; // holeDia < rootDia < pitchDia < outsideDia double holeDia = 0.5 * 2.54, diametralPitch = 2 / 2.54; double pitchDia = _numTeeth / diametralPitch; double dedendum = 1.157 / diametralPitch; if (fabs((20 * (pi / 180)) - diametralPitch) < 1e-6) { double circularPitch = pi / diametralPitch; if (circularPitch >= 20) dedendum = 1.25 / diametralPitch; else dedendum = (1.2 / diametralPitch) + (.002 * 2.54); } double rootDia = pitchDia - (2 * dedendum); double outsideDia = (_numTeeth + 2) / diametralPitch; Ptr<Vector2D> vecRootRadi = Vector2D::create(rootDia / 2, 0); Ptr<Vector2D> vecHoleRadi = Vector2D::create(holeDia / 2, 0); Ptr<Vector2D> vecPitchRadi = Vector2D::create(pitchDia / 2, 0); Ptr<Vector2D> vecOutRadi = Vector2D::create(outsideDia / 2, 0); double unitRadian = pi / numTeeth; for (int i = 0; i < 2 * numTeeth; ++i) { if (Ptr<Vector2D> pos = rotate2D(unitRadian * (i - 0.5), vecRootRadi)) { double x = pos->x(), y = pos->y(); rPts0.push_back(static_cast<int>(vecCoords.size() / 3)); rPts1.push_back(static_cast<int>(vecCoords.size() / 3 + 1)); vecCoords.insert(vecCoords.end(), {x, y, 0, x, y, _thickness}); vecColors.insert(vecColors.end(), {255, 0, 255, 128, 255, 0, 255, 128}); } } for (int i = 0; i < 2 * numTeeth; ++i) { if (Ptr<Vector2D> pos = rotate2D(unitRadian * (i - 0.5), vecHoleRadi)) { double x = pos->x(), y = pos->y(); hPts0.push_back(static_cast<int>(vecCoords.size() / 3)); hPts1.push_back(static_cast<int>(vecCoords.size() / 3 + 1)); vecCoords.insert(vecCoords.end(), {x, y, 0, x, y, _thickness}); vecColors.insert(vecColors.end(), {255, 0, 0, 128, 255, 0, 0, 128}); } } for (int i = 0; i < 2 * numTeeth; ++i) { if (Ptr<Vector2D> pos = rotate2D(unitRadian * (i - 0.5), vecPitchRadi)) { double x = pos->x(), y = pos->y(); pPts0.push_back(static_cast<int>(vecCoords.size() / 3)); pPts1.push_back(static_cast<int>(vecCoords.size() / 3 + 1)); vecCoords.insert(vecCoords.end(), {x, y, 0, x, y, _thickness}); vecColors.insert(vecColors.end(), {0, 0, 255, 128, 0, 0, 255, 128}); } } for (int i = 0; i < numTeeth; ++i) { if (Ptr<Vector2D> pos = rotate2D(unitRadian * i * 2, vecOutRadi)) { double x = pos->x(), y = pos->y(); oPts0.push_back(static_cast<int>(vecCoords.size() / 3)); oPts1.push_back(static_cast<int>(vecCoords.size() / 3 + 1)); vecCoords.insert(vecCoords.end(), {x, y, 0, x, y, _thickness}); vecColors.insert(vecColors.end(), {0, 255, 255, 128, 0, 255, 255, 128}); } } } static std::vector<int> calculateStripLen(int numTeeth) { if (numTeeth < 3) return std::vector<int>(); std::vector<int> vecStripLen; for (int i = 0; i < numTeeth; ++i) vecStripLen.push_back(6); for (int i = 0; i < 2 * numTeeth; ++i) vecStripLen.push_back(21); for (int i = 0; i < numTeeth; ++i) vecStripLen.push_back(24); for (int i = 0; i < 2 * numTeeth; ++i) vecStripLen.push_back(6); return vecStripLen; } static std::vector<int> calculateTriangles( int numTeeth, std::vector<int> rPts0, std::vector<int> hPts0, std::vector<int> pPts0, std::vector<int> oPts0, std::vector<int> rPts1, std::vector<int> hPts1, std::vector<int> pPts1, std::vector<int> oPts1) { if (numTeeth < 3) return std::vector<int>(); std::vector<int> vertexIndexList; // triangles between teeth for (int i = 0; i < numTeeth; ++i) { int idx0 = (2 * i + 1) % (2 * numTeeth); int idx1 = (2 * i + 2) % (2 * numTeeth); int rPtA0 = rPts0[idx0]; int rPtB0 = rPts0[idx1]; int rPtA1 = rPts1[idx0]; int rPtB1 = rPts1[idx1]; vertexIndexList.insert(vertexIndexList.end(), {rPtA0, rPtB0, rPtB1, rPtB1, rPtA1, rPtA0}); } // triangles on surface0 for (int i = 0; i < numTeeth; ++i) { int rPtA = rPts0[i * 2]; int rPtB = rPts0[i * 2 + 1]; int rPtC = rPts0[(i * 2 + 2) % (2 * numTeeth)]; int hPtA = hPts0[i * 2]; int hPtB = hPts0[i * 2 + 1]; int hPtC = hPts0[(i * 2 + 2) % (2 * numTeeth)]; int pPtA = pPts0[i * 2]; int pPtB = pPts0[i * 2 + 1]; int oPt = oPts0[i]; vertexIndexList.insert(vertexIndexList.end(), {hPtB, hPtC, rPtC, rPtC, rPtB, hPtB, rPtA, rPtB, pPtB, pPtB, pPtA, rPtA, hPtA, hPtB, rPtB, rPtB, rPtA, hPtA, pPtA, pPtB, oPt}); } // triangles on surface1 for (int i = 0; i < numTeeth; ++i) { int rPtA = rPts1[i * 2]; int rPtB = rPts1[i * 2 + 1]; int rPtC = rPts1[(i * 2 + 2) % (2 * numTeeth)]; int hPtA = hPts1[i * 2]; int hPtB = hPts1[i * 2 + 1]; int hPtC = hPts1[(i * 2 + 2) % (2 * numTeeth)]; int pPtA = pPts1[i * 2]; int pPtB = pPts1[i * 2 + 1]; int oPt = oPts1[i]; vertexIndexList.insert(vertexIndexList.end(), {hPtC, hPtB, rPtB, rPtB, rPtC, hPtC, rPtB, rPtA, pPtA, pPtA, pPtB, rPtB, hPtB, hPtA, rPtA, rPtA, rPtB, hPtB, pPtB, pPtA, oPt}); } // triangles on teeth for (int i = 0; i < numTeeth; ++i) { int rPtA0 = rPts0[i * 2]; int rPtB0 = rPts0[i * 2 + 1]; int pPtA0 = pPts0[i * 2]; int pPtB0 = pPts0[i * 2 + 1]; int rPtA1 = rPts1[i * 2]; int rPtB1 = rPts1[i * 2 + 1]; int pPtA1 = pPts1[i * 2]; int pPtB1 = pPts1[i * 2 + 1]; int oPt0 = oPts0[i]; int oPt1 = oPts1[i]; vertexIndexList.insert(vertexIndexList.end(), {rPtA1, rPtA0, pPtA0, pPtA0, pPtA1, rPtA1, pPtA1, pPtA0, oPt0, oPt0, oPt1, pPtA1, rPtB0, rPtB1, pPtB1, pPtB1, pPtB0, rPtB0, pPtB0, pPtB1, oPt1, oPt1, oPt0, pPtB0}); } // triangles on inner face for (int i = 0; i < 2 * numTeeth; ++i) { int hPtA0 = hPts0[i]; int hPtB0 = hPts0[(i + 1) % (2 * numTeeth)]; int hPtA1 = hPts1[i]; int hPtB1 = hPts1[(i + 1) % (2 * numTeeth)]; vertexIndexList.insert(vertexIndexList.end(), {hPtA1, hPtB1, hPtB0, hPtB0, hPtA0, hPtA1}); } return vertexIndexList; } static Ptr<CustomGraphicsMesh> drawMesh(const Ptr<CustomGraphicsGroup>& cgGroup) { // Calculate mesh coordinates std::vector<int> rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1; std::vector<short> vecColors; std::vector<double> vecCoords; calculateCoordinates(_numTeeth, rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1, vecCoords, vecColors); Ptr<CustomGraphicsCoordinates> coordinates = CustomGraphicsCoordinates::create(vecCoords); if (!coordinates) return nullptr; coordinates->colors(vecColors); // Calculate mesh triangles std::vector<int> vertexIndexList = calculateTriangles(_numTeeth, rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1); // Add Custom Graphics mesh if (!cgGroup) return nullptr; return cgGroup->addMesh(coordinates, vertexIndexList, std::vector<double>(), std::vector<int>()); } static Ptr<CustomGraphicsLines> drawLines(const Ptr<CustomGraphicsGroup>& cgGroup) { if (!cgGroup) return nullptr; // Calculate lines coordinates std::vector<int> rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1; std::vector<short> vecColors; std::vector<double> vecCoords; calculateCoordinates(_numTeeth, rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1, vecCoords, vecColors); Ptr<CustomGraphicsCoordinates> coordinates = CustomGraphicsCoordinates::create(vecCoords); if (!coordinates) return nullptr; // Calculate lines triangles std::vector<int> vertexIndexList = calculateTriangles(_numTeeth, rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1); // Calculate lines strip length std::vector<int> vecStripLen = calculateStripLen(_numTeeth); Ptr<CustomGraphicsLines> cgLines = cgGroup->addLines(coordinates, vertexIndexList, true, vecStripLen); return cgLines; } static Ptr<CustomGraphicsPointSet> drawPointSet(const Ptr<CustomGraphicsGroup>& cgGroup) { if (!cgGroup) return nullptr; // Calculate coordinates std::vector<int> rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1; std::vector<short> vecColors; std::vector<double> vecCoords; calculateCoordinates(_numTeeth, rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1, vecCoords, vecColors); Ptr<CustomGraphicsCoordinates> coordinates = CustomGraphicsCoordinates::create(vecCoords); if (!coordinates) return nullptr; return cgGroup->addPointSet(coordinates, std::vector<int>(), UserDefinedCustomGraphicsPointType, _pointSetImage); } // CommandExecuted event handler. class OnExecuteEventHandler : public adsk::core::CommandEventHandler { public: void notify(const Ptr<CommandEventArgs>& eventArgs) override { // get selection entity first since it's fragile and any creation/edit operations will clear the selection. Ptr<Base> selEntity = nullptr; if (_selection && _selection->selectionCount() > 0) { if (Ptr<Selection> sel0 = _selection->selection(0)) { selEntity = sel0->entity(); } } if (_customGraphicsObj) { if (!_cgGroups) return; Ptr<CustomGraphicsGroup> cgGroup = _cgGroups->add(); if (!cgGroup) return; if (!_anchorPt) _anchorPt = Point3D::create(); Ptr<CustomGraphicsEntity> cgEnt = nullptr; Ptr<ListItem> selectedCGObj = _customGraphicsObj->selectedItem(); if (!selectedCGObj) return; std::string cgObjName = selectedCGObj->name(); if (cgObjName == "Mesh") { cgEnt = drawMesh(cgGroup); _anchorPt->setWithArray({0, 0, _thickness / 2}); } else if (cgObjName == "Lines") { cgEnt = drawLines(cgGroup); _anchorPt->setWithArray({0, 0, _thickness / 2}); applyLinesProperties(cgEnt); } else if (cgObjName == "PointSet") { cgEnt = drawPointSet(cgGroup); } else if (cgObjName == "BRep") { if (Ptr<BRepBody> body = selEntity->cast<BRepBody>()) { cgEnt = cgGroup->addBRepBody(body); } } else if (cgObjName == "Curve") { if (Ptr<SketchCurve> skCurve = selEntity->cast<SketchCurve>()) { if (Ptr<Sketch> sk = skCurve->parentSketch()) { Ptr<Curve3D> curv = nullptr; if (Ptr<SketchArc> skArc = skCurve->cast<SketchArc>()) curv = skArc->geometry(); else if (Ptr<SketchEllipticalArc> skEllipArc = skCurve->cast<SketchEllipticalArc>()) curv = skEllipArc->geometry(); else if (Ptr<SketchCircle> skCircle = skCurve->cast<SketchCircle>()) curv = skCircle->geometry(); else if (Ptr<SketchEllipse> skEllipse = skCurve->cast<SketchEllipse>()) curv = skEllipse->geometry(); else if (Ptr<SketchLine> skLine = skCurve->cast<SketchLine>()) curv = skLine->geometry(); else if (Ptr<SketchFittedSpline> skSpline = skCurve->cast<SketchFittedSpline>()) curv = skSpline->geometry(); if (curv) { curv->transformBy(sk->transform()); Ptr<CustomGraphicsCurve> cgCurve = cgGroup->addCurve(curv); cgEnt = cgCurve; if (cgCurve) cgCurve->weight(static_cast<float>(_lineStyleWeight->valueOne())); } } } } // else if (cgObjName == "Text") { // if (_text) { // cgEnt = cgGroup->addText(_text->value(), "Test", 10, Point3D::create()); // } // } else if (cgObjName == "PointSet - Custom") { if (_coordTable) { std::vector<double> vecCoords; std::vector<int> vecStripLen; getCoordinatesFromTable(_coordTable, vecCoords, vecStripLen); Ptr<CustomGraphicsCoordinates> coordinates = CustomGraphicsCoordinates::create(vecCoords); cgEnt = cgGroup->addPointSet( coordinates, std::vector<int>(), UserDefinedCustomGraphicsPointType, _pointSetImage); } } else if (cgObjName == "Lines - Custom") { if (_coordTable) { std::vector<double> vecCoords; std::vector<int> vecStripLen; getCoordinatesFromTable(_coordTable, vecCoords, vecStripLen); Ptr<CustomGraphicsCoordinates> coordinates = CustomGraphicsCoordinates::create(vecCoords); bool isLineStrip = true; if (_isLineStrip) isLineStrip = _isLineStrip->value(); cgEnt = cgGroup->addLines(coordinates, std::vector<int>(), isLineStrip, vecStripLen); applyLinesProperties(cgEnt); } } // add attributes to the custom graphics entity if (cgEnt) { // color effect if (!cgEnt->cast<CustomGraphicsPointSet>()) // do not apply effect to point set node applyColorEffect(cgEnt); // transform Ptr<Matrix3D> transMat = Matrix3D::create(); double transformDistance = 1.0; if (_transform) transformDistance = _transform->value(); Ptr<Point3D> origin = Point3D::create(transformDistance, 0, 0); if (transMat && origin) { transMat->setWithCoordinateSystem( origin, Vector3D::create(1, 0, 0), Vector3D::create(0, 1, 0), Vector3D::create(0, 0, 1)); cgEnt->transform(transMat); } // calculate _scaleFactor and _anchorPt for viewPlacement, viewScale and billboarding attributes based // on the bounding box of custom graphics entity if (Ptr<BoundingBox3D> bbox = cgEnt->boundingBox()) { Ptr<Point3D> maxPt = bbox->maxPoint(); Ptr<Point3D> minPt = bbox->minPoint(); if (maxPt && minPt) { _scaleFactor = 100 / minPt->distanceTo(maxPt); _anchorPt->setWithArray( {(minPt->x() + maxPt->x()) / 2, (minPt->y() + maxPt->y()) / 2, (minPt->z() + maxPt->z()) / 2}); } } // view placement if (_viewPlacementGroup && _viewPlacementGroup->isVisible() && _viewPlacementGroup->isEnabledCheckBoxChecked() && _viewCorner && _viewCorner->selectedItem()) { Ptr<Point2D> viewPt = Point2D::create(100, 100); // upper left corner by default ViewCorners corner = ViewCorners::upperLeftViewCorner; Ptr<ListItem> selected = _viewCorner->selectedItem(); if (selected->name() == "Upper Right") corner = ViewCorners::upperRightViewCorner; else if (selected->name() == "Lower Left") corner = ViewCorners::lowerLeftViewCorner; else if (selected->name() == "Lower Right") corner = ViewCorners::lowerRightViewCorner; Ptr<CustomGraphicsViewPlacement> attr = CustomGraphicsViewPlacement::create(_anchorPt, corner, viewPt); cgEnt->viewPlacement(attr); } // view scale if (_viewScaleGroup && _viewScaleGroup->isVisible() && _viewScaleGroup->isEnabledCheckBoxChecked() && _pixelScale) { Ptr<CustomGraphicsViewScale> attr = CustomGraphicsViewScale::create(_scaleFactor * _pixelScale->valueOne(), _anchorPt); cgEnt->viewScale(attr); } // billboarding if (_billboardingGroup && _billboardingGroup->isVisible() && _billboardingGroup->isEnabledCheckBoxChecked() && _billboardingStyle && _billboardingStyle->selectedItem()) { // screen style by default CustomGraphicsBillBoardStyles bbStyle = CustomGraphicsBillBoardStyles::ScreenBillBoardStyle; Ptr<ListItem> selected = _billboardingStyle->selectedItem(); if (selected->name() == "Axis") bbStyle = CustomGraphicsBillBoardStyles::AxialBillBoardStyle; else if (selected->name() == "Right Reading") bbStyle = CustomGraphicsBillBoardStyles::RightReadingBillBoardStyle; Ptr<CustomGraphicsBillBoard> attr = CustomGraphicsBillBoard::create(_anchorPt); attr->axis(Vector3D::create(0, 1, 0)); attr->billBoardStyle(bbStyle); cgEnt->billBoarding(attr); } } } } }; // InputChange event handler. class OnInputChangedEventHander : public adsk::core::InputChangedEventHandler { public: void notify(const Ptr<InputChangedEventArgs>& eventArgs) override { if (!eventArgs) return; Ptr<CommandInput> changedInput = eventArgs->input(); if (!changedInput) return; std::string changedInputId = changedInput->id(); if (changedInputId == _commandId + "_cgObj") { if (_customGraphicsObj) { if (Ptr<ListItem> selectedItem = _customGraphicsObj->selectedItem()) { changeCGObjVisibility(selectedItem->name()); } } } else if (changedInputId == _commandId + "_colorEffects") { if (_colorEffects) { if (Ptr<ListItem> selectedItem = _colorEffects->selectedItem()) { changeColorEffectVisibility(selectedItem->name()); } } } else if (changedInputId == _commandId + "_appearanceFilter" || changedInputId == _commandId + "_materialLib") { std::string libName(""), filterExp(""); if (_materialLibList) { if (Ptr<ListItem> selectedItem = _materialLibList->selectedItem()) { libName = selectedItem->name(); } } if (_appearanceFilter) { filterExp = _appearanceFilter->value(); } std::vector<std::string> appearanceNames = getAppearancesFromLib(libName, filterExp); if (_appearanceList) { replaceItems(_appearanceList, appearanceNames); } } else if (_coordTable && changedInputId == _coordTable->id() + "_add") { addRow(_coordTable); } else if (_coordTable && changedInputId == _coordTable->id() + "_addStrip") { addLineStrip(_coordTable); } else if (_coordTable && changedInputId == _coordTable->id() + "_delete") { int selectedRowNo = _coordTable->selectedRow(); if (selectedRowNo == -1) { _ui->messageBox("Select one row to delete"); } else { _coordTable->deleteRow(selectedRowNo); } } else if (_lineStylePattern && changedInputId == _commandId + "_LSPattern") { changeLineStyleInputsVisibility(_lineStylePattern->selectedItem()->name()); } } }; // CommandDestroyed event handler class OnDestroyEventHandler : public adsk::core::CommandEventHandler { public: void notify(const Ptr<CommandEventArgs>& eventArgs) override { adsk::terminate(); } }; // CommandCreated event handler. class CommandCreatedEventHandler : public adsk::core::CommandCreatedEventHandler { public: void notify(const Ptr<CommandCreatedEventArgs>& eventArgs) override { if (eventArgs) { Ptr<Command> command = eventArgs->command(); if (command) { Ptr<CommandEvent> onDestroy = command->destroy(); if (!onDestroy) return; bool isOk = onDestroy->add(&onDestroyHandler_); if (!isOk) return; Ptr<InputChangedEvent> onInputChanged = command->inputChanged(); if (!onInputChanged) return; isOk = onInputChanged->add(&onInputChangedHandler_); if (!isOk) return; Ptr<CommandEvent> onExecute = command->execute(); if (!onExecute) return; isOk = onExecute->add(&onExecuteHandler_); if (!isOk) return; Ptr<CommandEvent> onExecutePtrview = command->executePreview(); if (!onExecutePtrview) return; isOk = onExecutePtrview->add(&onExecuteHandler_); if (!isOk) return; Ptr<CommandInputs> inputs = command->commandInputs(); if (!inputs) return; // menu for different kinds of custom graphics _customGraphicsObj = inputs->addDropDownCommandInput( _commandId + "_cgObj", "Custom Graphics Object", DropDownStyles::TextListDropDownStyle); if (_customGraphicsObj) { Ptr<ListItems> listItems = _customGraphicsObj->listItems(); if (listItems) { listItems->add("Mesh", true); listItems->add("Lines", false); listItems->add("PointSet", false); listItems->add("Curve", false); listItems->add("BRep", false); // listItems->add("Text", false); listItems->add("Lines - Custom", false); listItems->add("PointSet - Custom", false); } } // coordinates table used by 'Lines - Custom' and 'PointSet - Custom' _coordTable = inputs->addTableCommandInput(_commandId + "_table", "Coordinates Table", 3, "1:1:1"); if (_coordTable) { _coordTable->maximumVisibleRows(10); addRow(_coordTable); Ptr<CommandInput> addButtonInput = inputs->addBoolValueInput(_coordTable->id() + "_add", "Add", false, "", true); if (addButtonInput) { _coordTable->addToolbarCommandInput(addButtonInput); addButtonInput->isVisible(false); } Ptr<CommandInput> addStripButtonInput = inputs->addBoolValueInput(_coordTable->id() + "_addStrip", "Add Strip", false, "", true); if (addStripButtonInput) { _coordTable->addToolbarCommandInput(addStripButtonInput); addStripButtonInput->isVisible(false); } Ptr<CommandInput> deleteButtonInput = inputs->addBoolValueInput(_coordTable->id() + "_delete", "Delete", false, "", true); if (deleteButtonInput) { _coordTable->addToolbarCommandInput(deleteButtonInput); deleteButtonInput->isVisible(false); } _coordTable->isVisible(false); } // specific for 'Lines - Custom' _isLineStrip = inputs->addBoolValueInput(_commandId + "_isLineStrip", "Use LineStrip", true, "", true); if (_isLineStrip) { _isLineStrip->isVisible(false); } // color effects for custom graphics Mesh/BRep _colorEffects = inputs->addDropDownCommandInput( _commandId + "_colorEffects", "Color Effect", DropDownStyles::TextListDropDownStyle); if (_colorEffects) { Ptr<ListItems> listItems = _colorEffects->listItems(); if (listItems) { listItems->add(_colorEffect_solid_id, true); listItems->add(_colorEffect_basicMaterial_id, false); listItems->add(_colorEffect_appearance_id, false); listItems->add(_colorEffect_vertex_id, false); } } // RGB for solid colors _red = inputs->addIntegerSliderCommandInput(_commandId + "_red", "Red", 0, 255); if (_red) _red->valueOne(255); _green = inputs->addIntegerSliderCommandInput(_commandId + "_green", "Green", 0, 255); if (_green) _green->valueOne(0); _blue = inputs->addIntegerSliderCommandInput(_commandId + "_blue", "Blue", 0, 255); if (_blue) _blue->valueOne(0); // specific for basic material color effect _glossiness = inputs->addFloatSliderCommandInput(_commandId + "_glossiness", "Glossiness", "", 0, 128); if (_glossiness) { _glossiness->valueOne(128); _glossiness->isVisible(false); } _opacity = inputs->addFloatSliderCommandInput(_commandId + "_opacity", "Opacity", "", 0, 1); if (_opacity) { _opacity->valueOne(1); _opacity->isVisible(false); } // for appearance color effect std::string defaultMatLibName(""); _materialLibList = inputs->addDropDownCommandInput( _commandId + "_materialLib", "Material Library", DropDownStyles::TextListDropDownStyle); if (_materialLibList) { Ptr<ListItems> listItems = _materialLibList->listItems(); if (listItems) { std::vector<std::string> matLibNames = getMaterialLibNames(); for (std::string libName : matLibNames) { listItems->add(libName, false); } if (listItems->count() > 0) { Ptr<ListItem> item0 = listItems->item(0); if (item0) { item0->isSelected(true); defaultMatLibName = item0->name(); } } } _materialLibList->isVisible(false); } _appearanceList = inputs->addDropDownCommandInput( _commandId + "_appearanceList", "Appearance", DropDownStyles::TextListDropDownStyle); if (_appearanceList && !defaultMatLibName.empty()) { Ptr<ListItems> listItems = _appearanceList->listItems(); if (listItems) { std::vector<std::string> defaultAppearanceList = getAppearancesFromLib(defaultMatLibName, ""); for (std::string appearanceName : defaultAppearanceList) { listItems->add(appearanceName, false); } if (listItems->count() > 0) { Ptr<ListItem> item0 = listItems->item(0); if (item0) { item0->isSelected(true); } } } _appearanceList->isVisible(false); } _appearanceFilter = inputs->addStringValueInput(_commandId + "_appearanceFilter", "Filter"); if (_appearanceFilter) { _appearanceFilter->isVisible(false); } // selection input for custom graphics BRep/Curve _selection = inputs->addSelectionInput(_commandId + "_sel", "Selection", ""); if (_selection) { _selection->setSelectionLimits(0, 1); _selection->isVisible(false); _selection->isEnabled(false); } //// for custom graphics text //_text = inputs->addStringValueInput(_commandId + "_text", "Text", "This is a text."); // if (_text) { // _text->isVisible(false); //} // transform for all custom graphics entity if (Ptr<ValueInput> transformDistance = adsk::core::ValueInput::createByReal(0)) { _transform = inputs->addDistanceValueCommandInput(_commandId + "_transform", "Transform", transformDistance); if (_transform) { Ptr<Point3D> origin = adsk::core::Point3D::create(0, 0, 0); Ptr<Vector3D> direction = adsk::core::Vector3D::create(1, 0, 0); if (origin && direction) { _transform->setManipulator(origin, direction); } } } // for custom graphics line style pattern _lineStylePattern = inputs->addDropDownCommandInput( _commandId + "_LSPattern", "Line Style Pattern", DropDownStyles::TextListDropDownStyle); if (_lineStylePattern) { Ptr<ListItems> listItems = _lineStylePattern->listItems(); if (listItems) { listItems->add(_solidLine_id, true); listItems->add(_centerLine_id, false); listItems->add(_dashedLine_id, false); listItems->add(_dotLine_id, false); listItems->add(_phantomLine_id, false); listItems->add(_tracksLine_id, false); listItems->add(_zigZagLine_id, false); } _lineStylePattern->isVisible(false); } // for line style weight _lineStyleWeight = inputs->addIntegerSliderCommandInput(_commandId + "_LSWeight", "Line Style Weight", 1, 20); _lineStyleWeight->valueOne(1); _lineStyleWeight->isVisible(false); // for line style scale _lineStyleScale = inputs->addIntegerSliderCommandInput(_commandId + "_LSScale", "Line Style Scale", 1, 100); _lineStyleScale->valueOne(10); _lineStyleScale->isVisible(false); // for view placement attribute _viewPlacementGroup = inputs->addGroupCommandInput(_commandId + "_VPGroup", "View Placement"); if (_viewPlacementGroup) { _viewPlacementGroup->isEnabledCheckBoxDisplayed(true); _viewPlacementGroup->isEnabledCheckBoxChecked(false); if (Ptr<CommandInputs> childInputs = _viewPlacementGroup->children()) { _viewCorner = childInputs->addButtonRowCommandInput(_commandId + "_viewCorner", "corner", false); if (_viewCorner) { if (Ptr<ListItems> listItems = _viewCorner->listItems()) { listItems->add("Upper Left", false, "./resources/upperLeft"); listItems->add("Upper Right", false, "./resources/upperRight"); listItems->add("Lower Left", false, "./resources/lowerLeft"); listItems->add("Lower Right", false, "./resources/lowerRight"); } } } } // for view scale attribute _viewScaleGroup = inputs->addGroupCommandInput(_commandId + "_VSGroup", "View Scale"); if (_viewScaleGroup) { _viewScaleGroup->isEnabledCheckBoxDisplayed(true); _viewScaleGroup->isEnabledCheckBoxChecked(false); if (Ptr<CommandInputs> childInputs = _viewScaleGroup->children()) { _pixelScale = childInputs->addFloatSliderCommandInput( _commandId + "_pixelScale", "pixel scale", "", 0.5, 5, false); if (_pixelScale) { _pixelScale->valueOne(1); _pixelScale->setText("Smaller", "Larger"); } } } // for billboarding attribute _billboardingGroup = inputs->addGroupCommandInput(_commandId + "_BBGroup", "Billboarding"); if (_billboardingGroup) { _billboardingGroup->isEnabledCheckBoxDisplayed(true); _billboardingGroup->isEnabledCheckBoxChecked(false); if (Ptr<CommandInputs> childInputs = _billboardingGroup->children()) { _billboardingStyle = childInputs->addButtonRowCommandInput(_commandId + "_billboardingStyle", "style", false); if (_billboardingStyle) { if (Ptr<ListItems> listItems = _billboardingStyle->listItems()) { listItems->add("Screen", false, "./resources/One"); listItems->add("Axis", false, "./resources/Two"); listItems->add("Right Reading", false, "./resources/Three"); } } } } // } } } private: OnExecuteEventHandler onExecuteHandler_; OnDestroyEventHandler onDestroyHandler_; OnInputChangedEventHander onInputChangedHandler_; } cmdCreated_; extern "C" XI_EXPORT bool run(const char* context) { _app = Application::get(); if (!_app) return false; _ui = _app->userInterface(); if (!_ui) return false; Ptr<Document> doc = _app->activeDocument(); if (!doc) return false; Ptr<Products> prods = doc->products(); if (!prods) return false; Ptr<Product> prod = prods->itemByProductType("DesignProductType"); if (!prod) return false; _des = prod->cast<Design>(); if (!_des) return false; // get the entry for custom graphics Ptr<Product> activeProd = _app->activeProduct(); if (!activeProd) return false; Ptr<CAM> cam = activeProd->cast<CAM>(); if (cam) { _cgGroups = cam->customGraphicsGroups(); } else { Ptr<Component> rootComp = _des->rootComponent(); if (!rootComp) return false; _cgGroups = rootComp->customGraphicsGroups(); } if (!_cgGroups) return false; Ptr<CommandDefinition> command = createCommandDefinition(); if (!command) return false; Ptr<CommandCreatedEvent> commandCreatedEvent = command->commandCreated(); if (!commandCreatedEvent) return false; commandCreatedEvent->add(&cmdCreated_); command->execute(); // prevent this module from being terminate when the script returns, because we are waiting for event handlers to // fire adsk::autoTerminate(false); return true; } #ifdef XI_WIN #include <windows.h> BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved) { switch (reason) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } #endif // XI_WIN
#Author-Autodesk Inc. #Description-Demo custom graphics examples import adsk.core, adsk.fusion, adsk.cam, traceback import math # Globals _app = adsk.core.Application.cast(None) _ui = adsk.core.UserInterface.cast(None) _des = adsk.fusion.Design.cast(None) _cgGroups = adsk.fusion.CustomGraphicsGroups.cast(None) _numTeeth = 5 _handlers = [] appearancesMap = {} coordNumber = 0 stripNumber = 0 _pointSetImage = './resources/16x16.png' _thickness = 0.5 * 2.54 _anchorPt = adsk.core.Point3D.cast(None) #_scaleFactor is used to limit the size of pixel-scaled model however large the actual graphics model. _scaleFactor = 10 _commandId = 'CustomGraphicsSample_Python' _colorEffect_solid_id = 'SolidColorEfect' _colorEffect_basicMaterial_id = 'BasicMaterialColorEffect' _colorEffect_appearance_id = 'AppearanceColorEffect' _colorEffect_vertex_id = 'VertexColorEffect' # Global Command inputs _customGraphicsObj = adsk.core.DropDownCommandInput.cast(None) _colorEffects = adsk.core.DropDownCommandInput.cast(None) _red = adsk.core.IntegerSliderCommandInput.cast(None) _green = adsk.core.IntegerSliderCommandInput.cast(None) _blue = adsk.core.IntegerSliderCommandInput.cast(None) _opacity = adsk.core.SliderCommandInput.cast(None) _glossiness = adsk.core.SliderCommandInput.cast(None) #_text = adsk.core.StringValueCommandInput.cast(None) _selection = adsk.core.SelectionCommandInput.cast(None) _transform = adsk.core.DistanceValueCommandInput.cast(None) _materialLibList = adsk.core.DropDownCommandInput.cast(None) _appearanceList = adsk.core.DropDownCommandInput.cast(None) _appearanceFilter = adsk.core.StringValueCommandInput.cast(None) _coordTable = adsk.core.TableCommandInput.cast(None) _add = adsk.core.BoolValueCommandInput.cast(None) _addStrip = adsk.core.BoolValueCommandInput.cast(None) _delete = adsk.core.BoolValueCommandInput.cast(None) _isLineStrip = adsk.core.BoolValueCommandInput.cast(None) _lineStylePattern = adsk.core.DropDownCommandInput.cast(None) _lineStyleWeight = adsk.core.IntegerSliderCommandInput.cast(None) _lineStyleScale = adsk.core.IntegerSliderCommandInput.cast(None) _viewPlacementGroup = adsk.core.GroupCommandInput.cast(None) _viewCorner = adsk.core.ButtonRowCommandInput.cast(None) _viewScaleGroup = adsk.core.GroupCommandInput.cast(None) _pixelScale = adsk.core.FloatSliderCommandInput.cast(None) _billboardingGroup = adsk.core.GroupCommandInput.cast(None) _billboardingStyle = adsk.core.ButtonRowCommandInput.cast(None) def run(context): try: global _app, _ui, _des, _cgGroups _app = adsk.core.Application.get() _ui = _app.userInterface doc = _app.activeDocument prods = doc.products _des = prods.itemByProductType('DesignProductType') if not _des: raise Exception('Failed to get fusion design.') # get the entry for custom graphics activeProd = _app.activeProduct cam = adsk.cam.CAM.cast(activeProd) if cam: _cgGroups = cam.customGraphicsGroups else: _cgGroups = _des.rootComponent.customGraphicsGroups cmdDef = _ui.commandDefinitions.itemById(_commandId) if not cmdDef: # Create a command definition. cmdDef = _ui.commandDefinitions.addButtonDefinition(_commandId, 'CustomGraphicsSample', 'Custom Graphics Sample') # Connect to the command created event. onCommandCreated = MyCommandCreatedHandler() cmdDef.commandCreated.add(onCommandCreated) _handlers.append(onCommandCreated) # Execute the command. cmdDef.execute() # prevent this module from being terminate when the script returns, because we are waiting for event handlers to fire adsk.autoTerminate(False) except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class MyCommandDestroyHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: # eventArgs = adsk.core.CommandEventArgs.cast(args) # when the command is done, terminate the script # this will release all globals which will remove all event handlers adsk.terminate() except: if _ui: _ui.messageBox('Failed in MyCommandDestroyHandler:\n{}'.format(traceback.format_exc())) def addRow(tableInput): global coordNumber tableChildInputs = tableInput.commandInputs xValueInput = tableChildInputs.addValueInput(_coordTable.id + '_x{}'.format(coordNumber), 'Value', 'cm', adsk.core.ValueInput.createByReal(coordNumber)) yValueInput = tableChildInputs.addValueInput(_coordTable.id + '_y{}'.format(coordNumber), 'Value', 'cm', adsk.core.ValueInput.createByReal(coordNumber)) zValueInput = tableChildInputs.addValueInput(_coordTable.id + '_z{}'.format(coordNumber), 'Value', 'cm', adsk.core.ValueInput.createByReal(coordNumber)) row = tableInput.rowCount tableInput.addCommandInput(xValueInput, row, 0) tableInput.addCommandInput(yValueInput, row, 1) tableInput.addCommandInput(zValueInput, row, 2) coordNumber = coordNumber + 1 def addLineStrip(tableInput): global stripNumber tableChildInputs = tableInput.commandInputs strInput = tableChildInputs.addStringValueInput(_coordTable.id + '_strip{}'.format(stripNumber), 'Line Strip', '-- Line Strip --') strInput.isReadOnly = True row = tableInput.rowCount tableInput.addCommandInput(strInput, row, 0, 0, 2) stripNumber = stripNumber + 1 def replaceItems(cmdInput, newItems): try: cmdInput.listItems.clear() itemNone = cmdInput.listItems.add('None', True, '') itemNone.isSelected = True if len(newItems) > 0: for item in newItems: cmdInput.listItems.add(item, False, '') cmdInput.listItems[1].isSelected = True cmdInput.listItems[0].deleteMe() except: if _ui: _ui.messageBox('Failed in replaceItems:\n{}'.format(traceback.format_exc())) def getAppearancesFromLib(libName, filterExp): try: global appearancesMap appearanceList = None if libName in appearancesMap: appearanceList = appearancesMap[libName] else: materialLib = _app.materialLibraries.itemByName(libName) appearances = materialLib.appearances appearanceNames = [] for appearance in appearances: appearanceNames.append(appearance.name) appearancesMap[libName] = appearanceNames appearanceList = appearanceNames if filterExp and len(filterExp) > 0: filteredList = [] for appearanceName in appearanceList: if appearanceName.lower().find(filterExp.lower()) >= 0: filteredList.append(appearanceName) return filteredList else: return appearanceList except: if _ui: _ui.messageBox('Failed in getAppearancesFromLib:\n{}'.format(traceback.format_exc())) def hasAppearances(lib): if lib and lib.appearances.count > 0: return True return False def getMaterialLibNames(libFilter): materialLibs = _app.materialLibraries libNames = [] for materialLib in materialLibs: if (not libFilter) or libFilter(materialLib): libNames.append(materialLib.name) return libNames def getAppearance(libName, appearanceName): try: if not appearanceName or appearanceName == 'None': return appearance = _des.appearances.itemByName(appearanceName) if appearance: return appearance matLib = _app.materialLibraries.itemByName(libName) if matLib: appearance = matLib.appearances.itemByName(appearanceName) return appearance except: if _ui: _ui.messageBox('Failed in getAppearance:\n{}'.format(traceback.format_exc())) # Event handler for the commandCreated event. class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CommandCreatedEventArgs.cast(args) # Verify that a Fusion design is active. if not _des: _ui.messageBox('A Fusion design must be active when invoking this command.') return() cmd = eventArgs.command cmd.isExecutedWhenPreEmpted = False inputs = cmd.commandInputs global _customGraphicsObj, _selection, _coordTable, _add, _delete global _colorEffects,_glossiness, _opacity, _transform, _isLineStrip, _addStrip, _lineStyleWeight, _lineStyleScale, _lineStylePattern global _red,_green,_blue, _appearanceList, _materialLibList, _appearanceFilter # menu for different kinds of custom graphics _customGraphicsObj = inputs.addDropDownCommandInput(_commandId + '_cgObj', 'Custom Graphics Object', adsk.core.DropDownStyles.TextListDropDownStyle) _customGraphicsObj.listItems.add('Mesh', True) _customGraphicsObj.listItems.add('Lines', False) _customGraphicsObj.listItems.add('PointSet', False) _customGraphicsObj.listItems.add('Curve', False) _customGraphicsObj.listItems.add('BRep', False) #_customGraphicsObj.listItems.add('Text', False) _customGraphicsObj.listItems.add('Lines - Custom', False) _customGraphicsObj.listItems.add('PointSet - Custom', False) # coordinates table used by 'Lines - Custom' and 'PointSet - Custom' _coordTable = inputs.addTableCommandInput(_commandId + '_table', 'Coordinates Table', 3, '1:1:1') _coordTable.maximumVisibleRows = 10 addRow(_coordTable) _add = inputs.addBoolValueInput(_coordTable.id + '_add', 'Add', False, '', True) _coordTable.addToolbarCommandInput(_add) _addStrip = inputs.addBoolValueInput(_coordTable.id + '_addStrip', 'AddStrip', False, '', True) _coordTable.addToolbarCommandInput(_addStrip) _delete = inputs.addBoolValueInput(_coordTable.id + '_delete', 'Delete', False, '', True) _coordTable.addToolbarCommandInput(_delete) _coordTable.isVisible = False _add.isVisible = False _delete.isVisible = False _addStrip.isVisible = False # specific for 'Lines - Custom' _isLineStrip = inputs.addBoolValueInput(_commandId + '_isLineStrip', 'Use LineStrip', True, '', True) _isLineStrip.isVisible = False # color effects for custom graphics Mesh/BRep _colorEffects = inputs.addDropDownCommandInput(_commandId + '_colorEffects', 'Color Effect', adsk.core.DropDownStyles.TextListDropDownStyle) _colorEffects.listItems.add(_colorEffect_solid_id, True) _colorEffects.listItems.add(_colorEffect_basicMaterial_id, False) _colorEffects.listItems.add(_colorEffect_appearance_id, False) _colorEffects.listItems.add(_colorEffect_vertex_id, False) # RGB for solid colors _red = inputs.addIntegerSliderCommandInput(_commandId + '_red', 'Red', 0, 255, False) _red.valueOne = 255 _green = inputs.addIntegerSliderCommandInput(_commandId + '_green', 'Green', 0, 255, False) _green.valueOne = 0 _blue = inputs.addIntegerSliderCommandInput(_commandId + '_blue', 'Blue', 0, 255, False) _blue.valueOne = 0 # specific for basic material color effect _glossiness = inputs.addFloatSliderCommandInput(_commandId + '_glossiness', 'Glossiness', '', 0.0, 128.0, False) _glossiness.valueOne = 128.0 _glossiness.isVisible = False _opacity = inputs.addFloatSliderCommandInput(_commandId + '_opacity', 'Opacity', '', 0.0, 1.0, False) _opacity.valueOne = 1.0 _opacity.isVisible = False # for appearance color effect _materialLibList = inputs.addDropDownCommandInput(_commandId + '_materialLib', 'Material Library', adsk.core.DropDownStyles.TextListDropDownStyle) listItems = _materialLibList.listItems materialLibNames = getMaterialLibNames(hasAppearances) for materialName in materialLibNames: listItems.add(materialName, False, '') listItems[0].isSelected = True _materialLibList.isVisible = False _appearanceList = inputs.addDropDownCommandInput(_commandId + '_appearanceList', 'Appearance', adsk.core.DropDownStyles.TextListDropDownStyle) appearances = getAppearancesFromLib(materialLibNames[0], '') listItems = _appearanceList.listItems for appearanceName in appearances: listItems.add(appearanceName, False, '') listItems[0].isSelected = True _appearanceList.isVisible = False _appearanceFilter = inputs.addStringValueInput(_commandId + '_appearanceFilter', 'Filter', '') _appearanceFilter.isVisible = False # selection input for custom graphics BRep/Curve _selection = inputs.addSelectionInput(_commandId + '_sel', 'Selection', '') _selection.setSelectionLimits(0, 1) _selection.isVisible = False _selection.isEnabled = False # for custom graphics text #_text = inputs.addStringValueInput(_commandId + '_text', 'Text', 'This is a text.') #_text.isVisible = False # transform for all custom graphics entity _transform = inputs.addDistanceValueCommandInput(_commandId + '_transform', 'Transform', adsk.core.ValueInput.createByReal(0)) _transform.setManipulator( adsk.core.Point3D.create(0,0,0), adsk.core.Vector3D.create(1,0,0)) # menu for different kinds of line sytles _lineStylePattern = inputs.addDropDownCommandInput(_commandId + '_LSPattern', 'Line Style Pattern', adsk.core.DropDownStyles.TextListDropDownStyle) _lineStylePattern.listItems.add('Solid Line', True) _lineStylePattern.listItems.add('Center Line', False) _lineStylePattern.listItems.add('Dashed Line', False) _lineStylePattern.listItems.add('Dot Line', False) _lineStylePattern.listItems.add('Phantom Line', False) _lineStylePattern.listItems.add('Tracks Line', False) _lineStylePattern.listItems.add('ZigZag Line', False) _lineStylePattern.isVisible = False # for line sytle weight _lineStyleWeight = inputs.addIntegerSliderCommandInput(_commandId + '_LSWeight', 'Line Style Weight', 1, 20, False) _lineStyleWeight.valueOne = 1 _lineStyleWeight.isVisible = False # for line style scale _lineStyleScale = inputs.addIntegerSliderCommandInput(_commandId + '_LSScale', 'Line Style Scale', 1, 100, False) _lineStyleScale.valueOne = 10 _lineStyleScale.isVisible = False global _viewPlacementGroup, _viewCorner, _viewScaleGroup, _pixelScale, _billboardingGroup, _billboardingStyle # for view placement attribute _viewPlacementGroup = inputs.addGroupCommandInput(_commandId + '_VPGroup', 'View Placement') _viewPlacementGroup.isEnabledCheckBoxDisplayed = True _viewPlacementGroup.isEnabledCheckBoxChecked = False _viewCorner = _viewPlacementGroup.children.addButtonRowCommandInput(_commandId + '_viewCorner', 'corner', False) _viewCorner.listItems.add('Upper Left', False, './resources/upperLeft') _viewCorner.listItems.add('Upper Right', False, './resources/upperRight') _viewCorner.listItems.add('Lower Left', False, './resources/lowerLeft') _viewCorner.listItems.add('Lower Right', False, './resources/lowerRight') # for view scale attribute _viewScaleGroup = inputs.addGroupCommandInput(_commandId + '_VSGroup', 'View Scale') _viewScaleGroup.isEnabledCheckBoxDisplayed = True _viewScaleGroup.isEnabledCheckBoxChecked = False _pixelScale = _viewScaleGroup.children.addFloatSliderCommandInput(_commandId + '_pixelScale', 'pixel scale', '', 0.5, 5, False) _pixelScale.valueOne = 1 _pixelScale.setText('Smaller', 'Larger') # for billboarding attribute _billboardingGroup = inputs.addGroupCommandInput(_commandId + '_BBGroup', 'Billboarding') _billboardingGroup.isEnabledCheckBoxDisplayed = True _billboardingGroup.isEnabledCheckBoxChecked = False _billboardingStyle = _billboardingGroup.children.addButtonRowCommandInput(_commandId + '_billboardingStyle', 'style', False) _billboardingStyle.listItems.add('Screen', False, './resources/One') _billboardingStyle.listItems.add('Axis', False, './resources/Two') _billboardingStyle.listItems.add('Right Reading', False, './resources/Three') # Connect to the command related events. onExecute = MyCommandExecuteHandler() cmd.execute.add(onExecute) _handlers.append(onExecute) onExecutePreview = MyCommandExecuteHandler() cmd.executePreview.add(onExecutePreview) _handlers.append(onExecutePreview) onInputChanged = MyCommandInputChangedHandler() cmd.inputChanged.add(onInputChanged) _handlers.append(onInputChanged) onDestroy = MyCommandDestroyHandler() cmd.destroy.add(onDestroy) _handlers.append(onDestroy) except: if _ui: _ui.messageBox('Failed in MyCommandCreatedHandler:\n{}'.format(traceback.format_exc())) def applyColorEffect(cgEnt): try: colorEffect = None if _colorEffects.selectedItem.name == _colorEffect_solid_id: colorEffect = adsk.fusion.CustomGraphicsSolidColorEffect.create(adsk.core.Color.create(int(_red.valueOne),int(_green.valueOne),int(_blue.valueOne),255)) elif _colorEffects.selectedItem.name == _colorEffect_basicMaterial_id: diffuseColor = adsk.core.Color.create(0,255,0,255) ambientColor = adsk.core.Color.create(255,0,0,255) specularColor = adsk.core.Color.create(0,0,255,255) emissiveColor = adsk.core.Color.create(0,0,0,255) colorEffect = adsk.fusion.CustomGraphicsBasicMaterialColorEffect.create(diffuseColor, ambientColor, specularColor, emissiveColor, float(_glossiness.valueOne), float(_opacity.valueOne)) elif _colorEffects.selectedItem.name == _colorEffect_appearance_id: appearance = getAppearance(_materialLibList.selectedItem.name, _appearanceList.selectedItem.name) if appearance: if not _des.appearances.itemByName(appearance.name): appearance = _des.appearances.addByCopy(appearance, appearance.name) colorEffect = adsk.fusion.CustomGraphicsAppearanceColorEffect.create(appearance) elif _colorEffects.selectedItem.name == _colorEffect_vertex_id: colorEffect = adsk.fusion.CustomGraphicsVertexColorEffect.create() if colorEffect: cgEnt.color = colorEffect except: if _ui: _ui.messageBox('Failed in applyColorEffect:\n{}'.format(traceback.format_exc())) def getCoordinatesFromTable(tableInput): try: vecCoord = [] vecStripLen = [] stripLen = 0 if _coordTable: for i in range(0, _coordTable.rowCount): xValueInput = adsk.core.ValueCommandInput.cast(_coordTable.getInputAtPosition(i,0)) if xValueInput: stripLen = stripLen + 1 yValueInput = adsk.core.ValueCommandInput.cast(_coordTable.getInputAtPosition(i,1)) zValueInput = adsk.core.ValueCommandInput.cast(_coordTable.getInputAtPosition(i,2)) vecCoord.extend([xValueInput.value, yValueInput.value, zValueInput.value]) else: vecStripLen.append(stripLen) stripLen = 0 vecStripLen.append(stripLen) return vecCoord, vecStripLen except: if _ui: _ui.messageBox('Failed in getCoordinatesFromTable:\n{}'.format(traceback.format_exc())) # Event handler for the execute event. class MyCommandExecuteHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: # get selection entity first since it's fragile and any creation/edit operations will clear the selection. selEntity = None if _selection.selectionCount > 0: selEntity = _selection.selection(0).entity if _customGraphicsObj: cgGroup = adsk.fusion.CustomGraphicsGroup.cast(_cgGroups.add()) global _anchorPt, _scaleFactor if not _anchorPt: _anchorPt = adsk.core.Point3D.create(0,0,0) cgEnt = None if _customGraphicsObj.selectedItem.name == 'Mesh': cgEnt = drawMesh(cgGroup) _anchorPt.setWithArray([0,0,_thickness/2]) elif _customGraphicsObj.selectedItem.name == 'Lines': cgEnt = drawLines(cgGroup) _anchorPt.setWithArray([0,0,_thickness/2]) elif _customGraphicsObj.selectedItem.name == 'PointSet': cgEnt = drawPointSet(cgGroup) elif _customGraphicsObj.selectedItem.name == 'BRep': if selEntity: body = adsk.fusion.BRepBody.cast(selEntity) cgEnt = cgGroup.addBRepBody(body) elif _customGraphicsObj.selectedItem.name == 'Curve': if selEntity: skCurve = adsk.fusion.SketchCurve.cast(selEntity) sk = skCurve.parentSketch curve = skCurve.geometry curve.transformBy(sk.transform) cgEnt = cgGroup.addCurve(curve) cgEnt.weight = float(_lineStyleWeight.valueOne) #elif _customGraphicsObj.selectedItem.name == 'Text': # if _text.value: # cgEnt = cgGroup.addText(_text.value, 'None', 10, adsk.core.Point3D.create(0,0,0)) elif _customGraphicsObj.selectedItem.name == 'PointSet - Custom': vecCoords, vecStripLen = getCoordinatesFromTable(_coordTable) coords = adsk.fusion.CustomGraphicsCoordinates.create(vecCoords) cgEnt = cgGroup.addPointSet(coords, [], adsk.fusion.CustomGraphicsPointTypes.UserDefinedCustomGraphicsPointType, _pointSetImage) elif _customGraphicsObj.selectedItem.name == 'Lines - Custom': vecCoords, vecStripLength = getCoordinatesFromTable(_coordTable) coords = adsk.fusion.CustomGraphicsCoordinates.create(vecCoords) isLineStrip = _isLineStrip.value if coords.coordinateCount < 1: return cgEnt = cgGroup.addLines(coords, [], isLineStrip, vecStripLength) # add attributes to the custom graphics entity if cgEnt: # transform transMat = adsk.core.Matrix3D.create() origin = adsk.core.Point3D.create(float(_transform.value),0,0) transMat.setWithCoordinateSystem(origin, adsk.core.Vector3D.create(1,0,0), adsk.core.Vector3D.create(0,1,0), adsk.core.Vector3D.create(0,0,1)) cgEnt.transform = transMat # color effect if not adsk.fusion.CustomGraphicsPointSet.cast(cgEnt): applyColorEffect(cgEnt) # calculate _scaleFactor and _anchorPt for viewPlacement, viewScale and billboarding attributes based on the bounding box of custom graphics entity maxPt = cgEnt.boundingBox.maxPoint minPt = cgEnt.boundingBox.minPoint _scaleFactor = 100 / minPt.distanceTo(maxPt) _anchorPt.setWithArray([(minPt.x + maxPt.x) / 2, (minPt.y + maxPt.y) / 2, (minPt.z + maxPt.z) / 2]) # view placement if _viewPlacementGroup and _viewPlacementGroup.isVisible and _viewPlacementGroup.isEnabledCheckBoxChecked and _viewCorner and _viewCorner.selectedItem: viewPt = adsk.core.Point2D.create(100,100) # upper left by default corner = adsk.fusion.ViewCorners.upperLeftViewCorner if _viewCorner.selectedItem.name == 'Upper Right': corner = adsk.fusion.ViewCorners.upperRightViewCorner elif _viewCorner.selectedItem.name == 'Lower Left': corner = adsk.fusion.ViewCorners.lowerLeftViewCorner elif _viewCorner.selectedItem.name == 'Lower Right': corner = adsk.fusion.ViewCorners.lowerRightViewCorner attr = adsk.fusion.CustomGraphicsViewPlacement.create(_anchorPt, corner, viewPt) cgEnt.viewPlacement = attr # view scale if _viewScaleGroup and _viewScaleGroup.isVisible and _viewScaleGroup.isEnabledCheckBoxChecked and _pixelScale: attr = adsk.fusion.CustomGraphicsViewScale.create(_scaleFactor * _pixelScale.valueOne, _anchorPt) cgEnt.viewScale = attr # billboarding if _billboardingGroup and _billboardingGroup.isVisible and _billboardingGroup.isEnabledCheckBoxChecked and _billboardingStyle and _billboardingStyle.selectedItem: # screen style by default bbStyle = adsk.fusion.CustomGraphicsBillBoardStyles.ScreenBillBoardStyle if _billboardingStyle.selectedItem.name == 'Axis': bbStyle = adsk.fusion.CustomGraphicsBillBoardStyles.AxialBillBoardStyle elif _billboardingStyle.selectedItem.name == 'Right Reading': bbStyle = adsk.fusion.CustomGraphicsBillBoardStyles.RightReadingBillBoardStyle attr = adsk.fusion.CustomGraphicsBillBoard.create(_anchorPt) attr.axis = adsk.core.Vector3D.create(0,1,0) attr.billBoardStyle = bbStyle cgEnt.billBoarding = attr except: if _ui: _ui.messageBox('Failed in MyCommandExecuteHandler:\n{}'.format(traceback.format_exc())) def changeCGObjVisibility(strObjName): try: _colorEffects.listItems.clear() _colorEffects.listItems.add(_colorEffect_solid_id, True) _colorEffects.listItems.add(_colorEffect_basicMaterial_id, False) _colorEffects.listItems.add(_colorEffect_appearance_id, False) _colorEffects.isVisible = False _selection.clearSelection() _selection.clearSelectionFilter() _selection.setSelectionLimits(0, 0) _selection.isVisible = False _selection.isEnabled = False #_text.isVisible = False _coordTable.isVisible = False _isLineStrip.isVisible = False _lineStylePattern.isVisible = False _lineStyleWeight.isVisible = False _lineStyleScale.isVisible = False changeColorEffectVisibility(None) _viewPlacementGroup.isVisible = False _viewScaleGroup.isVisible = False _billboardingGroup.isVisible = False if strObjName == 'Mesh': _colorEffects.isVisible = True _colorEffects.listItems.add(_colorEffect_vertex_id, False) changeColorEffectVisibility(_colorEffect_solid_id) _viewPlacementGroup.isVisible = True _viewScaleGroup.isVisible = True _billboardingGroup.isVisible = True elif strObjName == 'Lines': changeColorEffectVisibility(_colorEffect_solid_id) _lineStylePattern.isVisible = True _lineStyleWeight.isVisible = True if _lineStylePattern.selectedItem.name != 'Solid Line': _lineStyleScale.isVisible = True _viewPlacementGroup.isVisible = True _viewScaleGroup.isVisible = True _billboardingGroup.isVisible = True elif strObjName == 'Curve': _selection.isVisible = True _selection.isEnabled = True _selection.tooltip = 'select a curve' _selection.commandPrompt = 'select a curve' _selection.addSelectionFilter('SketchCurves') _selection.setSelectionLimits(1,1) changeColorEffectVisibility(_colorEffect_solid_id) _lineStyleWeight.isVisible = True _viewPlacementGroup.isVisible = True _viewScaleGroup.isVisible = True _billboardingGroup.isVisible = True elif strObjName == 'BRep': _selection.isVisible = True _selection.isEnabled = True _selection.tooltip = 'select a body' _selection.commandPrompt = 'select a body' _selection.addSelectionFilter('Bodies') _selection.setSelectionLimits(1,1) _colorEffects.isVisible = True changeColorEffectVisibility(_colorEffect_solid_id) _viewPlacementGroup.isVisible = True _viewScaleGroup.isVisible = True _billboardingGroup.isVisible = True #elif strObjName == 'Text': # _text.isVisible = True # changeColorEffectVisibility(_colorEffect_solid_id) elif strObjName == 'PointSet - Custom': _coordTable.isVisible = True _addStrip.isEnabled = False elif strObjName == 'Lines - Custom': _coordTable.isVisible = True _isLineStrip.isVisible = True _addStrip.isEnabled = True changeColorEffectVisibility(_colorEffect_solid_id) _lineStylePattern.isVisible = True _lineStyleWeight.isVisible = True if _lineStylePattern.selectedItem.name != 'Solid Line': _lineStyleScale.isVisible = True except: if _ui: _ui.messageBox('Failed in changeCGObjVisibility:\n{}'.format(traceback.format_exc())) def changeColorEffectVisibility(strColorEffectName): try: _red.isVisible = False _green.isVisible = False _blue.isVisible = False _opacity.isVisible = False _glossiness.isVisible = False _appearanceList.isVisible = False _materialLibList.isVisible = False _appearanceFilter.isVisible = False if strColorEffectName == _colorEffect_solid_id: _red.isVisible = True _green.isVisible = True _blue.isVisible = True elif strColorEffectName == _colorEffect_basicMaterial_id: _opacity.isVisible = True _glossiness.isVisible = True elif strColorEffectName == _colorEffect_appearance_id: _appearanceList.isVisible = True _materialLibList.isVisible = True _appearanceFilter.isVisible = True except: if _ui: _ui.messageBox('Failed in changeColorEffectVisibility:\n{}'.format(traceback.format_exc())) def changeLineStyleInputsVisibility(patternName): try: if patternName == 'Solid Line': _lineStyleScale.isVisible = False else: _lineStyleScale.isVisible = True except: if _ui: _ui.messageBox('Failed in changeLineStyleInputsVisibility:\n{}'.format(traceback.format_exc())) # Event handler for the inputChanged event. class MyCommandInputChangedHandler(adsk.core.InputChangedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.InputChangedEventArgs.cast(args) changedInput = eventArgs.input if changedInput.id == _commandId + '_cgObj': changeCGObjVisibility(_customGraphicsObj.selectedItem.name) elif changedInput.id == _commandId + '_colorEffects': changeColorEffectVisibility(_colorEffects.selectedItem.name) elif changedInput.id == _commandId + '_appearanceFilter' or changedInput.id == _commandId + '_materialLib': appearances = getAppearancesFromLib(_materialLibList.selectedItem.name, _appearanceFilter.value) replaceItems(_appearanceList, appearances) elif changedInput.id == _coordTable.id + '_add': addRow(_coordTable) elif changedInput.id == _coordTable.id + '_addStrip': addLineStrip(_coordTable) elif changedInput.id == _coordTable.id + '_delete': if _coordTable.selectedRow == -1: _ui.messageBox('Select one row to delete') else: _coordTable.deleteRow(_coordTable.selectedRow) elif changedInput.id == _commandId + '_LSPattern': changeLineStyleInputsVisibility(_lineStylePattern.selectedItem.name) except: if _ui: _ui.messageBox('Failed in MyCommandInputChangedHandler:\n{}'.format(traceback.format_exc())) def rotate2D(rad, vec): try: x = vec[0] y = vec[1] return (x*math.cos(rad)-y*math.sin(rad), x*math.sin(rad)+y*math.cos(rad)) except: if _ui: _ui.messageBox('Failed in rotate2D:\n{}'.format(traceback.format_exc())) def calculateCoordinates(numTeeth): try: # holeDia < rootDia < pitchDia < outsideDia holeDia = 0.5 * 2.54 diametralPitch = 2 / 2.54 pitchDia = numTeeth / diametralPitch if (diametralPitch < (20 *(math.pi/180))-0.000001): dedendum = 1.157 / diametralPitch else: circularPitch = math.pi / diametralPitch if circularPitch >= 20: dedendum = 1.25 / diametralPitch else: dedendum = (1.2 / diametralPitch) + (.002 * 2.54) rootDia = pitchDia - (2 * dedendum) outsideDia = (numTeeth + 2) / diametralPitch rPts0 = [] # 2 * numTeeth for root hPts0 = [] # 2 * numTeeth for hole pPts0 = [] # 2 * numTeeth for pitch oPts0 = [] # 1 * numTeeth for outside rPts1 = [] # 2 * numTeeth for root with thickness hPts1 = [] # 2 * numTeeth for hole with thickness pPts1 = [] # 2 * numTeeth for pitch with thickness oPts1 = [] # 1 * numTeeth for outside with thickness vecRootRadi = [rootDia/2.0, 0] vecHoleRadi = [holeDia/2.0, 0] vecPitchRadi = [pitchDia/2.0, 0] vecOutRadi = [outsideDia/2.0, 0] unitRadian = math.pi / numTeeth vecCoords = [] vecColors = [] for i in range(0, 2 * numTeeth): x, y = rotate2D(unitRadian * (i - 0.5), vecRootRadi) rPts0.append(int(len(vecCoords) / 3)) rPts1.append(int(len(vecCoords) / 3) + 1) vecCoords.extend([x, y, 0, x, y, _thickness]) vecColors.extend([255,0,255,128, 255,0,255,128]) for i in range(0, 2 * numTeeth): x, y = rotate2D(unitRadian * (i - 0.5), vecHoleRadi) hPts0.append(int(len(vecCoords) / 3)) hPts1.append(int(len(vecCoords) / 3) + 1) vecCoords.extend([x, y, 0, x, y, _thickness]) vecColors.extend([255,0,0,128, 255,0,0,128]) for i in range(0, 2 * numTeeth): x, y = rotate2D(unitRadian * (i - 0.5), vecPitchRadi) pPts0.append(int(len(vecCoords) / 3)) pPts1.append(int(len(vecCoords) / 3) + 1) vecCoords.extend([x, y, 0, x, y, _thickness]) vecColors.extend([0,0,255,128, 0,0,255,128]) for i in range(0, numTeeth): x, y = rotate2D(unitRadian * i * 2 , vecOutRadi) oPts0.append(int(len(vecCoords) / 3)) oPts1.append(int(len(vecCoords) / 3) + 1) vecCoords.extend([x, y, 0, x, y, _thickness]) vecColors.extend([0,255,255,128, 0,255,255,128]) return (rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1, vecCoords, vecColors) except: if _ui: _ui.messageBox('Failed in calculateCoordinates:\n{}'.format(traceback.format_exc())) def calculateStripLen(numTeeth): try: vecStripLen = [] for i in range(0, numTeeth): vecStripLen.append(6) for i in range(0, 2 * numTeeth): vecStripLen.append(21) for i in range(0, numTeeth): vecStripLen.append(24) for i in range(0, 2 * numTeeth): vecStripLen.append(6) return vecStripLen except Exception as error: _ui.messageBox("calculateTriangles Failed : " + str(error)) def calculateTriangles(numTeeth, rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1): try: vertexIndexList = [] # triangles between teeth for i in range(0, numTeeth): idx0 = (2*i+1) % (2*numTeeth) idx1 = (2*i+2) % (2*numTeeth) rPtA0 = rPts0[idx0] rPtB0 = rPts0[idx1] rPtA1 = rPts1[idx0] rPtB1 = rPts1[idx1] vertexIndexList.extend([rPtA0,rPtB0,rPtB1, rPtB1,rPtA1,rPtA0]) # triangles on surface0 for i in range(0, numTeeth): rPtA = rPts0[i*2] rPtB = rPts0[i*2 + 1] rPtC = rPts0[(i*2 + 2)%(2*numTeeth)] hPtA = hPts0[i*2] hPtB = hPts0[i*2 + 1] hPtC = hPts0[(i*2 + 2)%(2*numTeeth)] pPtA = pPts0[i*2] pPtB = pPts0[i*2 + 1] oPt = oPts0[i] vertexIndexList.extend([hPtB,hPtC,rPtC, rPtC,rPtB,hPtB]) vertexIndexList.extend([rPtA,rPtB,pPtB, pPtB,pPtA,rPtA]) vertexIndexList.extend([hPtA,hPtB,rPtB, rPtB,rPtA,hPtA]) vertexIndexList.extend([pPtA,pPtB,oPt]) # triangles on surface1 for i in range(0, numTeeth): rPtA = rPts1[i*2] rPtB = rPts1[i*2 + 1] rPtC = rPts1[(i*2 + 2)%(2*numTeeth)] hPtA = hPts1[i*2] hPtB = hPts1[i*2 + 1] hPtC = hPts1[(i*2 + 2)%(2*numTeeth)] pPtA = pPts1[i*2] pPtB = pPts1[i*2 + 1] oPt = oPts1[i] vertexIndexList.extend([hPtC,hPtB,rPtB, rPtB,rPtC,hPtC]) vertexIndexList.extend([rPtB,rPtA,pPtA, pPtA,pPtB,rPtB]) vertexIndexList.extend([hPtB,hPtA,rPtA, rPtA,rPtB,hPtB]) vertexIndexList.extend([pPtB,pPtA,oPt]) # triangles on teeth for i in range(0, numTeeth): rPtA0 = rPts0[i*2] rPtB0 = rPts0[i*2 + 1] pPtA0 = pPts0[i*2] pPtB0 = pPts0[i*2 + 1] rPtA1 = rPts1[i*2] rPtB1 = rPts1[i*2 + 1] pPtA1 = pPts1[i*2] pPtB1 = pPts1[i*2 + 1] oPt0 = oPts0[i] oPt1 = oPts1[i] # triangles on one tooth vertexIndexList.extend([rPtA1, rPtA0, pPtA0, pPtA0, pPtA1, rPtA1]) vertexIndexList.extend([pPtA1, pPtA0, oPt0, oPt0, oPt1, pPtA1]) vertexIndexList.extend([rPtB0, rPtB1, pPtB1, pPtB1, pPtB0, rPtB0]) vertexIndexList.extend([pPtB0, pPtB1, oPt1, oPt1, oPt0, pPtB0]) # triangles on inner face for i in range(0, 2*numTeeth): hPtA0 = hPts0[i] hPtB0 = hPts0[(i + 1)%(2*numTeeth)] hPtA1 = hPts1[i] hPtB1 = hPts1[(i + 1)%(2*numTeeth)] vertexIndexList.extend([hPtA1,hPtB1,hPtB0, hPtB0,hPtA0,hPtA1]) return vertexIndexList except Exception as error: _ui.messageBox("calculateTriangles Failed : " + str(error)) return None # Builds a custom graphics mesh. def drawMesh(cgGroup): try: # Calculate mesh coordinates rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1, vecCoords, vecColors = calculateCoordinates(_numTeeth) coordinates = adsk.fusion.CustomGraphicsCoordinates.create(vecCoords) coordinates.colors = vecColors # Calculate mesh triangles vertexIndexList = calculateTriangles(_numTeeth, rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1) # Add Custom Graphics mesh normalVectors = [] normalIndexList = [] cgMesh = cgGroup.addMesh(coordinates, vertexIndexList, normalVectors, normalIndexList) return cgMesh except Exception as error: _ui.messageBox("drawMesh Failed : " + str(error)) return None def drawLines(cgGroup): try: rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1, vecCoords, vecColors = calculateCoordinates(_numTeeth) coordinates = adsk.fusion.CustomGraphicsCoordinates.create(vecCoords) vertexIndexList = calculateTriangles(_numTeeth, rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1) stripLen = calculateStripLen(_numTeeth) cgLines = cgGroup.addLines(coordinates, vertexIndexList, True, stripLen) if _lineStylePattern.selectedItem.name == 'Solid Line': cgLines.lineStylePattern = adsk.fusion.LineStylePatterns.continuousLineStylePattern elif _lineStylePattern.selectedItem.name == 'Center Line': cgLines.lineStylePattern = adsk.fusion.LineStylePatterns.centerLineStylePattern elif _lineStylePattern.selectedItem.name == 'Dashed Line': cgLines.lineStylePattern = adsk.fusion.LineStylePatterns.dashedLineStylePattern elif _lineStylePattern.selectedItem.name == 'Dot Line': cgLines.lineStylePattern = adsk.fusion.LineStylePatterns.dotLineStylePattern elif _lineStylePattern.selectedItem.name == 'Dashed Line': cgLines.lineStylePattern = adsk.fusion.LineStylePatterns.dashedLineStylePattern elif _lineStylePattern.selectedItem.name == 'Phantom Line': cgLines.lineStylePattern = adsk.fusion.LineStylePatterns.phantomLineStylePattern elif _lineStylePattern.selectedItem.name == 'Tracks Line': cgLines.lineStylePattern = adsk.fusion.LineStylePatterns.tracksLineStylePattern elif _lineStylePattern.selectedItem.name == 'ZigZag Line': cgLines.lineStylePattern = adsk.fusion.LineStylePatterns.zigzagLineStylePattern cgLines.weight = float(_lineStyleWeight.valueOne) cgLines.lineStyleScale = float(_lineStyleScale.valueOne) return cgLines except Exception as error: _ui.messageBox("drawLines Failed : " + str(error)) return None def drawPointSet(cgGroup): try: rPts0, hPts0, pPts0, oPts0, rPts1, hPts1, pPts1, oPts1, vecCoords, vecColors = calculateCoordinates(_numTeeth) coordinates = adsk.fusion.CustomGraphicsCoordinates.create(vecCoords) cgPoints = cgGroup.addPointSet(coordinates, [], adsk.fusion.CustomGraphicsPointTypes.UserDefinedCustomGraphicsPointType, _pointSetImage) return cgPoints except Exception as error: _ui.messageBox("drawPointSet Failed : " + str(error)) return None