A Recipe Specification (RecipeSpec) is an XML file that describes which views (section, elevation, and so on) are available for a given detail component and how those views are to be created and placed within the drawing.
Here is a simple example of a RecipeSpec.
<?xml version="1.0" encoding="UTF-8"?> <AecRecipeSpec defaultUnit="in"><Recipe idStr="side"><Label>Side</Label> <Implementation></Recipe><ObjectARX></Implementation> <Data><AppName>AecDtl50</AppName> <RcpFunc>AecDtlRcpColumnCapCCSide</RcpFunc></ObjectARX><Item idStr="block"></Data><AcadEntityProps></Item> <Item idStr="boundary"> </Item> <Item idStr="holes"> </Item> <Item idStr="hidden"><Layer ref="layerKey">THIN</Layer></AcadEntityProps><AcadEntityProps></Item><Layer ref="layerKey">FINE</Layer> <Linetype>HIDDEN</Linetype></AcadEntityProps><Recipe idStr="end"></AecRecipeSpec><Label>End</Label> <Implementation><ObjectARX></Implementation><AppName>AecDtl50</AppName> <RcpFunc>AecDtlRcpColumnCapCCEnd</RcpFunc></ObjectARX><Data></Recipe><Item idStr="block"><AcadEntityProps></Item><Layer ref="layerKey">THIN</Layer></AcadEntityProps><Item idStr="boundary"> </Item> <Item idStr="holes"> </Item></Data>
A RecipeSpec is composed of one or more Recipes. Each Recipe is responsible for creating a single view of the component. In the example above, the first Recipe creates a side view of the drawing, and the second creates an end view. When the component is inserted in a drawing, the user-configurable View setting on the Properties palette determines which recipe is used.
Each Recipe contains the following four major sections:
In short, the <Data> and <Controls> sections help define what the basic component looks like, and the <Options> section helps define how the component is placed. In many cases, you will not need an <Options> section, because the default behavior of the Jig is sufficient.
Each of these sections is described in more detail further on in this section.
Everything in the RecipeSpec that needs to be identifiable programmatically has an idStr attribute. The idStr value should never change and should be unique within the file (or at least within a given element type). The Rcp function will be expecting ID strings with certain values, so when writing a RecipeSpec, you need to know the implied contract from the Rcp function.
Elements with the tag <Label> or <Description> are intended to be translated. These will be displayed in the Properties palette and other user interface constructs, but will never be used to refer to anything and will never be referenced from the code (that is the job of the idStr).
Within the Recipe Spec, the value of an item appears between the element tags. It is taken as a literal value unless the ref attribute is specified. In this case, the value between the element tags is considered a lookup value and is used to retrieve the actual value.
ref [Optional]
Specifies that the value between the element tags is to be used as a lookup key. It can have one of the following values:
layerKey | (AutoCAD Architecture LayerKey) |
dbTable | (Column in the table from component database) |
control | (idStr of a <Control>) |
The dbTable reference will use the value as the column name within the size table for the current component. Consider the following two examples.
<Data><Item idStr="block"></Data><AcadBlockProps><BlockName dwgLib="dwgs/AecDtlLib_BlockTest.dwg">Jimbo</BlockName> <Scale>6.0</Scale></AcadBlockProps><AcadEntityProps></Item><Layer>DOOR</Layer></AcadEntityProps>
In the first case, the <Scale> and <Layer> values have been specified literally. This component, regardless of what row was selected in the database, will have a scale factor of 6.0. Likewise, regardless of what Layer Key style is current within AutoCAD Architecture, this component will go on the DOOR layer (not the layer assigned to the LayerKey “DOOR”).
<Data><Item idStr="block"></Data><AcadBlockProps><BlockName dwgLib="dwgs/AecDtlLib_BlockTest.dwg">Jimbo</BlockName> <Scale ref="dbTable">SCALE</Scale></AcadBlockProps><AcadEntityProps></Item><Layer ref="layerKey">DOOR</Layer></AcadEntityProps>
In this example, references were used to look up the values dynamically. The <Scale> will be set to the value in the SCALE column of the current row in the component’s size table. Likewise, the reference “DOOR” is the Layer Key to use to look up the Layer, not the actual Layer name itself. There is also a reference of type “control,” which lets you use the idStr of a control defined within the Recipe. The value of that control is then used as the actual value of the Element.
Each Recipe Spec has a default unit that applies to the entire XML file. Any unit-dependent value that appears within the XML file is automatically converted from the default unit to the current drawing unit when the value is retrieved from XML.
To specify the default unit, use the following syntax in the root node of the RecipeSpec.
<?xml version="1.0" encoding="UTF-8"?> <AecRecipeSpec defaultUnit="mm"><Recipe idStr="section"></AecRecipeSpec><….. omitted ….></Recipe>
The defaultUnit attribute must be one of the values: in, ft, mm, cm, dm, or m. If no value is speciifed, “in” is used by default.
In some cases, a simple hard conversion from Metric to Imperial (or vice versa) is not good enough. For instance, the <GapSpacing> between paver bricks should be a logical distance for each measurement system instead of an arbitrary distance created by a hard conversion. You can specify a unit-specific element by including the “unit” attribute, as in the following example.
<Data><Item idStr="block"><AcadEntityProps></Item><Layer ref="layerKey">THIN</Layer></AcadEntityProps><Item idStr="head"><Params></Item><Overhang unit="in">0.25</Overhang> <Overhang unit="mm">6.5</Overhang> <Depth unit="in">0.375</Depth> <Depth unit="mm">10.0</Depth></Params><Item idStr="tip"><Params></Item><Depth unit="in">0.0625</Depth> <Depth unit="mm">1.5</Depth></Params><Item idStr="shaft"/> <Item idStr="hidden"></Data><AcadEntityProps></Item><Linetype>HIDDEN2</Linetype> <!-- override the Linetype for hidden components --></AcadEntityProps>
In this case, different values are given depending upon whether the current drawing is Imperial or Metric.
The Implementation section can look like any of the following examples (<ObjectARX>, <VBA>, and <ManagedDotNet>):
<ObjectARX>
<Implementation><ObjectARX></Implementation><AppName>AecDtl50</AppName> <RcpFunc>AecDtlRcpColumnCapCCSide</RcpFunc></ObjectARX>
Where... | Is... |
---|---|
AppName | the logical appname that appears in the Registry for an ObjectARX application. |
<RcpFunc> | the name of a Recipe function that is implemented within the ObjectARX module and is registered using the AecRcpBase framework object AecRcpFuncTable. The function signature should take no arguments and must return a value of type RcpStatus |
<VBA>
<Implementation><VBA projectName="M:/Juneau/bin/TestDtl_VBA.dvb" macroName="DrawRectangle"/></Implementation>
Where... | Is... |
---|---|
projectName | the pathname of the VBA project file that contains the macro. This can be a full pathname, a partial path relative to the location of the XML file, or it can use the “dirKey” attribute to specify a path from the DirKeys table in the component database. |
macroName | The VBA macro name to call. This macro should take no arguments and returns no value. It needs to call the function aecDtlSetRcpReturnStatus() before returning. |
<ManagedDotNet>
<Implementation><ManagedDotNet moduleName="M:/Juneau//bin/TestDtl_VB.dll" funcRcp="DrawRectangle"/></Implementation>
Where... | Is... |
---|---|
moduleName | the DLL pathname where the function exists. This can be a full pathname, a partial path relative to the location of the XML file, or it can use the “dirKey” attribute to specify a path from the DirKeys table in the component database. |
funcRcp | the name of a Recipe function that is implemented within the ObjectARX module and is registered usingn the AecRcpBase framework object AecRcpFuncTable. The function signature should take no arguments and must return a value of type RcpStatus. |
The Controls section contains a list of control definitions that will be added to the Properties palette, or prompted for on the command line. All controls must have an idStr attribute that the program can use to reference it. It must also have a <Label> element to display in the Properties palette. Optionally, controls can have a <Description> element to use as a “tip” string in the bottom of the Properties palette when this control has focus. If no <Description> element is present, the <Label> element will be used.
Each specific type of control is listed below.
<ComboBox>
This type of control is used to present a list of choices. It is a simple single-selection list.
<ComboBox idStr="head"><Label>Head type</Label> <Description>Head type to use for bolt</Description> <ComboBoxValue idStr="blkHeadHex"><Label>Hex</Label></ComboBoxValue> <ComboBoxValue idStr="blkHeadSq"><Label>Square</Label></ComboBoxValue><ComboBoxValue idStr="blkHeadRnd"></ComboBox><Label>Round</Label></ComboBoxValue> <Default>blkHeadHex</Default>
A ComboBox has a list of <ComboBoxValue> nodes that simply specify an idStr used to uniquely identify that item in the list. Each <ComboBoxValue> must also have a <Label> element to display within the list.
If the <ComboBox> has a <Default> element, the listed idStr will be used as the default <ComboBoxValue>. If no <Default> element is present, the first <ComboBoxValue> will be used as the default.
<Default> [Optional]
The <ComboBoxValue> idStr to use as the default selection in the list.
<CheckBox>
This type of control is used for Boolean values.
<CheckBox idStr="doStagger"><Label>Stagger columns</Label> <Default>0</Default></CheckBox>
It can have the following elements:
Element | Description |
---|---|
<Default> [Optional] | The default Boolean value. It can be specified as any of the following values: “1”, “0”, “true”, or “false”. |
<EditBoxAngle>
This type of control corresponds to the AecEditBoxAngle class in AutoCAD Architecture and has the same basic options.
<EditBoxAngle idStr="slope"><Label>Slope angle</Label> <Default>0.0</Default> <Validation>range</Validation> <RangeLow>-45.0</RangeLow> <RangeHigh>45.0</RangeHigh></EditBoxAngle>
It can have the following elements:
Element | Description |
---|---|
<Default> [Optional] | The default angle value. This value is specified in degrees. |
<Validation> [Optional] | Specifies what type of validation rule is used. Possible values are: “Any”, “NoZero”, or “Range”. If not specified, “Any” is used by default. |
<RangeLow> [Optional, except when validation="Range"] | The lower end of the range of allowable values. |
<RangeHigh> [Optional, except when validation="Range"] | The high end of the range of allowable values. |
<EditBoxDistance>
This type of control corresponds to the AecEditBoxDist class in AutoCAD Architecture and has the same basic options.
<EditBoxDistance idStr="rowSpacing" unitDep="true"><Label>Y-Axis</Label> <Description>Spacing between bolts in Y direction</Description> <Default>2.0</Default> <Validation>NoNeg</Validation></EditBoxDistance>
It can have the following attributes:
Attribute | Description |
---|---|
unitDep [Optional] | This attribute indicates whether the value of this control needs to be scaled to the current unit in the drawing. A value of “1” or “true” will cause the value to be scaled. A value of “0” or “false” will leave the value as specified. |
The <EditBoxDistance> control can have the following elements:
Element | Description |
---|---|
<Default> [Optional] | The default distance value. |
<Validation> [Optional] | Specifies what type of validation rule is used. Possible values are: “Any”, “NoNeg”, “NoZero”, or “Range”. If not specified, “Any” is used by default. |
<RangeLow> [Optional, except when validation="Range”] | The lower end of the range of allowable values. |
<RangeHigh> [Optional, except when validation="Range"] | The high end of the range of allowable values. |
<EditBoxInt>
This type of control corresponds to the AecEditBoxDist class in AutoCAD Architecture (with precision set to “0”) and has the same basic options.
<EditBoxInteger idStr="cols"><Label>Columns</Label> <Description>Number of bolts in Y direction</Description> <Default>2</Default> <Validation>NoNegNoZero</Validation></EditBoxInteger>
It can have the following elements:
Element | Description |
---|---|
<Default> [Optional] | The default integer value. |
<Validation> [Optional] | Specifies what type of validation rule is used. Possible values are: “Any”, “NoNeg”, “NoZero”, “NoNegNoZero”, or “Range”. If not specified, “Any” is used by default. |
<RangeLow> [Optional, except when validation="Range"] | The lower end of the range of allowable values. |
<RangeHigh> [Optional, except when validation="Range"] | The high end of the range of allowable values. |
<Picture>
A Picture control is used to display a static image in the Properties palette. It has a list of <PictureValue> elements that may be used to fill the Picture control under certain conditions.
<Picture idStr="end_conditions_illustration" rowHeight="5"><Label>End conditions illustration</Label> <Default>plain_plain</Default> <Varies>plain_plain</Varies><PictureValue idStr="regular_regular" idFile="Images/cmu_regular_regular.png"></Picture><ParentControl idRef="leftEndStyle" idStr="regular"/> <ParentControl idRef="rightEndStyle" idStr="regular"/></PictureValue> <PictureValue idStr="regular_plain" idFile="Images/cmu_regular_plain.png"><ParentControl idRef="leftEndStyle" idStr="regular"/> <ParentControl idRef="rightEndStyle" idStr="plain"/></PictureValue>
A Picture control can have the following attributes:
Attribute | Description |
---|---|
rowHeight [Optional] | The number of rows that this control should occupy in the Properties palette. The default value is 3. |
A Picture control can have the following elements:
Element | Description |
---|---|
<Default> [Optional] | The idStr of the <PictureValue> to show by default. |
<Validation> [Optional] | The idStr of the <PictureValue> to show under a multiple selection condition in the Properties palette. If not specified, the <Default> is used. |
When the same control is used by different Recipes within the same RecipeSpec, you can define them in the <ControlDefs> section and then reference them within the <Controls> section of a specific Recipe.
<ControlRef idRef="head"/>
Simply use the idRef attribute to refer to the idStr of the Control that is defined in the <ControlDefs> section.
The following example shows a control defined at the <RecipeSpec> level that can be referenced from any <Recipe>. It also shows a control that is defined local to a specific <Recipe>.
<?xml version="1.0" encoding="UTF-8"?> <AecRecipeSpec defaultUnit="in"><ControlDefs><CheckBox idStr="hatchBlock"></ControlDefs><Label>Hatch block</Label> <Description>Specifies whether to hatch the block. </Description> <Default>1</Default></CheckBox><Recipe idStr="section"> <Label>Section</Label> <Implementation><ObjectARX></Implementation> <Controls><AppName>AecDtl50</AppName> <RcpFunc>ConcreteUnit2CoreSection</RcpFunc></ObjectARX><ControlRef idRef="hatchBlock"/> <CheckBox idStr="hatchCores"></Controls><Label>Grout fill cores</Label> <Description>Specifies whether to hatch the cores solid with grout.</Description> <Default>0</Default></CheckBox>
This section has customization data that is used by the Rcp function. This includes things like simple Layer/Color/Linetype properties, hatch pattern information, spacing parameters, and so on. It is the Rcp function’s responsibility to look back to this section and find any data that may be relevant.
There is an implicit contract between the Rcp function and the RecipeSpec. The Rcp function can decide what is allowed to be in the <Data> section, but it will usually contain a set of commonly seen elements. You can put virtually anything in the <Data> section, but if the Rcp function is not expecting it, it will be ignored.
The data within this section is divided into <Item> sections. Each Item section can contain virtually anything that the Recipe dictates. An Item section usually defines the data for a portion of the overall component, such as “boundary”, “infill”, and “hidden”.
The following standard types of information appear regularly within an Item section:
These standard information elements are described individually in the following sections.
<AcadEntityProps>
This Element specifies the Layer/Color/Linetype properties of an entity. All the items are optional and are only used if specifically listed. If they are not listed, the Rcp function should use either ByBlock or ByLayer (or whatever the appropriate setting is) as the default. Here are four examples:
<AcadEntityProps><Layer ref="layerKey">FINE</Layer> <Linetype>HIDDEN</Linetype></AcadEntityProps> <AcadEntityProps><Layer>Jimbo</Layer> <ColorIndex>1</ColorIndex> <Linetype>DASHED</Linetype> <LinetypeScale>3.0</LinetypeScale> <Lineweight>53</Lineweight></AcadEntityProps> <AcadEntityProps><Layer>Jimbo</Layer> <Color></AcadEntityProps><Red>73</Red> <Green>179</Green> <Blue>157</Blue></Color> <Linetype>DASHED</Linetype>
The following Elements can be specified within <AcadEntityProps>:
<AcadBlockProps>
This Element specifies the properties of a block reference. Here are a few examples:
<AcadBlockProps><BlockName dwgLib="dwgs/AecDtlLib_BlockTest.dwg"</AcadBlockProps> <AcadBlockProps><ScaleX ref="dbTable">SCALE_X</ScaleX> <ScaleY ref="dbTable">SCALE_Y</ScaleY> <ScaleZ ref="dbTable">SCALE_Z</ScaleZ>remapLayers="true">Jimbo</BlockName><BlockName dwgLib="dwgs/AecDtlLib_BlockTest.dwg"</AcadBlockProps> <AcadBlockProps><Scale>6.0</Scale> <!-- This one uses uniform scale-->remapLayers="true">Jimbo</BlockName><BlockName dwgLib="dwgs/AecDtlLib_TrenchDrains.dwg" remapLayers="true"</AcadBlockProps>ref="dbTable">R_BLOCK</BlockName>
The following Elements can be specified within <AcadBlockProps>:
The <BlockName> element tells the name of the block definition to use and can include the following attributes providing instructions on how to load the block if it is not found in the current drawing:
Attribute | Description |
---|---|
dwgLib [Optional] | The pathname of the library DWG file where the block is defined. If a relative path is specified, it is relative to the XML RecipeSpec’s location. |
dirKey [Optional] | A directory key to look up in the detail component database. The dwgLib attribute value is then appended to the dirKey value to form the full pathname. |
remapLayers [Optional] | A Boolean value specifying whether the layers for entities within the block are to be searched for LayerKeys. If a LayerKey is found as the value of the Layer, the Layer is remapped to that LayerKey. This value should only be specified as true if you know for certain that there are LayerKeys defined within the block. |
ref [Optional] | If specified, the block name is a lookup value to find the real block name. |
If <Scale> is used, it is a uniform scale for each axis of the block reference.
<AcadMInsertProps>
This element specifies the additional values that an MInsert can have above and beyond a Block Reference. Anything common to both MInserts and Block References will thus appear in the <AcadBlockProps> section.
<AcadMInsertProps><Rows>2</Rows> <RowSpacing>5.0</RowSpacing> <Columns>3</Columns> <ColumnSpacing>6.0</ColumnSpacing></AcadMInsertProps> <AcadMInsertProps><Rows ref="dbTable">ROWS</Rows> <RowSpacing>5.0</RowSpacing> <Columns ref="dbTable">COLUMNS</Columns> <ColumnSpacing>6.0</ColumnSpacing></AcadMInsertProps>
The following Elements can be specified within <AcadMInsertProps>:
<AcadHatchProps>
This Element specifies the properties of a hatch. Here are a few examples:
<AcadHatchProps><HatchAlias>brick</HatchAlias></AcadHatchProps> <AcadHatchProps><HatchAlias ref="dbTable">PAT_ALIAS</HatchAlias></AcadHatchProps> <AcadHatchProps><PatternName>Escher</PatternName> <PatternScale>4.0</PatternScale> <PatternAngle>45.0</PatternAngle></AcadHatchProps>
The following Elements can be specified within < AcadHatchProps >:
Element | Description |
---|---|
<HatchAlias> [Optional] | The name of an Alias from the Detail Component database’s Hatches table. This table is used so that you can centrally define the Pattern, Scale, and Angle for representative materials used throughout the database. Most RecipeSpecs will use a Hatch Alias to define all the parameters of the Hatch. However, you can specify these values directly by using the other elements. |
<PatternType> [Optional] | Possible values are: “PreDefined” (the default), “User”, or “Custom”. |
<PatternName> [Optional] | If the <PatternName> specified (or indirectly referenced from <HatchAlias>) does not exist, the pattern “ANSI31” is used. |
<PatternScale> [Optional] | |
<PatternMultiplier> [Optional] | |
<PatternAngle> [Optional] | |
<PatternDouble> [Optional] | |
<PatternSpace> [Optional] |
<Params>
This Element specifies the parameters specific to this particular Recipe. These are typically values that the Recipe needs, but that are not hardwired into the code, and thus are customizable. Here are a few examples:
<Item idStr="boundary"><Params></Item> <Item idStr="boundary"><Tongue>0.125</Tongue> <GrooveSpacing>0.03125</GrooveSpacing></Params><Params></Item><Chamfer>0.5</Chamfer></Params>
The Element names are defined by the Rcp function itself and must be known in advance of editing them in the Recipe Spec.
This section provides customization data that is used by the placement phase (Jig) of the Rcp function. In most cases, Recipe functions divide their labor into two phases:
The job of placing the component is usually handled by a standard Jig that may be controlled by elements specified in the <Options> section. You must, of course, have advanced knowledge of which Jig and JigEnt are used by a Recipe function in order to take advantage of this.
The example below is from the Brick Pavers component group. It uses the LinearArrayJig to repeat a row of blocks at a specified spacing.
<?xml version="1.0" encoding="UTF-8"?> <AecRecipeSpec defaultUnit="in"><Recipe idStr="section"></AecRecipeSpec><Label>Section</Label> <Implementation></Recipe><ObjectARX logicalAppname="AecDtl50" funcRcp="AecDtlRcpUnitPaver"/></Implementation> <Controls><CheckBox idStr="doHatch"></Controls> <Data><Label>Hatch item</Label> <Default>1</Default></CheckBox><Item idStr="block"></Data> <Options><AcadEntityProps></Item> <Item idStr="boundary"><Layer ref="layerKey">MED</Layer></AcadEntityProps><Params></Item> <Item idStr="infill"><Chamfer>0.0</Chamfer></Params><AcadHatchProps></Item><HatchAlias>brick</HatchAlias></AcadHatchProps> <AcadEntityProps><Layer ref="layerKey">HATCH</Layer></AcadEntityProps><JigEnt></Options><GapSpacing>0.25</GapSpacing></JigEnt> <Jig><PromptCount>Number of courses</PromptCount></Jig>
In the <Options> section, it tells the JigEnt to put a ¼" spacing between each paver, and it changes the prompt string for one of the prompts issued by the Jig.