Based on the example "circuit" and it's use of Data Definition Blocks to read user data linkages, I went to try the same approach in one of my tools. It's not working for me (both mdlLinkage_extractUsingDescr() and/or mdlCnv_bufferFromFileFormat() ). I tried to use parts from that example to read the attributes on a "wire" line drawn into my model. I *think* I've left out one step, but I can't figure out where. THe V8 docs make no mention of how to use createDataDef() and I'm thinking that's where my issue is. The mdlLinkage_extractUsingDescr() works when I DONT supply a data definition block id. Below are the parts related to this process:
header file:
#define DATADEFID_CIRCUITLINKAGE_WIRE 2 #define SIGNATUREID_CIRCUITPROJECT 900 typedef struct wireinfo { int typeID; int circuitID; int gauge; int colorCode; }WireInfo; typedef struct wireLinkage { LinkageHeader linkHdr; WireInfo info; } WireLinkage;
from the type file
#pragma packedLittleEndian #include <datadef.h> #include "mdl.h" createDataDef (wireinfo, DATADEFID_CIRCUITLINKAGE_WIRE); publishStructures ( wireinfo );
from the .mki file
maRscs = $(o)$(appName).mi \ $(o)$(appName)Type.rsc \ $(baseDir)$(appName)Type.r : $(baseDir)$(appName)Type.mt $(o)$(appName)Type.rsc : $(baseDir)$(appName)Type.r
from the .cpp file
// Get the resource file mdlResource_openFile(&rfHandle, NULL, FALSE); ... void *nextLink = NULL; WireLinkage uDataWire; nextLink = mdlLinkage_extractFromElement (&uDataWire, elemP->GetElementCP(),SIGNATUREID_CIRCUITPROJECT, DATADEFID_CIRCUITLINKAGE_WIRE, NULL, NULL, NULL); printf("nextLink=%08x\n",nextLink );
Is there anything else required? When I have the "wire" element in my test app, "nextLink" is NULL. When I use the "circuit" example, the same element has a non-NULL nextLink value.
Thanks,
Bruce
Michael Stark said:I think you have to keep the publishStructures and createDataDef in the .mt file
Sorry I wasn't more clear, but they are in the .mt file and I do create the .r from the .mt and then create a .rsc from the .r intermediate file via the .mki file.
Very werid, even when I restore this publishStructures line in my test .mt file, the result is always correct. Can't get NULL. But I am sure in my first try, I really got the same result as Bruce. Please use my DGN and basic project to test.
circuit_test.dgn
basic.zip
The example file and code DID work. However, I'm seeing that when you attempt to read the linkage in a "view substitution" function, it does not. I added a simple view substitution function with mdlView_setSubstitutionElemFunc(), and in the provided function I then called mdlLinkage_extractFromElement() using the Data Definition ID and the passed in ElemHandleCP. In there, the mdlLinkage_extract function fails when using a Data Definition ID. If you don't utilize it (i.e. keep the linkage in file format), the mdlLinkage_extract function works....
Unknown said:What exactly are you doing in your view substitution function?
I want to control the display of elements with certain UserDataLinkages on them. Part of that linkage is a field that, when set, tells me the element should be allowed to display. When not set, I want to not display it. I've been using mdlLinkage_extractxx() without a data definition block id, just providing a callback function to process the mdlLinkage_extract elements (in the view substitution function) that have my User Data Linkage. In that callback function I manually convert the format into my struct so I can make the determination of display/no display. Now I'm looking at the need to change the length of my linkages to hold additional information, and that means I'll have >1 linkage size to deal with. I thought by using a Data Definition Block ID, that I could ease the pain of decoding from the file format to the internal format. But for some reason the use of the ID with mdlLinkage_extract doesn't seem to work when called inside the view substitution function.
Here is the view substitution function:
Public SubstituteElemStatus viewSubstituteElemFunc ( MSElementDescrH newEdPP, // <= output if element being replaced (Brien Bastings "replacement element wont be persistent" int* priorityP, // <= priority if element being deferred IViewportP viewPortP, // => the viewport in which the element is being displayed. DrawPurpose drawPurpose, // => the purpose for which the element is being displayed. IViewContextP context, // => view context (NOTE: this value is currently not useful for application callers and is provided for future compatibility). bool allowDefer, // => whether element can be deferred ElemHandleCP elemP // => the element being displayed. ) { SubstituteElemStatus substituteStatus=SUBSTELEM_STATUS_Normal; if ( !elemP->IsPersistent() ) { printf("Element NOT persistent\n"); return SUBSTELEM_STATUS_Normal; } void *nextLink = NULL; WireLinkage uDataWire; nextLink = mdlLinkage_extractFromElement (&uDataWire, elemP->GetElementCP(),SIGNATUREID_CIRCUITPROJECT, /*NULL*/ DATADEFID_CIRCUITLINKAGE_WIRE, NULL, NULL, NULL); if ( nextLink ) { printf("viewSubstituteElemFunc, nextLink=%08x, type=%d, circuitID=%d, gauge=%d, colorCode=%d\n", nextLink , uDataWire.info.typeID, uDataWire.info.circuitID, uDataWire.info.gauge, uDataWire.info.colorCode ); } else { printf("viewSubstituteElemFunc, nextLink=%08x\n",nextLink ); } return substituteStatus; }
and here is the OnElementModify() from my MstnElementSetTool:
virtual StatusInt OnElementModify (EditElemHandleR elHandle) override { void *nextLink = NULL; WireLinkage uDataWire; nextLink = mdlLinkage_extractFromElement (&uDataWire, elHandle.GetElementCP(),SIGNATUREID_CIRCUITPROJECT, /*NULL*/ DATADEFID_CIRCUITLINKAGE_WIRE, NULL, NULL, NULL); if ( nextLink ) { printf("OnElementModify, nextLink=%08x, type=%d, circuitID=%d, gauge=%d, colorCode=%d\n", nextLink , uDataWire.info.typeID, uDataWire.info.circuitID, uDataWire.info.gauge, uDataWire.info.colorCode ); } return ERROR; } // Do something...